#ifndef LLVM_LIBC_SRC_STDLIB_STRFROM_UTIL_H
#define LLVM_LIBC_SRC_STDLIB_STRFROM_UTIL_H
#include "src/__support/CPP/type_traits.h"
#include "src/__support/macros/config.h"
#include "src/__support/str_to_integer.h"
#include "src/stdio/printf_core/converter_atlas.h"
#include "src/stdio/printf_core/core_structs.h"
#include "src/stdio/printf_core/writer.h"
#include <stddef.h>
namespace LIBC_NAMESPACE_DECL {
namespace internal {
template <typename T>
using storage_type = typename fputil::FPBits<T>::StorageType;
template <typename T>
printf_core::FormatSection parse_format_string(const char *__restrict format,
T fp) {
printf_core::FormatSection section;
size_t cur_pos = 0;
[[maybe_unused]] double new_fp;
bool t_is_single_prec_type = cpp::is_same<T, float>::value;
if (t_is_single_prec_type)
new_fp = (double)fp;
if (format[cur_pos] == '%') {
section.has_conv = true;
++cur_pos;
section.precision = -1;
if (format[cur_pos] == '.') {
++cur_pos;
section.precision = 0;
if (internal::isdigit(format[cur_pos])) {
auto result = internal::strtointeger<int>(format + cur_pos, 10);
section.precision += result.value;
cur_pos += result.parsed_len;
}
}
section.conv_name = format[cur_pos];
switch (format[cur_pos]) {
case 'a':
case 'A':
if (t_is_single_prec_type)
section.conv_val_raw = cpp::bit_cast<storage_type<double>>(new_fp);
else
section.conv_val_raw = cpp::bit_cast<storage_type<T>>(fp);
break;
case 'e':
case 'E':
case 'f':
case 'F':
case 'g':
case 'G':
section.conv_val_raw = cpp::bit_cast<storage_type<T>>(fp);
break;
default:
section.has_conv = false;
while (format[cur_pos] != '\0')
++cur_pos;
break;
}
if (format[cur_pos] != '\0')
++cur_pos;
} else {
section.has_conv = false;
while (format[cur_pos] != '\0')
++cur_pos;
}
section.raw_string = {format, cur_pos};
return section;
}
template <typename T>
int strfromfloat_convert(printf_core::Writer *writer,
const printf_core::FormatSection §ion) {
if (!section.has_conv)
return writer->write(section.raw_string);
auto res = static_cast<storage_type<T>>(section.conv_val_raw);
fputil::FPBits<T> strfromfloat_bits(res);
if (strfromfloat_bits.is_inf_or_nan())
return convert_inf_nan(writer, section);
switch (section.conv_name) {
case 'f':
case 'F':
return convert_float_decimal_typed(writer, section, strfromfloat_bits);
case 'e':
case 'E':
return convert_float_dec_exp_typed(writer, section, strfromfloat_bits);
case 'a':
case 'A':
return convert_float_hex_exp(writer, section);
case 'g':
case 'G':
return convert_float_dec_auto_typed(writer, section, strfromfloat_bits);
default:
return writer->write(section.raw_string);
}
return -1;
}
}
}
#endif