38 namespace json_details {
42 template<
typename Real,
bool = std::is_
floating_po
int_v<Real>>
43 inline constexpr bool is_narrow_real_v =
false;
45 template<
typename Real>
46 inline constexpr bool is_narrow_real_v<Real, true> =
47 std::numeric_limits<Real>::is_iec559 and
48 std::numeric_limits<Real>::radix == 2 and
49 std::numeric_limits<Real>::digits <
50 std::numeric_limits<float>::digits and
51 std::numeric_limits<Real>::max_exponent <=
52 std::numeric_limits<float>::max_exponent and
53 std::numeric_limits<Real>::min_exponent >=
54 std::numeric_limits<float>::min_exponent;
58 template<
typename Real>
59 inline constexpr bool is_precise_real_v =
60 std::is_floating_point_v<Real> and not is_narrow_real_v<Real> and
61 ( is_lemire_capable_v<Real> or has_precise_fallback_v<Real> );
63 template<
typename Result,
typename Signed>
64 [[nodiscard]]
constexpr Result parse_truncated_lemire(
65 bool negative, Signed exponent, std::uint64_t significant_digits,
66 bool discarded_nonzero, daw::not_null<char const *> number_first,
67 daw::not_null<char const *> number_last ) {
68 auto const lower = json_details::parse_real_eisellemire<Result>(
69 negative, exponent, significant_digits );
70 if( not discarded_nonzero ) {
76 auto const upper = json_details::parse_real_eisellemire<Result>(
77 negative, exponent, significant_digits + std::uint64_t{ 1 } );
78 if( lower == upper ) {
82 return json_details::parse_json_real_exact<Result>(
83 negative, number_first, number_last );
86 namespace single_pass_details {
88 inline constexpr std::ptrdiff_t max_u64_digits = 19;
93 inline constexpr std::int64_t max_explicit_exponent = 0x1000'0000;
97 template<
typename Result>
98 inline constexpr std::int64_t max_exact_power10 =
99 std::is_same_v<Result, long double> and
100 std::numeric_limits<long double>::digits == 113
102 : std::is_same_v<Result, long double> and
103 std::numeric_limits<long double>::digits == 64
105 : std::is_same_v<lemire_compute_t<Result>,
float> ? 10
109 template<
bool SkipEndCheck,
typename Accumulator,
typename Iterator>
110 [[nodiscard]] DAW_ATTRIB_INLINE
constexpr Iterator
111 parse_digit_run( Iterator first, Iterator
const last,
112 Accumulator &value ) {
113 while( last - first >= 8 and is_made_of_eight_digits_cx( first ) ) {
114 value = value *
static_cast<Accumulator
>( 100'000'000U ) +
115 static_cast<Accumulator
>(
116 static_cast<std::uint64_t
>( parse_8_digits( first ) ) );
119 while( SkipEndCheck or first < last ) {
120 auto const digit = parse_digit( *first );
124 value = value *
static_cast<Accumulator
>( 10U ) +
125 static_cast<Accumulator
>( digit );
131 struct significand_t {
132 std::uint64_t mantissa = 0;
134 std::int64_t exponent = 0;
135 std::ptrdiff_t significant_digits = 0;
136 bool discarded_nonzero =
false;
141 template<
typename Iterator>
142 [[nodiscard]]
constexpr significand_t
143 parse_long_significand( Iterator whole_first, Iterator
const whole_last,
144 Iterator fract_first,
145 Iterator
const fract_last ) {
146 significand_t result{ };
147 bool seen_nonzero =
false;
148 for( ; whole_first < whole_last; ++whole_first ) {
149 auto const digit = parse_digit( *whole_first );
150 seen_nonzero |= digit != 0;
151 if( not seen_nonzero ) {
154 ++result.significant_digits;
155 if( result.significant_digits <= max_u64_digits ) {
156 result.mantissa = result.mantissa * 10U + digit;
159 result.discarded_nonzero |= digit != 0;
162 for( ; fract_first < fract_last; ++fract_first ) {
163 auto const digit = parse_digit( *fract_first );
164 seen_nonzero |= digit != 0;
165 if( not seen_nonzero ) {
169 ++result.significant_digits;
170 if( result.significant_digits <= max_u64_digits ) {
171 result.mantissa = result.mantissa * 10U + digit;
174 result.discarded_nonzero |= digit != 0;
184 template<
typename Result,
typename ParseState,
typename Accumulator,
186 [[nodiscard]] DAW_ATTRIB_INLINE
constexpr Result finish_real(
187 int sign, Accumulator mantissa, std::int64_t explicit_exponent,
188 Iterator whole_first, Iterator whole_last, Iterator fract_first,
189 Iterator fract_last, Iterator number_first, Iterator number_last ) {
190 namespace sp = single_pass_details;
191 constexpr bool integer_accumulator =
192 std::is_same_v<Accumulator, std::uint64_t>;
193 auto const fract_digits = fract_last - fract_first;
194 auto const digit_count = ( whole_last - whole_first ) + fract_digits;
195 std::int64_t exponent =
196 explicit_exponent -
static_cast<std::int64_t
>( fract_digits );
197 std::ptrdiff_t significant_digits = digit_count;
198 bool discarded_nonzero =
false;
199 if( DAW_UNLIKELY( digit_count > sp::max_u64_digits ) ) {
200 auto const sig = sp::parse_long_significand(
201 whole_first, whole_last, fract_first, fract_last );
202 significant_digits = sig.significant_digits;
203 if constexpr( integer_accumulator ) {
205 mantissa = sig.mantissa;
206 exponent = explicit_exponent + sig.exponent;
207 discarded_nonzero = sig.discarded_nonzero;
211 if constexpr( is_precise_real_v<Result> and
212 ParseState::precise_ieee754 ) {
213 if constexpr( is_lemire_capable_v<Result> ) {
214 static_assert( integer_accumulator );
215 using compute_t = lemire_compute_t<Result>;
216 if( DAW_LIKELY( significant_digits <= sp::max_u64_digits and
217 mantissa <= ( std::uint64_t{ 1 }
218 << daw::digits<compute_t> ) and
219 exponent <= sp::max_exact_power10<Result> and
220 exponent >= -sp::max_exact_power10<Result> ) ) {
221 return static_cast<Result
>( sign ) *
222 power10<Result>( ParseState::exec_tag,
223 static_cast<Result
>( mantissa ),
226 return static_cast<Result
>(
227 parse_truncated_lemire<compute_t>( sign < 0,
235 if( DAW_LIKELY( significant_digits <= sp::max_u64_digits and
236 exponent <= sp::max_exact_power10<Result> and
237 exponent >= -sp::max_exact_power10<Result> ) ) {
238 return static_cast<Result
>( sign ) *
239 power10<Result>( ParseState::exec_tag,
240 static_cast<Result
>( mantissa ),
243 return parse_with_strtod<Result>( number_first, number_last );
245 }
else if constexpr( std::numeric_limits<Result>::radix != 2 or
246 daw::digits<Result> > daw::digits<double> ) {
250 return static_cast<Result
>( sign ) *
251 power10_wide(
static_cast<Result
>( mantissa ), exponent );
253 return static_cast<Result
>( sign ) *
254 power10<Result>( ParseState::exec_tag,
255 static_cast<Result
>( mantissa ),
264 template<
typename Result,
typename ParseState>
265 [[nodiscard]]
constexpr Result
266 parse_real_single_pass( ParseState &parse_state ) {
267 namespace sp = single_pass_details;
269 using iterator_t =
typename ParseState::iterator;
270 constexpr bool skip_end_check = ParseState::is_zero_terminated_string or
271 ParseState::is_unchecked_input;
274 constexpr bool integer_accumulator =
275 sp::max_u64_digits >= daw::max_digits10<Result> + 1;
276 using accumulator_t =
277 std::conditional_t<integer_accumulator, std::uint64_t, Result>;
279 iterator_t
const number_first = parse_state.first;
284 parse_policy_details::validate_signed_first( parse_state );
285 iterator_t first = parse_state.first;
286 iterator_t
const last = parse_state.last;
288 accumulator_t mantissa = accumulator_t( );
289 iterator_t
const whole_first = first;
290 first = sp::parse_digit_run<skip_end_check>( first, last, mantissa );
291 iterator_t
const whole_last = first;
292 iterator_t fract_first = first;
293 if( ( skip_end_check or first < last ) and *first ==
'.' ) {
296 first = sp::parse_digit_run<skip_end_check>( first, last, mantissa );
300 ErrorReason::InvalidNumber,
301 parse_state.copy( first ) );
303 iterator_t
const fract_last = first;
305 std::int64_t explicit_exponent = 0;
306 if( ( skip_end_check or first < last ) and
307 ( ( *first | 0x20 ) ==
'e' ) ) {
310 ErrorReason::UnexpectedEndOfData,
311 parse_state.copy( first ) );
312 bool negative_exponent =
false;
315 negative_exponent =
true;
320 parse_digit( *first ) < 10U,
321 ErrorReason::InvalidNumber );
325 ErrorReason::InvalidNumber );
327 while( skip_end_check or first < last ) {
328 auto const digit = parse_digit( *first );
332 if( explicit_exponent < sp::max_explicit_exponent ) {
333 explicit_exponent = explicit_exponent * 10 + digit;
337 if( negative_exponent ) {
338 explicit_exponent = -explicit_exponent;
341 parse_state.first = first;
343 return finish_real<Result, ParseState>( sign,
354 namespace single_pass_details {
356 template<
typename Accumulator,
typename Iterator>
357 DAW_ATTRIB_INLINE
constexpr void
358 parse_known_digits( Iterator first, Iterator
const last,
359 Accumulator &value ) {
360 while( last - first >= 8 ) {
361 value = value *
static_cast<Accumulator
>( 100'000'000U ) +
362 static_cast<Accumulator
>(
363 static_cast<std::uint64_t
>( parse_8_digits( first ) ) );
366 for( ; first < last; ++first ) {
367 value = value *
static_cast<Accumulator
>( 10U ) +
368 static_cast<Accumulator
>( parse_digit( *first ) );
379 template<
typename Result,
typename ParseState>
380 [[nodiscard]]
constexpr Result
381 parse_real_known_bounds( ParseState &parse_state ) {
382 namespace sp = single_pass_details;
384 parse_state.has_more( ) and
385 parse_policy_details::is_number_start( parse_state.front( ) ),
386 ErrorReason::InvalidNumberStart,
389 using iterator_t =
typename ParseState::iterator;
390 constexpr bool integer_accumulator =
391 sp::max_u64_digits >= daw::max_digits10<Result> + 1;
392 using accumulator_t =
393 std::conditional_t<integer_accumulator, std::uint64_t, Result>;
395 iterator_t
const number_first = parse_state.first;
396 iterator_t
const last = parse_state.last;
397 iterator_t
const decimal_point = parse_state.class_first;
398 iterator_t
const exponent_marker = parse_state.class_last;
400 parse_policy_details::validate_signed_first( parse_state );
402 iterator_t
const whole_first = parse_state.first;
403 iterator_t
const whole_last =
404 decimal_point ? decimal_point
405 : ( exponent_marker ? exponent_marker : last );
406 iterator_t
const fract_first =
407 decimal_point ? decimal_point + 1 : whole_last;
408 iterator_t
const fract_last =
409 decimal_point ? ( exponent_marker ? exponent_marker : last )
414 ErrorReason::InvalidNumber,
415 parse_state.copy( whole_first ) );
417 whole_last - whole_first == 1,
418 ErrorReason::InvalidNumberStart,
419 parse_state.copy( whole_first ) );
421 fract_first < fract_last,
422 ErrorReason::InvalidNumber,
423 parse_state.copy( fract_first ) );
425 std::int64_t explicit_exponent = 0;
426 if( exponent_marker !=
nullptr ) {
427 iterator_t first = exponent_marker + 1;
429 ErrorReason::InvalidNumber,
430 parse_state.copy( first ) );
431 bool const negative_exponent = *first ==
'-';
432 if( negative_exponent or *first ==
'+' ) {
436 ErrorReason::InvalidNumber,
437 parse_state.copy( first ) );
438 for( ; first < last; ++first ) {
439 if( explicit_exponent < sp::max_explicit_exponent ) {
441 explicit_exponent * 10 + parse_digit( *first );
444 if( negative_exponent ) {
445 explicit_exponent = -explicit_exponent;
448 parse_state.first = last;
450 accumulator_t mantissa = accumulator_t( );
453 if( not integer_accumulator or
454 DAW_LIKELY( ( whole_last - whole_first ) +
455 ( fract_last - fract_first ) <=
456 sp::max_u64_digits ) ) {
457 sp::parse_known_digits( whole_first, whole_last, mantissa );
458 sp::parse_known_digits( fract_first, fract_last, mantissa );
460 return finish_real<Result, ParseState>( sign,
471 template<
typename Result,
bool KnownRange,
typename ParseState>
472 [[nodiscard]]
constexpr Result parse_real( ParseState &parse_state );
477 template<
typename Result>
478 [[nodiscard]]
constexpr bool is_halfway_for_narrowing(
float f ) {
479 auto const bits = DAW_BIT_CAST( std::uint32_t, f );
480 auto const biased_exponent =
481 static_cast<std::int32_t
>( ( bits >> 23U ) & 0xFFU );
482 if( biased_exponent == 0xFF ) {
485 std::uint32_t mantissa = bits & 0x7F'FFFFU;
486 std::int32_t exponent = -126;
487 if( biased_exponent != 0 ) {
488 mantissa |= 0x80'0000U;
489 exponent = biased_exponent - 127;
493 DAW_CPP23_STATIC_LOCAL
constexpr std::int32_t result_min_exponent =
494 std::numeric_limits<Result>::min_exponent - 1;
495 std::int32_t dropped_bits = std::numeric_limits<float>::digits -
496 std::numeric_limits<Result>::digits;
497 if( exponent < result_min_exponent ) {
498 dropped_bits += result_min_exponent - exponent;
500 if( dropped_bits > std::numeric_limits<float>::digits ) {
503 auto const half = std::uint32_t{ 1 }
504 <<
static_cast<std::uint32_t
>( dropped_bits - 1 );
505 return ( mantissa & ( ( half << 1U ) - 1U ) ) == half;
508 template<
typename Result,
bool KnownRange,
typename ParseState>
509 [[nodiscard]]
constexpr Result
510 parse_narrow_real( ParseState &parse_state ) {
511 daw::not_null<char const *>
const number_first = parse_state.first;
512 float const f = parse_real<float, KnownRange>( parse_state );
513 if constexpr( ParseState::precise_ieee754 ) {
514 if( DAW_UNLIKELY( is_halfway_for_narrowing<Result>( f ) ) ) {
515 auto const number_last =
516 KnownRange ? parse_state.last : parse_state.first;
517 return json_details::parse_json_real_exact<Result>(
518 f < 0.0f, number_first, number_last );
521 return static_cast<Result
>( f );
524 template<
typename Result,
bool KnownRange,
typename ParseState>
525 [[nodiscard]]
constexpr Result parse_real( ParseState &parse_state ) {
526 if constexpr( is_narrow_real_v<Result> ) {
527 return parse_narrow_real<Result, KnownRange>( parse_state );
528 }
else if constexpr( KnownRange ) {
530 return parse_real_known_bounds<Result>( parse_state );
532 return parse_real_single_pass<Result>( parse_state );