18#include <daw/daw_cxmath.h>
19#include <daw/daw_likely.h>
20#include <daw/daw_utility.h>
30 namespace json_details {
31 template<
bool skip_end_check,
typename Un
signed>
32 DAW_ATTRIB_FLATINLINE
inline constexpr void
36 if constexpr( skip_end_check ) {
45 while( DAW_LIKELY( first < last ) ) {
54 template<
bool skip_end_check,
typename Un
signed,
typename CharT>
55 DAW_ATTRIB_FLATINLINE
inline constexpr CharT *
64 if constexpr( skip_end_check ) {
72 for( ; DAW_LIKELY( first < last ) and
83 template<
typename Result,
bool KnownRange,
typename ParseState,
84 std::enable_if_t<KnownRange, std::nullptr_t> =
nullptr>
85 [[nodiscard]] DAW_ATTRIB_FLATINLINE
inline constexpr Result
87 using CharT =
typename ParseState::CharT;
114 using max_storage_digits = daw::constant<static_cast<std::ptrdiff_t>(
115 daw::numeric_limits<std::uint64_t>::digits10 )>;
116 bool use_strtod = [&] {
117 if constexpr( std::is_floating_point_v<Result> and
118 ParseState::precise_ieee754 ) {
120 ( ( whole_last - whole_first ) +
121 ( fract_first ? fract_last - fract_first : 0 ) ) >
122 max_storage_digits::value );
128 Result
const sign = [&] {
129 if( *whole_first ==
'-' ) {
131 return static_cast<Result
>( -1.0 );
133 return static_cast<Result
>( 1.0 );
135 using max_exponent = daw::constant<static_cast<std::ptrdiff_t>(
136 daw::numeric_limits<Result>::max_digits10 + 1 )>;
138 std::conditional_t<max_storage_digits::value >= max_exponent::value,
139 std::uint64_t, Result>;
142 typename std::conditional_t<std::is_floating_point_v<unsigned_t>,
143 daw::traits::identity<unsigned_t>,
144 std::make_signed<unsigned_t>>::type;
145 std::intmax_t whole_exponent_available = whole_last - whole_first;
146 std::intmax_t fract_exponent_available =
147 fract_first ? fract_last - fract_first : 0;
148 signed_t exponent = 0;
150 if( whole_exponent_available > max_exponent::value ) {
151 whole_last = whole_first + max_exponent::value;
152 whole_exponent_available -= max_exponent::value;
153 fract_exponent_available = 0;
154 fract_first =
nullptr;
155 exponent = whole_exponent_available;
157 whole_exponent_available =
158 max_exponent::value - whole_exponent_available;
159 if constexpr( ParseState::precise_ieee754 ) {
160 use_strtod |= DAW_UNLIKELY( fract_exponent_available >
161 whole_exponent_available );
163 fract_exponent_available =
164 ( std::min )( fract_exponent_available, whole_exponent_available );
165 exponent = -fract_exponent_available;
166 fract_last = fract_first + fract_exponent_available;
169 unsigned_t significant_digits = 0;
171 ParseState::is_unchecked_input )>(
172 whole_first, whole_last, significant_digits );
175 ParseState::is_unchecked_input )>(
176 fract_first, fract_last, significant_digits );
179 if( exp_first and ( exp_last - exp_first ) > 0 ) {
180 signed_t
const exp_sign = [&] {
181 switch( *exp_first ) {
185 ErrorReason::InvalidNumber );
189 ErrorReason::InvalidNumber );
198 unsigned_t exp_result = 0;
200 if constexpr( ParseState::is_zero_terminated_string ) {
209 if( exp_first < exp_last ) {
218 if( exp_first >= exp_last ) {
229 if constexpr( std::is_floating_point_v<Result> and
230 ParseState::precise_ieee754 ) {
231 use_strtod |= DAW_UNLIKELY( exponent > 22 );
232 use_strtod |= DAW_UNLIKELY( exponent < -22 );
234 DAW_UNLIKELY( significant_digits > 9007199254740992ULL );
235 if( DAW_UNLIKELY( use_strtod ) ) {
236 return json_details::parse_with_strtod<Result>(
parse_state.first,
240 return sign * power10<Result>(
241 ParseState::exec_tag,
242 static_cast<Result
>( significant_digits ), exponent );
245 template<
typename Result,
bool KnownRange,
typename ParseState,
246 std::enable_if_t<not KnownRange, std::nullptr_t> =
nullptr>
247 [[nodiscard]] DAW_ATTRIB_FLATINLINE
inline constexpr Result
250 using CharT =
typename ParseState::CharT;
264 auto const sign =
static_cast<Result
>(
267 using max_storage_digits = daw::constant<static_cast<std::int64_t>(
268 daw::numeric_limits<std::uint64_t>::digits10 )>;
269 using max_exponent = daw::constant<static_cast<std::int64_t>(
270 daw::numeric_limits<Result>::max_digits10 + 1 )>;
272 std::conditional_t<max_storage_digits::value >= max_exponent::value,
273 std::uint64_t, Result>;
275 std::conditional_t<max_storage_digits::value >= max_exponent::value,
276 std::int64_t, Result>;
279 CharT *
const whole_last =
282 static_cast<std::ptrdiff_t
>( max_exponent::value ) );
284 unsigned_t significant_digits = 0;
287 ParseState::is_unchecked_input )>(
288 first, whole_last, significant_digits );
289 std::ptrdiff_t sig_digit_count = last_char -
parse_state.first;
291 std::is_floating_point_v<Result> and ParseState::precise_ieee754 and
292 DAW_UNLIKELY( sig_digit_count > max_storage_digits::value );
293 signed_t exponent_p1 = [&] {
294 if( DAW_UNLIKELY( last_char >= whole_last ) ) {
295 if constexpr( std::is_floating_point_v<Result> and
296 ParseState::precise_ieee754 ) {
301 CharT *ptr =
skip_digits<( ParseState::is_zero_terminated_string or
302 ParseState::is_unchecked_input )>(
304 auto const diff = ptr - last_char;
307 if( significant_digits == 0 ) {
308 return signed_t{ 0 };
310 return static_cast<signed_t
>( diff );
312 return signed_t{ 0 };
316 if( ( ParseState::is_zero_terminated_string or
317 ParseState::is_unchecked_input or
321 if( exponent_p1 != 0 ) {
323 first =
skip_digits<( ParseState::is_zero_terminated_string or
324 ParseState::is_unchecked_input )>(
330 static_cast<std::ptrdiff_t
>(
331 max_exponent::value -
335 ParseState::is_zero_terminated_string or
336 ParseState::is_unchecked_input )>( first, fract_last,
337 significant_digits );
338 sig_digit_count += last_char - first;
339 exponent_p1 -=
static_cast<signed_t
>( last_char - first );
341 if( ( first >= fract_last ) & ( first <
parse_state.last ) ) {
343 skip_digits<( ParseState::is_zero_terminated_string or
344 ParseState::is_unchecked_input )>(
346 if constexpr( std::is_floating_point_v<Result> and
347 ParseState::precise_ieee754 ) {
348 use_strtod |= new_first > first;
355 signed_t
const exponent_p2 = [&] {
356 if( ( ParseState::is_unchecked_input or first <
parse_state.last ) and
357 ( ( *first | 0x20 ) ==
'e' ) ) {
359 signed_t
const exp_sign = [&] {
362 ErrorReason::UnexpectedEndOfData,
369 ErrorReason::InvalidNumber );
370 return signed_t{ 1 };
375 ErrorReason::InvalidNumber );
376 return signed_t{ -1 };
379 ErrorReason::InvalidNumber );
380 return signed_t{ 1 };
384 ErrorReason::UnexpectedEndOfData,
386 unsigned_t exp_tmp = 0;
388 ParseState::is_zero_terminated_string or
389 ParseState::is_unchecked_input )>( first,
parse_state.last,
394 return signed_t{ 0 };
396 signed_t
const exponent = [&] {
397 if constexpr( ParseState::is_unchecked_input or
398 not std::is_floating_point_v<Result> ) {
399 return exponent_p1 + exponent_p2;
401 if(
bool matching_signs =
402 ( exponent_p1 < 0 ) == ( exponent_p2 < 0 );
403 not matching_signs ) {
405 return exponent_p1 + exponent_p2;
407 auto const s = exponent_p1 < 0 ? signed_t{ -1 } : signed_t{ 1 };
409 if( DAW_UNLIKELY( ( daw::numeric_limits<signed_t>::min( ) -
410 exponent_p1 ) > exponent_p2 ) ) {
413 return daw::numeric_limits<signed_t>::min( );
415 return exponent_p1 + exponent_p2;
417 auto r =
static_cast<unsigned_t
>( exponent_p1 ) +
418 static_cast<unsigned_t
>( exponent_p2 );
419 if( DAW_UNLIKELY( r >
420 static_cast<unsigned_t
>(
421 daw::numeric_limits<signed_t>::max( ) ) ) ) {
422 return daw::numeric_limits<signed_t>::max( );
424 return static_cast<signed_t
>( r );
429 if constexpr( std::is_floating_point_v<Result> and
430 ParseState::precise_ieee754 ) {
431 use_strtod |= DAW_UNLIKELY( exponent > 22 );
432 use_strtod |= DAW_UNLIKELY( exponent < -22 );
434 DAW_UNLIKELY( significant_digits > 9007199254740992ULL );
435 if( DAW_UNLIKELY( use_strtod ) ) {
436 return json_details::parse_with_strtod<Result>( orig_first,
440 return sign * power10<Result>(
441 ParseState::exec_tag,
442 static_cast<Result
>( significant_digits ), exponent );
#define daw_json_assert_weak(Bool,...)
Definition: daw_json_assert.h:190
ParseState & parse_state
Definition: daw_json_parse_class.h:182
constexpr DAW_ATTRIB_FLATINLINE Result parse_real(ParseState &parse_state)
Definition: daw_json_parse_real.h:86
constexpr DAW_ATTRIB_FLATINLINE CharT * skip_digits(CharT *first, CharT *const last)
Definition: daw_json_skip.h:136
constexpr DAW_ATTRIB_FLATINLINE void parse_digits_until_last(char const *first, char const *const last, Unsigned &v)
Definition: daw_json_parse_real.h:33
constexpr DAW_ATTRIB_FLATINLINE CharT * parse_digits_while_number(CharT *first, CharT *const last, Unsigned &v)
Definition: daw_json_parse_real.h:56
constexpr Signed to_signed(Unsigned &&u, Signed sign)
Definition: daw_json_parse_unsigned_int.h:38
static constexpr DAW_ATTRIB_FLATINLINE unsigned parse_digit(char c)
Definition: daw_json_parse_digit.h:19
constexpr DAW_ATTRIB_FLATINLINE int validate_signed_first(ParseState &parse_state)
Definition: daw_json_parse_policy_policy_details.h:73
constexpr DAW_ATTRIB_FLATINLINE bool is_number(char c)
Definition: daw_json_parse_policy_policy_details.h:34
constexpr DAW_ATTRIB_FLATINLINE bool is_number_start(char c)
Definition: daw_json_parse_policy_policy_details.h:107
@ Unsigned
Number - Signed Integer.
Definition: daw_from_json.h:22
#define DAW_JSON_VER
The version string used in namespace definitions. Must be a valid namespace name.
Definition: version.h:16