#include "src/stdio/scanf_core/float_converter.h"
#include "src/__support/CPP/limits.h"
#include "src/__support/char_vector.h"
#include "src/__support/ctype_utils.h"
#include "src/__support/macros/config.h"
#include "src/stdio/scanf_core/converter_utils.h"
#include "src/stdio/scanf_core/core_structs.h"
#include "src/stdio/scanf_core/reader.h"
#include <stddef.h>
namespace LIBC_NAMESPACE_DECL {
namespace scanf_core {
int convert_float(Reader *reader, const FormatSection &to_conv) {
CharVector out_str = CharVector();
bool is_number = false;
size_t max_width = cpp::numeric_limits<size_t>::max();
if (to_conv.max_width > 0) {
max_width = to_conv.max_width;
}
char cur_char = reader->getc();
if (cur_char == '+' || cur_char == '-') {
if (!out_str.append(cur_char)) {
return ALLOCATION_FAILURE;
}
if (out_str.length() == max_width) {
return MATCHING_FAILURE;
} else {
cur_char = reader->getc();
}
}
static constexpr char DECIMAL_POINT = '.';
static const char inf_string[] = "infinity";
if (to_lower(cur_char) == inf_string[0]) {
size_t inf_index = 0;
for (; inf_index < sizeof(inf_string) && out_str.length() < max_width &&
to_lower(cur_char) == inf_string[inf_index];
++inf_index) {
if (!out_str.append(cur_char)) {
return ALLOCATION_FAILURE;
}
cur_char = reader->getc();
}
if (inf_index == 3 || inf_index == sizeof(inf_string) - 1) {
write_float_with_length(out_str.c_str(), to_conv);
return READ_OK;
} else {
return MATCHING_FAILURE;
}
}
static const char nan_string[] = "nan";
if (to_lower(cur_char) == nan_string[0]) {
size_t nan_index = 0;
for (; nan_index < sizeof(nan_string) && out_str.length() < max_width &&
to_lower(cur_char) == nan_string[nan_index];
++nan_index) {
if (!out_str.append(cur_char)) {
return ALLOCATION_FAILURE;
}
cur_char = reader->getc();
}
if (nan_index == sizeof(nan_string) - 1) {
write_float_with_length(out_str.c_str(), to_conv);
return READ_OK;
} else {
return MATCHING_FAILURE;
}
}
int base = 10;
if (cur_char == '0') {
is_number = true;
if (!out_str.append(cur_char)) {
return ALLOCATION_FAILURE;
}
if (out_str.length() == max_width) {
write_float_with_length(out_str.c_str(), to_conv);
return READ_OK;
} else {
cur_char = reader->getc();
}
if (to_lower(cur_char) == 'x') {
base = 16;
if (!out_str.append(cur_char)) {
return ALLOCATION_FAILURE;
}
if (out_str.length() == max_width) {
write_float_with_length(out_str.c_str(), to_conv);
return READ_OK;
} else {
cur_char = reader->getc();
}
}
}
const char exponent_mark = ((base == 10) ? 'e' : 'p');
bool after_decimal = false;
while (out_str.length() < max_width) {
if (internal::isalnum(cur_char) &&
internal::b36_char_to_int(cur_char) < base) {
is_number = true;
if (!out_str.append(cur_char)) {
return ALLOCATION_FAILURE;
}
cur_char = reader->getc();
} else if (cur_char == DECIMAL_POINT && !after_decimal) {
after_decimal = true;
if (!out_str.append(cur_char)) {
return ALLOCATION_FAILURE;
}
cur_char = reader->getc();
} else {
break;
}
}
if (to_lower(cur_char) == exponent_mark) {
if (!out_str.append(cur_char)) {
return ALLOCATION_FAILURE;
}
if (out_str.length() == max_width) {
return MATCHING_FAILURE;
} else {
cur_char = reader->getc();
}
if (cur_char == '+' || cur_char == '-') {
if (!out_str.append(cur_char)) {
return ALLOCATION_FAILURE;
}
if (out_str.length() == max_width) {
return MATCHING_FAILURE;
} else {
cur_char = reader->getc();
}
}
if (!internal::isdigit(cur_char)) {
return MATCHING_FAILURE;
}
while (internal::isdigit(cur_char) && out_str.length() < max_width) {
if (!out_str.append(cur_char)) {
return ALLOCATION_FAILURE;
}
cur_char = reader->getc();
}
}
reader->ungetc(cur_char);
if (!is_number) {
return MATCHING_FAILURE;
}
write_float_with_length(out_str.c_str(), to_conv);
return READ_OK;
}
}
}