@@ -60,6 +60,7 @@ fastfloat_really_inline
6060parsed_number_string parse_number_string (const char *p, const char *pend, chars_format fmt) noexcept {
6161 parsed_number_string answer;
6262 answer.valid = false ;
63+ answer.too_many_digits = false ;
6364 answer.negative = (*p == ' -' );
6465 if ((*p == ' -' ) || (*p == ' +' )) {
6566 ++p;
@@ -81,10 +82,11 @@ parsed_number_string parse_number_string(const char *p, const char *pend, chars_
8182 uint64_t (*p - ' 0' ); // might overflow, we will handle the overflow later
8283 ++p;
8384 }
85+ const char *const end_of_integer_part = p;
86+ int64_t digit_count = int64_t (end_of_integer_part - start_digits);
8487 int64_t exponent = 0 ;
8588 if ((p != pend) && (*p == ' .' )) {
8689 ++p;
87- const char *first_after_period = p;
8890#if FASTFLOAT_IS_BIG_ENDIAN == 0
8991 // Fast approach only tested under little endian systems
9092 if ((p + 8 <= pend) && is_made_of_eight_digits_fast (p)) {
@@ -101,19 +103,16 @@ parsed_number_string parse_number_string(const char *p, const char *pend, chars_
101103 ++p;
102104 i = i * 10 + digit; // in rare cases, this will overflow, but that's ok
103105 }
104- exponent = first_after_period - p;
106+ exponent = end_of_integer_part + 1 - p;
107+ digit_count -= exponent;
105108 }
106109 // we must have encountered at least one integer!
107- if ((start_digits == p) || ((start_digits == p - 1 ) && (*start_digits == ' . ' ) ) ) {
110+ if (digit_count == 0 ) {
108111 return answer;
109112 }
110- // digit_count is the exact number of digits.
111- int32_t digit_count =
112- int32_t (p - start_digits); // used later to guard against overflows
113- if (exponent > 0 ) {digit_count--;}
113+ int64_t exp_number = 0 ; // explicit exponential part
114114 if ((fmt & chars_format::scientific) && (p != pend) && ((' e' == *p) || (' E' == *p))) {
115115 const char * location_of_e = p;
116- int64_t exp_number = 0 ; // exponential part
117116 ++p;
118117 bool neg_exp = false ;
119118 if ((p != pend) && (' -' == *p)) {
@@ -137,7 +136,8 @@ parsed_number_string parse_number_string(const char *p, const char *pend, chars_
137136 }
138137 ++p;
139138 }
140- exponent += (neg_exp ? -exp_number : exp_number);
139+ if (neg_exp) { exp_number = - exp_number; }
140+ exponent += exp_number;
141141 }
142142 } else {
143143 // If it scientific and not fixed, we have to bail out.
@@ -151,25 +151,40 @@ parsed_number_string parse_number_string(const char *p, const char *pend, chars_
151151 // of a 64-bit integer. However, this is uncommon.
152152 //
153153 // We can deal with up to 19 digits.
154- if ((( digit_count > 19 )) ) { // this is uncommon
154+ if (digit_count > 19 ) { // this is uncommon
155155 // It is possible that the integer had an overflow.
156156 // We have to handle the case where we have 0.0000somenumber.
157157 // We need to be mindful of the case where we only have zeroes...
158158 // E.g., 0.000000000...000.
159159 const char *start = start_digits;
160160 while ((start != pend) && (*start == ' 0' || *start == ' .' )) {
161- if (*start == ' . ' ) { digit_count++ ; } // We will subtract it again later.
161+ if (*start == ' 0 ' ) { digit_count -- ; }
162162 start++;
163163 }
164- // We over-decrement by one when there is a decimal separator
165- digit_count -= int (start - start_digits);
166164 if (digit_count > 19 ) {
167- answer.mantissa = 0xFFFFFFFFFFFFFFFF ; // important: we don't want the mantissa to be used in a fast path uninitialized.
168165 answer.too_many_digits = true ;
169- return answer;
166+ // Let us start again, this time, avoiding overflows.
167+ i = 0 ;
168+ p = start_digits;
169+ const uint64_t minimal_nineteen_digit_integer{1000000000000000000 };
170+ while ((i < minimal_nineteen_digit_integer) && (p != pend) && is_integer (*p)) {
171+ i = i * 10 + uint64_t (*p - ' 0' );
172+ ++p;
173+ }
174+ if (i >= minimal_nineteen_digit_integer) { // We have a big integers
175+ exponent = end_of_integer_part - p + exp_number;
176+ } else { // We have a value with a fractional component.
177+ p++; // skip the '.'
178+ const char *first_after_period = p;
179+ while ((i < minimal_nineteen_digit_integer) && (p != pend) && is_integer (*p)) {
180+ i = i * 10 + uint64_t (*p - ' 0' );
181+ ++p;
182+ }
183+ exponent = first_after_period - p + exp_number;
184+ }
185+ // We have now corrected both exponent and i, to a truncated value
170186 }
171187 }
172- answer.too_many_digits = false ;
173188 answer.exponent = exponent;
174189 answer.mantissa = i;
175190 return answer;
0 commit comments