Further tweaking.

This commit is contained in:
Daniel Lemire 2021-01-08 10:09:26 -05:00
parent 192b271c12
commit cf1a4ec2f5

View File

@ -83,11 +83,10 @@ parsed_number_string parse_number_string(const char *p, const char *pend, chars_
++p; ++p;
} }
const char *const end_of_integer_part = p; const char *const end_of_integer_part = p;
int64_t digit_count = int64_t(end_of_integer_part - start_digits);
int64_t exponent = 0; int64_t exponent = 0;
if ((p != pend) && (*p == '.')) { if ((p != pend) && (*p == '.')) {
++p; ++p;
const char *first_after_period = p;
#if FASTFLOAT_IS_BIG_ENDIAN == 0 #if FASTFLOAT_IS_BIG_ENDIAN == 0
// Fast approach only tested under little endian systems // Fast approach only tested under little endian systems
if ((p + 8 <= pend) && is_made_of_eight_digits_fast(p)) { if ((p + 8 <= pend) && is_made_of_eight_digits_fast(p)) {
@ -104,16 +103,13 @@ parsed_number_string parse_number_string(const char *p, const char *pend, chars_
++p; ++p;
i = i * 10 + digit; // in rare cases, this will overflow, but that's ok i = i * 10 + digit; // in rare cases, this will overflow, but that's ok
} }
exponent = first_after_period - p; exponent = end_of_integer_part + 1 - p;
digit_count -= exponent;
} }
// we must have encountered at least one integer! // we must have encountered at least one integer!
if ((start_digits == p) || ((start_digits == p - 1) && (*start_digits == '.') )) { if (digit_count == 0) {
return answer; return answer;
} }
// digit_count is the exact number of digits.
int32_t digit_count =
int32_t(p - start_digits); // used later to guard against overflows
if(exponent > 0) {digit_count--;}
int64_t exp_number = 0; // explicit exponential part int64_t exp_number = 0; // explicit exponential part
if ((fmt & chars_format::scientific) && (p != pend) && (('e' == *p) || ('E' == *p))) { if ((fmt & chars_format::scientific) && (p != pend) && (('e' == *p) || ('E' == *p))) {
const char * location_of_e = p; const char * location_of_e = p;
@ -155,18 +151,16 @@ parsed_number_string parse_number_string(const char *p, const char *pend, chars_
// of a 64-bit integer. However, this is uncommon. // of a 64-bit integer. However, this is uncommon.
// //
// We can deal with up to 19 digits. // We can deal with up to 19 digits.
if (((digit_count > 19))) { // this is uncommon if (digit_count > 19) { // this is uncommon
// It is possible that the integer had an overflow. // It is possible that the integer had an overflow.
// We have to handle the case where we have 0.0000somenumber. // We have to handle the case where we have 0.0000somenumber.
// We need to be mindful of the case where we only have zeroes... // We need to be mindful of the case where we only have zeroes...
// E.g., 0.000000000...000. // E.g., 0.000000000...000.
const char *start = start_digits; const char *start = start_digits;
while ((start != pend) && (*start == '0' || *start == '.')) { while ((start != pend) && (*start == '0' || *start == '.')) {
if(*start == '.') { digit_count++; } // We will subtract it again later. if(*start == '0') { digit_count --; }
start++; start++;
} }
// We over-decrement by one when there is a decimal separator
digit_count -= int(start - start_digits);
if (digit_count > 19) { if (digit_count > 19) {
answer.too_many_digits = true; answer.too_many_digits = true;
// Let us start again, this time, avoiding overflows. // Let us start again, this time, avoiding overflows.
@ -188,7 +182,7 @@ parsed_number_string parse_number_string(const char *p, const char *pend, chars_
} }
exponent = first_after_period - p + exp_number; exponent = first_after_period - p + exp_number;
} }
// We have now corrected both exponent and i, to a truncated value. // We have now corrected both exponent and i, to a truncated value
} }
} }
answer.exponent = exponent; answer.exponent = exponent;