mod binary;
mod common;
mod decimal;
mod float;
mod number;
mod simple;
mod table;
use binary::compute_float;
use float::*;
use number::*;
use crate::{Parser, config::Config, source::Source};
impl<S: Source, C: Config> Parser<'_, S, C> {
#[inline(always)]
pub(crate) unsafe fn parse_f64(
&mut self,
mut mantissa: u64,
neg: bool,
start: usize,
) -> Option<f64> {
let mut n_digits = self.idx() - start;
let mut exponent = 0;
let mut exp_number = 0;
let int_end = self.idx();
match self.cur() {
b'.' => {
self.inc(1);
let stamp = self.idx();
self.parse_mantissa(&mut mantissa);
let tmp = self.idx() - stamp;
if tmp == 0 {
return None;
}
exponent = (tmp as i64).wrapping_neg();
n_digits += tmp;
if self.idx() != self.src.len() {
match self.cur() {
b'e' | b'E' => exp_number = self.parse_scientific()?,
_ => self.dec(),
}
}
}
b'e' | b'E' => exp_number = self.parse_scientific()?,
_ => {}
}
exponent += exp_number;
let num = 'tmp: {
if n_digits <= 19 {
break 'tmp Number {
exponent,
mantissa,
negative: neg,
many_digits: false,
};
}
while S::NULL_PADDED || self.idx() != self.src.len() {
if self.cur().wrapping_sub(b'0') > 9 {
break;
}
n_digits += 1;
self.inc(1);
}
n_digits -= 19;
let mut idx = start;
while (S::NULL_PADDED || idx != self.src.len()) && n_digits != 0 {
match *self.src.ptr(idx) {
v @ (b'.' | b'0') => {
n_digits -= (v - b'.') as usize >> 1;
idx += 1;
}
_ => break,
}
}
let mut many_digits = false;
if n_digits != 0 {
mantissa = 0;
many_digits = true;
let mut idx = start;
self.try_parse_19digits(&mut idx, &mut mantissa);
exponent = if mantissa >= MIN_19DIGIT_INT {
(int_end - idx) as _ } else {
idx += 1;
let before = idx;
self.try_parse_19digits(&mut idx, &mut mantissa);
(idx - before).wrapping_neg() as _
};
exponent += exp_number; }
self.dec();
Number {
exponent,
mantissa,
negative: neg,
many_digits,
}
};
if let Some(value) = num.try_fast_path() {
return Some(value);
}
let mut am = compute_float(num.exponent, num.mantissa);
if num.many_digits && am != compute_float(num.exponent, num.mantissa + 1) {
am.power2 = -1;
}
if am.power2 < 0 {
am = self.parse_long_mantissa(start - neg as usize)
}
let mut word = am.mantissa;
word |= (am.power2 as u64) << MANTISSA_EXPLICIT_BITS;
word |= (num.negative as u64) << SIGN_INDEX;
Some(f64::from_bits(word))
}
#[inline(always)]
unsafe fn parse_scientific(&mut self) -> Option<i64> {
self.inc(1);
if !S::NULL_PADDED && self.idx() == self.src.len() {
return None;
}
let mut num = 0i64;
let mut neg = false;
let mut flag = false;
if matches!(self.cur(), b'-' | b'+') {
neg = self.cur() == b'-';
self.inc(1);
}
while S::NULL_PADDED || self.idx() != self.src.len() {
let tmp = self.cur();
if tmp < b'0' || tmp > b'9' {
break;
}
if num < 0x10000 {
num = num * 10 + (tmp - b'0') as i64;
}
flag = true;
self.inc(1);
}
self.dec();
if flag {
Some(if neg { -num } else { num })
} else {
None
}
}
#[inline]
unsafe fn try_parse_19digits(&mut self, idx: &mut usize, mantissa: &mut u64) {
while (S::NULL_PADDED || *idx != self.src.len()) && *mantissa < MIN_19DIGIT_INT {
let num = self.src.ptr(*idx).read().wrapping_sub(b'0');
if num > 9 {
break;
}
*mantissa = mantissa.wrapping_mul(10).wrapping_add(num as _);
*idx += 1;
}
}
}