This commit is contained in:
Maya Warrier 2023-03-29 02:20:36 -04:00
parent 3cafcca2ff
commit b6acf38a2e
2 changed files with 7 additions and 8 deletions

View File

@ -99,7 +99,7 @@ struct parsed_number_string {
const char *lastmatch{nullptr}; const char *lastmatch{nullptr};
bool negative{false}; bool negative{false};
bool valid{false}; bool valid{false};
bool is_64bit_uint{false}; bool is_64bit_int{false};
bool too_many_digits{false}; bool too_many_digits{false};
// contains the range of the significant digits // contains the range of the significant digits
byte_span integer{}; // non-nullable byte_span integer{}; // non-nullable
@ -210,6 +210,7 @@ parsed_number_string parse_number_string(const char *p, const char *pend, parse_
answer.lastmatch = p; answer.lastmatch = p;
answer.valid = true; answer.valid = true;
answer.is_64bit_int = (p == end_of_integer_part);
// If we frequently had to deal with long strings of digits, // If we frequently had to deal with long strings of digits,
// we could extend our code by using a 128-bit integer instead // we could extend our code by using a 128-bit integer instead
@ -226,16 +227,15 @@ parsed_number_string parse_number_string(const char *p, const char *pend, parse_
if(*start == '0') { digit_count --; } if(*start == '0') { digit_count --; }
start++; start++;
} }
constexpr uint64_t minimal_twenty_digit_integer{10000000000000000000}; constexpr uint64_t minimal_twenty_digit_integer{10000000000000000000ULL};
// maya: A 64-bit number may have up to 20 digits, not 19! // maya: A 64-bit number may have up to 20 digits, not 19!
// If we're parsing ints, preserve accuracy up to 20 digits instead // If we're parsing ints, preserve accuracy up to 20 digits instead
// of converting them to the closest floating point value. // of converting them to the closest floating point value.
answer.too_many_digits = rules == parse_rules::json_rules && parse_ints ? answer.too_many_digits = rules == parse_rules::json_rules && parse_ints && answer.is_64bit_int ?
answer.is_integer && (digit_count > 20 || i < minimal_twenty_digit_integer) : (digit_count > 20 || i < minimal_twenty_digit_integer) : digit_count > 19;
digit_count > 19;
if (answer.too_many_digits) { if (answer.too_many_digits) {
answer.is_64bit_uint = false; answer.is_64bit_int = false;
// Let us start again, this time, avoiding overflows. // Let us start again, this time, avoiding overflows.
// We don't need to check if is_integer, since we use the // We don't need to check if is_integer, since we use the
// pre-tokenized spans from above. // pre-tokenized spans from above.
@ -260,7 +260,6 @@ parsed_number_string parse_number_string(const char *p, const char *pend, parse_
} }
// We have now corrected both exponent and i, to a truncated value // We have now corrected both exponent and i, to a truncated value
} }
else answer.is_64bit_uint = (p == end_of_integer_part);
} }
answer.exponent = exponent; answer.exponent = exponent;
answer.mantissa = i; answer.mantissa = i;

View File

@ -27,7 +27,7 @@ struct parse_options {
constexpr explicit parse_options( constexpr explicit parse_options(
chars_format fmt = chars_format::general, chars_format fmt = chars_format::general,
parse_rules rules = parse_rules::std_rules, parse_rules rules = parse_rules::std_rules,
bool parse_ints = false, char dot = '.', ) bool parse_ints = false, char dot = '.')
: format(fmt), rules(rules), parse_ints(parse_ints), decimal_point(dot) {} : format(fmt), rules(rules), parse_ints(parse_ints), decimal_point(dot) {}
/** Which number formats are accepted */ /** Which number formats are accepted */