@@ -2,11 +2,14 @@ use crate::common::{is_8digits_le, AsciiStr, ByteSlice};
22use crate :: float:: Float ;
33use crate :: format:: FloatFormat ;
44
5+ const MIN_19DIGIT_INT : u64 = 100_0000_0000_0000_0000 ;
6+
57#[ derive( Clone , Copy , Debug , Default , PartialEq , Eq ) ]
68pub struct Number {
79 pub exponent : i64 ,
810 pub mantissa : u64 ,
911 pub negative : bool ,
12+ pub many_digits : bool ,
1013}
1114
1215impl Number {
@@ -15,6 +18,7 @@ impl Number {
1518 F :: MIN_EXPONENT_FAST_PATH <= self . exponent
1619 && self . exponent <= F :: MAX_EXPONENT_FAST_PATH
1720 && self . mantissa <= F :: MAX_MANTISSA_FAST_PATH
21+ && !self . many_digits
1822 }
1923
2024 #[ inline]
@@ -56,6 +60,15 @@ fn try_parse_digits(s: &mut AsciiStr<'_>, x: &mut u64) {
5660 } ) ;
5761}
5862
63+ #[ inline]
64+ fn try_parse_19digits ( s : & mut AsciiStr < ' _ > , x : & mut u64 ) {
65+ while * x < MIN_19DIGIT_INT && !s. is_empty ( ) && s. first ( ) . is_ascii_digit ( ) {
66+ let digit = s. first ( ) - b'0' ;
67+ * x = ( * x * 10 ) + digit as u64 ; // no overflows here
68+ s. step ( ) ;
69+ }
70+ }
71+
5972#[ inline]
6073fn try_parse_8digits_le ( s : & mut AsciiStr < ' _ > , x : & mut u64 ) -> usize {
6174 // may cause overflows, to be handled later
@@ -135,6 +148,7 @@ pub fn parse_number(s: &[u8], fmt: FloatFormat) -> Option<(Number, usize)> {
135148 // handle dot with the following digits
136149 let mut n_after_dot = 0 ;
137150 let mut exponent = 0i64 ;
151+ let int_end = s;
138152 if s. check_first ( b'.' ) {
139153 s. step ( ) ;
140154 let before = s;
@@ -150,33 +164,64 @@ pub fn parse_number(s: &[u8], fmt: FloatFormat) -> Option<(Number, usize)> {
150164 }
151165
152166 // handle scientific format
167+ let mut exp_number = 0i64 ;
153168 if fmt. scientific {
154169 if s. check_first_either ( b'e' , b'E' ) {
155- parse_scientific ( & mut s, & mut exponent, fmt. fixed ) ?;
170+ parse_scientific ( & mut s, & mut exp_number, fmt. fixed ) ?;
171+ exponent += exp_number;
156172 } else if !fmt. fixed {
157173 return None ; // error: scientific and not fixed
158174 }
159175 }
160176
177+ let len = s. offset_from ( & start) as _ ;
178+
161179 // handle uncommon case with many digits
162180 n_digits -= 19 ;
181+ if n_digits <= 0 {
182+ return Some ( (
183+ Number {
184+ exponent,
185+ mantissa,
186+ negative,
187+ many_digits : false ,
188+ } ,
189+ len,
190+ ) ) ;
191+ }
192+
193+ let mut many_digits = false ;
194+ let mut p = digits_start;
195+ while p. check_first_either ( b'0' , b'.' ) {
196+ n_digits -= p. first ( ) . saturating_sub ( b'0' - 1 ) as isize ; // '0' = b'.' + 2
197+ p. step ( ) ;
198+ }
163199 if n_digits > 0 {
164- let mut p = digits_start;
165- while p. check_first_either ( b'0' , b'.' ) {
166- n_digits -= p. first ( ) . saturating_sub ( b'0' - 1 ) as isize ; // '0' = b'.' + 2
167- p. step ( ) ;
168- }
169- if n_digits > 0 {
170- mantissa = u64:: MAX ;
171- }
200+ // at this point we have more than 19 significant digits, let's try again
201+ many_digits = true ;
202+ mantissa = 0u64 ;
203+ let mut s = digits_start;
204+ try_parse_19digits ( & mut s, & mut mantissa) ;
205+ exponent = if mantissa >= MIN_19DIGIT_INT {
206+ int_end. offset_from ( & s) // big int
207+ } else {
208+ s. step ( ) ; // fractional component, skip the '.'
209+ let before = s;
210+ try_parse_19digits ( & mut s, & mut mantissa) ;
211+ -s. offset_from ( & before)
212+ } as i64 ;
213+ exponent += exp_number; // add back the explicit part
172214 }
173215
174- let number = Number {
175- exponent,
176- mantissa,
177- negative,
178- } ;
179- Some ( ( number, s. offset_from ( & start) as usize ) )
216+ Some ( (
217+ Number {
218+ exponent,
219+ mantissa,
220+ negative,
221+ many_digits,
222+ } ,
223+ len,
224+ ) )
180225}
181226
182227#[ inline]
0 commit comments