mirror of
https://github.com/fastfloat/fast_float.git
synced 2025-12-06 16:56:57 +08:00
fix for the parse_number_string
This commit is contained in:
parent
6b22957188
commit
3ee80c2da3
@ -328,24 +328,15 @@ parse_number_string(UC const *p, UC const *pend,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
UC const *const start_digits = p;
|
UC const *const start_digits = p;
|
||||||
#ifndef FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN
|
|
||||||
if (p != pend)
|
while ((p != pend) && is_integer(*p)) {
|
||||||
#endif
|
// a multiplication by 10 is cheaper than an arbitrary integer
|
||||||
{
|
// multiplication
|
||||||
do {
|
answer.mantissa = static_cast<fast_float::am_mant_t>(
|
||||||
if (is_integer(*p)) {
|
answer.mantissa * 10 +
|
||||||
// a multiplication by 10 is cheaper than an arbitrary integer
|
static_cast<fast_float::am_mant_t>(
|
||||||
// multiplication
|
*p - UC('0'))); // might overflow, we will handle the overflow later
|
||||||
answer.mantissa = static_cast<fast_float::am_mant_t>(
|
++p;
|
||||||
answer.mantissa * 10 +
|
|
||||||
static_cast<fast_float::am_mant_t>(
|
|
||||||
*p -
|
|
||||||
UC('0'))); // might overflow, we will handle the overflow later
|
|
||||||
++p;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} while (p != pend);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
UC const *const end_of_integer_part = p;
|
UC const *const end_of_integer_part = p;
|
||||||
@ -370,7 +361,7 @@ parse_number_string(UC const *p, UC const *pend,
|
|||||||
// We can now parse the fraction part of the mantissa.
|
// We can now parse the fraction part of the mantissa.
|
||||||
if ((p != pend) && (*p == options.decimal_point)) {
|
if ((p != pend) && (*p == options.decimal_point)) {
|
||||||
++p;
|
++p;
|
||||||
UC const *before = p;
|
UC const *const before = p;
|
||||||
// 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);
|
||||||
@ -404,74 +395,46 @@ parse_number_string(UC const *p, UC const *pend,
|
|||||||
|
|
||||||
// Now we can parse the explicit exponential part.
|
// Now we can parse the explicit exponential part.
|
||||||
am_pow_t exp_number = 0; // explicit exponential part
|
am_pow_t exp_number = 0; // explicit exponential part
|
||||||
bool neg_exp = false;
|
if ((p != pend) &&
|
||||||
if (p != pend) {
|
(chars_format_t(options.format & chars_format::scientific) &&
|
||||||
UC const *location_of_e;
|
((UC('e') == *p) || (UC('E') == *p)))
|
||||||
if (chars_format_t(options.format & chars_format::scientific)) {
|
|
||||||
switch (*p) {
|
|
||||||
case UC('e'):
|
|
||||||
case UC('E'):
|
|
||||||
location_of_e = p;
|
|
||||||
++p;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if (!chars_format_t(options.format & chars_format::fixed)) {
|
|
||||||
// It scientific and not fixed, we have to bail out.
|
|
||||||
return report_parse_error<UC>(p,
|
|
||||||
parse_error::missing_exponential_part);
|
|
||||||
}
|
|
||||||
// In fixed notation we will be ignoring the 'e'.
|
|
||||||
location_of_e = nullptr;
|
|
||||||
}
|
|
||||||
if (location_of_e && p != pend) {
|
|
||||||
switch (*p) {
|
|
||||||
case UC('-'):
|
|
||||||
neg_exp = true;
|
|
||||||
++p;
|
|
||||||
break;
|
|
||||||
case UC('+'): // '+' on exponent is allowed by C++17 20.19.3.(7.1)
|
|
||||||
++p;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// In scientific and fixed notations sign is optional.
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#ifndef FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN
|
#ifndef FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN
|
||||||
else if (chars_format_t(options.format & detail::basic_fortran_fmt)) {
|
|| (chars_format_t(options.format & detail::basic_fortran_fmt) &&
|
||||||
switch (*p) {
|
((UC('+') == *p) || (UC('-') == *p) || (UC('d') == *p) ||
|
||||||
case UC('d'):
|
(UC('D') == *p)))
|
||||||
case UC('D'):
|
#endif
|
||||||
++p;
|
) {
|
||||||
break;
|
UC const *location_of_e = p;
|
||||||
default:
|
#ifdef FASTFLOAT_ONLY_POSITIVE_C_NUMBER_WO_INF_NAN
|
||||||
// In Fortran the d symbol is optional.
|
++p;
|
||||||
break;
|
#else
|
||||||
}
|
if ((UC('e') == *p) || (UC('E') == *p) || (UC('d') == *p) ||
|
||||||
switch (*p) {
|
(UC('D') == *p)) {
|
||||||
case UC('-'):
|
++p;
|
||||||
neg_exp = true;
|
|
||||||
location_of_e = p;
|
|
||||||
++p;
|
|
||||||
break;
|
|
||||||
case UC('+'):
|
|
||||||
location_of_e = p;
|
|
||||||
++p;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// In Fortran the sign is mandatory.
|
|
||||||
return report_parse_error<UC>(p, parse_error::missing_exponential_part);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
else {
|
bool neg_exp = false;
|
||||||
location_of_e = nullptr;
|
if (p != pend) {
|
||||||
|
if (UC('-') == *p) {
|
||||||
|
neg_exp = true;
|
||||||
|
++p;
|
||||||
|
} else if (UC('+') == *p) {
|
||||||
|
// '+' on exponent is allowed by C++17 20.19.3.(7.1)
|
||||||
|
++p;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
// We have now parsed the sign of the exponent.
|
||||||
if (location_of_e) {
|
if ((p == pend) || !is_integer(*p)) {
|
||||||
// We have a valid scientific notation, let's parse the explicit
|
if (!(chars_format_t(options.format & chars_format::fixed))) {
|
||||||
// exponent.
|
// The exponential part is invalid for scientific notation, so it
|
||||||
|
// must be a trailing token for fixed notation. However, fixed
|
||||||
|
// notation is disabled, so report a scientific notation error.
|
||||||
|
return report_parse_error<UC>(p, parse_error::missing_exponential_part);
|
||||||
|
}
|
||||||
|
// Otherwise, we will be ignoring the 'e'.
|
||||||
|
p = location_of_e;
|
||||||
|
} else {
|
||||||
|
// Now let's parse the explicit exponent.
|
||||||
while ((p != pend) && is_integer(*p)) {
|
while ((p != pend) && is_integer(*p)) {
|
||||||
if (exp_number < 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.
|
||||||
@ -484,9 +447,11 @@ parse_number_string(UC const *p, UC const *pend,
|
|||||||
exp_number = -exp_number;
|
exp_number = -exp_number;
|
||||||
}
|
}
|
||||||
answer.exponent += exp_number;
|
answer.exponent += exp_number;
|
||||||
} else if (chars_format_t(options.format & chars_format::scientific) &&
|
}
|
||||||
!chars_format_t(options.format & chars_format::fixed)) {
|
} else {
|
||||||
// If it scientific and not fixed, we have to bail out.
|
// If it scientific and not fixed, we have to bail out.
|
||||||
|
if ((chars_format_t(options.format & chars_format::scientific)) &&
|
||||||
|
!(chars_format_t(options.format & chars_format::fixed))) {
|
||||||
return report_parse_error<UC>(p, parse_error::missing_exponential_part);
|
return report_parse_error<UC>(p, parse_error::missing_exponential_part);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user