18 #include <daw/daw_cxmath.h>
19 #include <daw/daw_likely.h>
25 #include <type_traits>
29 namespace json_details {
30 template<
bool skip_end_check,
typename Un
signed>
31 DAW_ATTRIB_FLATINLINE
inline constexpr
void
35 if constexpr( skip_end_check ) {
44 while( DAW_LIKELY( first < last ) ) {
53 template<
bool skip_end_check,
typename Un
signed,
typename CharT>
54 DAW_ATTRIB_FLATINLINE
inline constexpr CharT *
63 if constexpr( skip_end_check ) {
73 while( DAW_LIKELY( first < last ) and
84 template<
typename Result,
bool KnownRange,
typename ParseState,
85 std::enable_if_t<KnownRange, std::nullptr_t> =
nullptr>
86 [[nodiscard]] DAW_ATTRIB_FLATINLINE
inline constexpr Result
88 using CharT =
typename ParseState::CharT;
115 constexpr
auto max_storage_digits =
static_cast<std::ptrdiff_t
>(
116 daw::numeric_limits<std::uint64_t>::digits10 );
117 bool use_strtod = [&] {
118 if constexpr( std::is_floating_point_v<Result> and
119 ParseState::precise_ieee754 ) {
120 return DAW_UNLIKELY( ( ( whole_last - whole_first ) +
121 ( fract_first ? fract_last - fract_first
122 : 0 ) ) > max_storage_digits );
128 Result
const sign = [&] {
129 if( *whole_first ==
'-' ) {
131 return static_cast<Result
>( -1.0 );
133 return static_cast<Result
>( 1.0 );
135 constexpr
auto max_exponent =
static_cast<std::ptrdiff_t
>(
136 daw::numeric_limits<Result>::max_digits10 + 1 );
138 std::conditional_t<max_storage_digits >= max_exponent, std::uint64_t,
141 std::ptrdiff_t whole_exponent_available = whole_last - whole_first;
142 std::ptrdiff_t fract_exponent_available =
143 fract_first ? fract_last - fract_first : 0;
144 std::ptrdiff_t exponent = 0;
146 if( whole_exponent_available > max_exponent ) {
147 whole_last = whole_first + max_exponent;
148 whole_exponent_available -= max_exponent;
149 fract_exponent_available = 0;
150 fract_first =
nullptr;
151 exponent = whole_exponent_available;
153 whole_exponent_available = max_exponent - whole_exponent_available;
154 if constexpr( ParseState::precise_ieee754 ) {
155 use_strtod |= DAW_UNLIKELY( fract_exponent_available >
156 whole_exponent_available );
158 fract_exponent_available =
159 std::min( fract_exponent_available, whole_exponent_available );
160 exponent = -fract_exponent_available;
161 fract_last = fract_first + fract_exponent_available;
164 unsigned_t significant_digits = 0;
166 ParseState::is_unchecked_input )>(
167 whole_first, whole_last, significant_digits );
170 ParseState::is_unchecked_input )>(
171 fract_first, fract_last, significant_digits );
174 if( exp_first and ( exp_last - exp_first ) > 0 ) {
175 int const exp_sign = [&] {
176 switch( *exp_first ) {
180 ErrorReason::InvalidNumber );
184 ErrorReason::InvalidNumber );
191 exponent += exp_sign * [&] {
192 std::ptrdiff_t r = 0;
194 if constexpr( ParseState::is_zero_terminated_string ) {
203 if( exp_first < exp_last ) {
212 if( exp_first >= exp_last ) {
222 if constexpr( std::is_floating_point_v<Result> and
223 ParseState::precise_ieee754 ) {
224 use_strtod |= DAW_UNLIKELY( exponent > 22 );
225 use_strtod |= DAW_UNLIKELY( exponent < -22 );
226 use_strtod |= DAW_UNLIKELY( significant_digits > 9007199254740992 );
227 if( DAW_UNLIKELY( use_strtod ) ) {
228 return json_details::parse_with_strtod<Result>(
parse_state.first,
232 return sign * power10<Result>(
233 ParseState::exec_tag,
234 static_cast<Result
>( significant_digits ), exponent );
237 template<
typename Result,
bool KnownRange,
typename ParseState,
238 std::enable_if_t<not KnownRange, std::nullptr_t> =
nullptr>
239 [[nodiscard]] DAW_ATTRIB_FLATINLINE
inline constexpr Result
242 using CharT =
typename ParseState::CharT;
256 auto const sign =
static_cast<Result
>(
259 constexpr
auto max_storage_digits =
static_cast<std::ptrdiff_t
>(
260 daw::numeric_limits<std::uint64_t>::digits10 );
261 constexpr
auto max_exponent =
static_cast<std::ptrdiff_t
>(
262 daw::numeric_limits<Result>::max_digits10 + 1 );
264 std::conditional_t<max_storage_digits >= max_exponent, std::uint64_t,
267 std::conditional_t<max_storage_digits >= max_exponent, int, Result>;
270 CharT *
const whole_last =
274 unsigned_t significant_digits = 0;
277 ParseState::is_unchecked_input )>(
278 first, whole_last, significant_digits );
279 std::ptrdiff_t sig_digit_count = last_char -
parse_state.first;
280 bool use_strtod = std::is_floating_point_v<Result> and
281 ParseState::precise_ieee754 and
282 DAW_UNLIKELY( sig_digit_count > max_storage_digits );
283 signed_t exponent = [&] {
284 if( DAW_UNLIKELY( last_char >= whole_last ) ) {
285 if constexpr( std::is_floating_point_v<Result> and
286 ParseState::precise_ieee754 ) {
291 CharT *ptr =
skip_digits<( ParseState::is_zero_terminated_string or
292 ParseState::is_unchecked_input )>(
294 auto const diff = ptr - last_char;
297 return static_cast<signed_t
>( diff );
299 return static_cast<signed_t
>( 0 );
301 if( significant_digits == 0 ) {
305 if( ( ParseState::is_zero_terminated_string or
306 ParseState::is_unchecked_input or
310 if( exponent != 0 ) {
312 first =
skip_digits<( ParseState::is_zero_terminated_string or
313 ParseState::is_unchecked_input )>(
320 static_cast<std::ptrdiff_t
>(
324 ParseState::is_zero_terminated_string or
325 ParseState::is_unchecked_input )>( first, fract_last,
326 significant_digits );
327 sig_digit_count += last_char - first;
328 exponent -=
static_cast<signed_t
>( last_char - first );
330 if( ( first >= fract_last ) & ( first <
parse_state.last ) ) {
332 skip_digits<( ParseState::is_zero_terminated_string or
333 ParseState::is_unchecked_input )>(
335 if constexpr( std::is_floating_point_v<Result> and
336 ParseState::precise_ieee754 ) {
337 use_strtod |= new_first > first;
345 if( ( ParseState::is_unchecked_input or first <
parse_state.last ) and
346 ( ( *first | 0x20 ) ==
'e' ) ) {
348 bool const exp_sign = [&] {
351 ErrorReason::UnexpectedEndOfData,
358 ErrorReason::InvalidNumber );
364 ErrorReason::InvalidNumber );
368 ErrorReason::InvalidNumber );
373 ErrorReason::UnexpectedEndOfData,
375 unsigned_t exp_tmp = 0;
377 ParseState::is_zero_terminated_string or
378 ParseState::is_unchecked_input )>( first,
parse_state.last,
382 return -
static_cast<signed_t
>( exp_tmp );
384 return static_cast<signed_t
>( exp_tmp );
386 return static_cast<signed_t
>( 0 );
390 if constexpr( std::is_floating_point_v<Result> and
391 ParseState::precise_ieee754 ) {
392 use_strtod |= DAW_UNLIKELY( exponent > 22 );
393 use_strtod |= DAW_UNLIKELY( exponent < -22 );
395 DAW_UNLIKELY( significant_digits > 9007199254740992ULL );
396 if( DAW_UNLIKELY( use_strtod ) ) {
397 return json_details::parse_with_strtod<Result>( orig_first,
401 return sign * power10<Result>(
402 ParseState::exec_tag,
403 static_cast<Result
>( significant_digits ), exponent );
#define daw_json_assert_weak(Bool,...)
Definition: daw_json_assert.h:189
ParseState & parse_state
Definition: daw_json_parse_class.h:201
constexpr DAW_ATTRIB_FLATINLINE Result parse_real(ParseState &parse_state)
Definition: daw_json_parse_real.h:87
constexpr DAW_ATTRIB_FLATINLINE void parse_digits_until_last(char const *first, char const *const last, Unsigned &v)
Definition: daw_json_parse_real.h:32
constexpr DAW_ATTRIB_FLATINLINE CharT * skip_digits(CharT *first, CharT *const last)
Definition: daw_json_skip.h:133
constexpr DAW_ATTRIB_FLATINLINE CharT * parse_digits_while_number(CharT *first, CharT *const last, Unsigned &v)
Definition: daw_json_parse_real.h:55
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:106
Definition: daw_from_json.h:22
#define DAW_JSON_VER
Definition: version.h:11