mirror of
https://github.com/fastfloat/fast_float.git
synced 2025-12-06 16:56:57 +08:00
* fix errors in the parse_number_string.
This commit is contained in:
parent
88b3887b52
commit
563648f76d
@ -260,6 +260,7 @@ enum class parse_error {
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <typename UC> struct parsed_number_string_t {
|
template <typename UC> struct parsed_number_string_t {
|
||||||
|
// an unsigned int avoids signed overflows (which are bad)
|
||||||
uint64_t mantissa{0};
|
uint64_t mantissa{0};
|
||||||
int16_t exponent{0};
|
int16_t exponent{0};
|
||||||
#ifndef FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN
|
#ifndef FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN
|
||||||
@ -328,7 +329,6 @@ parse_number_string(UC const *p, UC const *pend,
|
|||||||
|
|
||||||
UC const *const start_digits = p;
|
UC const *const start_digits = p;
|
||||||
|
|
||||||
// an unsigned int avoids signed overflows (which are bad)
|
|
||||||
while ((p != pend) && is_integer(*p)) {
|
while ((p != pend) && is_integer(*p)) {
|
||||||
// a multiplication by 10 is cheaper than an arbitrary integer
|
// a multiplication by 10 is cheaper than an arbitrary integer
|
||||||
// multiplication
|
// multiplication
|
||||||
@ -359,7 +359,6 @@ parse_number_string(UC const *p, UC const *pend,
|
|||||||
if (has_decimal_point) {
|
if (has_decimal_point) {
|
||||||
++p;
|
++p;
|
||||||
UC const *before = p;
|
UC const *before = p;
|
||||||
uint16_t fraction = 0;
|
|
||||||
// can occur at most twice without overflowing, but let it occur more, since
|
// can occur at most twice without overflowing, but let it occur more, since
|
||||||
// for integers with many digits, digit parsing is the primary bottleneck.
|
// for integers with many digits, digit parsing is the primary bottleneck.
|
||||||
loop_parse_if_eight_digits(p, pend, answer.mantissa);
|
loop_parse_if_eight_digits(p, pend, answer.mantissa);
|
||||||
@ -371,13 +370,13 @@ parse_number_string(UC const *p, UC const *pend,
|
|||||||
digit; // in rare cases, this will overflow, but that's ok
|
digit; // in rare cases, this will overflow, but that's ok
|
||||||
++p;
|
++p;
|
||||||
}
|
}
|
||||||
fraction = static_cast<uint16_t>(before - p);
|
answer.exponent = static_cast<int16_t>(before - p);
|
||||||
answer.fraction = span<UC const>(before, static_cast<uint16_t>(p - before));
|
answer.fraction = span<UC const>(before, static_cast<uint16_t>(p - before));
|
||||||
digit_count -= fraction;
|
digit_count -= answer.exponent;
|
||||||
#ifndef FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN
|
#ifndef FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN
|
||||||
FASTFLOAT_IF_CONSTEXPR17(basic_json_fmt) {
|
FASTFLOAT_IF_CONSTEXPR17(basic_json_fmt) {
|
||||||
// at least 1 digit in fractional part
|
// at least 1 digit in fractional part
|
||||||
if (has_decimal_point && fraction == 0) {
|
if (has_decimal_point && answer.exponent == 0) {
|
||||||
return report_parse_error<UC>(
|
return report_parse_error<UC>(
|
||||||
p, parse_error::no_digits_in_fractional_part);
|
p, parse_error::no_digits_in_fractional_part);
|
||||||
}
|
}
|
||||||
@ -389,7 +388,8 @@ parse_number_string(UC const *p, UC const *pend,
|
|||||||
}
|
}
|
||||||
// We have now parsed the integer and the fraction part of the mantissa.
|
// We have now parsed the integer and the fraction part of the mantissa.
|
||||||
|
|
||||||
// Now we can parse the exponent part.
|
// Now we can parse the explicit exponential part.
|
||||||
|
int16_t exp_number = 0; // explicit exponential part
|
||||||
if ((p != pend) && (uint8_t(options.format & chars_format::scientific) &&
|
if ((p != pend) && (uint8_t(options.format & chars_format::scientific) &&
|
||||||
(UC('e') == *p) ||
|
(UC('e') == *p) ||
|
||||||
(UC('E') == *p))
|
(UC('E') == *p))
|
||||||
@ -400,8 +400,14 @@ parse_number_string(UC const *p, UC const *pend,
|
|||||||
#endif
|
#endif
|
||||||
) {
|
) {
|
||||||
UC const *location_of_e = p;
|
UC const *location_of_e = p;
|
||||||
|
#ifdef FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN
|
||||||
++p;
|
++p;
|
||||||
|
#else
|
||||||
|
if ((UC('e') == *p) || (UC('E') == *p) || (UC('d') == *p) ||
|
||||||
|
(UC('D') == *p)) {
|
||||||
|
++p;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
bool neg_exp = false;
|
bool neg_exp = false;
|
||||||
if (p != pend) {
|
if (p != pend) {
|
||||||
if (UC('-') == *p) {
|
if (UC('-') == *p) {
|
||||||
@ -423,16 +429,17 @@ parse_number_string(UC const *p, UC const *pend,
|
|||||||
p = location_of_e;
|
p = location_of_e;
|
||||||
} else {
|
} else {
|
||||||
while ((p != pend) && is_integer(*p)) {
|
while ((p != pend) && is_integer(*p)) {
|
||||||
if (answer.exponent < 0x1000) {
|
if (exp_number < 0x1000) {
|
||||||
// check for exponent overflow if we have too many digits.
|
// check for exponent overflow if we have too many digits.
|
||||||
uint8_t const digit = uint8_t(*p - UC('0'));
|
uint8_t const digit = uint8_t(*p - UC('0'));
|
||||||
answer.exponent = 10 * answer.exponent + digit;
|
exp_number = 10 * exp_number + digit;
|
||||||
}
|
}
|
||||||
++p;
|
++p;
|
||||||
}
|
}
|
||||||
if (neg_exp) {
|
if (neg_exp) {
|
||||||
answer.exponent = -answer.exponent;
|
exp_number = -exp_number;
|
||||||
}
|
}
|
||||||
|
answer.exponent += exp_number;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// If it scientific and not fixed, we have to bail out.
|
// If it scientific and not fixed, we have to bail out.
|
||||||
@ -479,7 +486,7 @@ parse_number_string(UC const *p, UC const *pend,
|
|||||||
}
|
}
|
||||||
if (answer.mantissa >=
|
if (answer.mantissa >=
|
||||||
minimal_nineteen_digit_integer) { // We have a big integers
|
minimal_nineteen_digit_integer) { // We have a big integers
|
||||||
answer.exponent += int16_t(end_of_integer_part - p);
|
answer.exponent = int16_t(end_of_integer_part - p) + exp_number;
|
||||||
} else { // We have a value with a fractional component.
|
} else { // We have a value with a fractional component.
|
||||||
p = answer.fraction.ptr;
|
p = answer.fraction.ptr;
|
||||||
UC const *frac_end = p + answer.fraction.len();
|
UC const *frac_end = p + answer.fraction.len();
|
||||||
@ -488,7 +495,7 @@ parse_number_string(UC const *p, UC const *pend,
|
|||||||
answer.mantissa = answer.mantissa * 10 + uint64_t(*p - UC('0'));
|
answer.mantissa = answer.mantissa * 10 + uint64_t(*p - UC('0'));
|
||||||
++p;
|
++p;
|
||||||
}
|
}
|
||||||
answer.exponent += int16_t(answer.fraction.ptr - p);
|
answer.exponent = int16_t(answer.fraction.ptr - p) + exp_number;
|
||||||
}
|
}
|
||||||
// We have now corrected both exponent and mantissa, to a truncated value
|
// We have now corrected both exponent and mantissa, to a truncated value
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user