core/num/imp/dec2flt/
parse.rs1use dec2flt::common::{ByteSlice, is_8digits};
4use dec2flt::decimal::Decimal;
5use dec2flt::float::RawFloat;
6
7use crate::num::imp::dec2flt;
8
9const MIN_19DIGIT_INT: u64 = 100_0000_0000_0000_0000;
10
11fn parse_8digits(mut v: u64) -> u64 {
20 const MASK: u64 = 0x0000_00FF_0000_00FF;
21 const MUL1: u64 = 0x000F_4240_0000_0064;
22 const MUL2: u64 = 0x0000_2710_0000_0001;
23 v -= 0x3030_3030_3030_3030;
24 v = (v * 10) + (v >> 8); let v1 = (v & MASK).wrapping_mul(MUL1);
26 let v2 = ((v >> 16) & MASK).wrapping_mul(MUL2);
27 ((v1.wrapping_add(v2) >> 32) as u32) as u64
28}
29
30fn try_parse_digits(mut s: &[u8], mut x: u64) -> (&[u8], u64) {
32 while s.len() >= 8 {
35 let num = s.read_u64();
36 if is_8digits(num) {
37 x = x.wrapping_mul(1_0000_0000).wrapping_add(parse_8digits(num));
38 s = &s[8..];
39 } else {
40 break;
41 }
42 }
43
44 s = s.parse_digits(|digit| {
45 x = x.wrapping_mul(10).wrapping_add(digit as _);
46 });
47
48 (s, x)
49}
50
51fn try_parse_19digits(s_ref: &mut &[u8], x: &mut u64) {
53 let mut s = *s_ref;
54
55 while *x < MIN_19DIGIT_INT {
56 if let Some((c, s_next)) = s.split_first() {
57 let digit = c.wrapping_sub(b'0');
58
59 if digit < 10 {
60 *x = (*x * 10) + digit as u64; s = s_next;
62 } else {
63 break;
64 }
65 } else {
66 break;
67 }
68 }
69
70 *s_ref = s;
71}
72
73fn parse_scientific(s_ref: &mut &[u8]) -> Option<i64> {
75 let mut exponent = 0i64;
76 let mut negative = false;
77
78 let mut s = *s_ref;
79
80 if let Some((&c, s_next)) = s.split_first() {
81 negative = c == b'-';
82 if c == b'-' || c == b'+' {
83 s = s_next;
84 }
85 }
86
87 if matches!(s.first(), Some(&x) if x.is_ascii_digit()) {
88 *s_ref = s.parse_digits(|digit| {
89 if exponent < 0x10000 {
91 exponent = 10 * exponent + digit as i64;
92 }
93 });
94 if negative { Some(-exponent) } else { Some(exponent) }
95 } else {
96 *s_ref = s;
97 None
98 }
99}
100
101fn parse_partial_number(mut s: &[u8]) -> Option<(Decimal, usize)> {
106 debug_assert!(!s.is_empty());
107
108 let mut mantissa = 0_u64;
110 let start = s;
111 let tmp = try_parse_digits(s, mantissa);
112 s = tmp.0;
113 mantissa = tmp.1;
114 let mut n_digits = s.offset_from(start);
115
116 let mut n_after_dot = 0;
118 let mut exponent = 0_i64;
119 let int_end = s;
120
121 if let Some((&b'.', s_next)) = s.split_first() {
122 s = s_next;
123 let before = s;
124 let tmp = try_parse_digits(s, mantissa);
125 s = tmp.0;
126 mantissa = tmp.1;
127 n_after_dot = s.offset_from(before);
128 exponent = -n_after_dot as i64;
129 }
130
131 n_digits += n_after_dot;
132 if n_digits == 0 {
133 return None;
134 }
135
136 let mut exp_number = 0_i64;
138 if let Some((&c, s_next)) = s.split_first() {
139 if c == b'e' || c == b'E' {
140 s = s_next;
141 exp_number = parse_scientific(&mut s)?;
143 exponent += exp_number;
144 }
145 }
146
147 let len = s.offset_from(start) as _;
148
149 if n_digits <= 19 {
151 return Some((Decimal { exponent, mantissa, negative: false, many_digits: false }, len));
152 }
153
154 n_digits -= 19;
155 let mut many_digits = false;
156 let mut p = start;
157 while let Some((&c, p_next)) = p.split_first() {
158 if c == b'.' || c == b'0' {
159 n_digits -= c.saturating_sub(b'0' - 1) as isize;
160 p = p_next;
161 } else {
162 break;
163 }
164 }
165 if n_digits > 0 {
166 many_digits = true;
168 mantissa = 0;
169 let mut s = start;
170 try_parse_19digits(&mut s, &mut mantissa);
171 exponent = if mantissa >= MIN_19DIGIT_INT {
172 int_end.offset_from(s)
174 } else {
175 s = &s[1..];
176 let before = s;
177 try_parse_19digits(&mut s, &mut mantissa);
178 -s.offset_from(before)
179 } as i64;
180 exponent += exp_number;
182 }
183
184 Some((Decimal { exponent, mantissa, negative: false, many_digits }, len))
185}
186
187pub fn parse_number(s: &[u8]) -> Option<Decimal> {
191 if let Some((float, rest)) = parse_partial_number(s) {
192 if rest == s.len() {
193 return Some(float);
194 }
195 }
196 None
197}
198
199pub(crate) fn parse_inf_nan<F: RawFloat>(s: &[u8], negative: bool) -> Option<F> {
201 let mut register;
206 let len: usize;
207
208 if s.len() == 8 {
210 register = s.read_u64();
211 len = 8;
212 } else if s.len() == 3 {
213 let a = s[0] as u64;
214 let b = s[1] as u64;
215 let c = s[2] as u64;
216 register = (c << 16) | (b << 8) | a;
217 len = 3;
218 } else {
219 return None;
220 }
221
222 register &= 0xDFDFDFDFDFDFDFDF;
226
227 const INF_3: u64 = 0x464E49; const INF_8: u64 = 0x5954494E49464E49; const NAN: u64 = 0x4E414E; let float = match (register, len) {
236 (INF_3, 3) => F::INFINITY,
237 (INF_8, 8) => F::INFINITY,
238 (NAN, 3) => F::NAN,
239 _ => return None,
240 };
241
242 if negative { Some(-float) } else { Some(float) }
243}