26 namespace json_details {
27 namespace decimal_details {
32 struct decimal_sequence {
33 static constexpr std::size_t max_digits = 768;
34 static constexpr std::int32_t decimal_point_limit = 2047;
36 std::uint8_t digits[max_digits]{ };
37 std::size_t digit_count = 0;
38 std::int32_t decimal_point = 0;
39 bool truncated =
false;
41 constexpr void push_digit(
unsigned digit ) {
42 if( digit_count < max_digits ) {
43 digits[digit_count++] =
static_cast<std::uint8_t
>( digit );
45 truncated |= digit != 0;
49 constexpr void trim( ) {
50 while( digit_count != 0 and digits[digit_count - 1] == 0 ) {
53 if( digit_count == 0 ) {
60 constexpr void shift_left(
unsigned shift ) {
61 if( digit_count == 0 or shift == 0 ) {
65 DAW_CPP23_STATIC_LOCAL
constexpr std::size_t max_growth = 19;
66 std::uint8_t result[max_digits + max_growth]{ };
67 auto write = max_digits + max_growth;
68 auto read = digit_count;
69 std::uint64_t carry = 0;
70 auto const factor = std::uint64_t{ 1 } << shift;
75 static_cast<std::uint64_t
>( digits[read] ) * factor + carry;
76 result[--write] =
static_cast<std::uint8_t
>( value % 10U );
80 result[--write] =
static_cast<std::uint8_t
>( carry % 10U );
84 auto const result_count = max_digits + max_growth - write;
85 auto const growth = result_count - digit_count;
86 decimal_point +=
static_cast<std::int32_t
>( growth );
88 auto const stored_count =
89 result_count < max_digits ? result_count : max_digits;
90 for( std::size_t n = 0; n < stored_count; ++n ) {
91 digits[n] = result[write + n];
93 for(
auto n = stored_count; n < result_count; ++n ) {
94 truncated |= result[write + n] != 0;
96 digit_count = stored_count;
101 constexpr void shift_right(
unsigned shift ) {
102 if( digit_count == 0 or shift == 0 ) {
106 std::size_t read = 0;
107 std::size_t write = 0;
108 std::uint64_t value = 0;
109 while( ( value >> shift ) == 0 ) {
110 if( read < digit_count ) {
112 value * 10U +
static_cast<std::uint64_t
>( digits[read++] );
113 }
else if( value == 0 ) {
119 }
while( ( value >> shift ) == 0 );
124 decimal_point -=
static_cast<std::int32_t
>( read - 1 );
125 if( decimal_point < -decimal_point_limit ) {
132 auto const mask = ( std::uint64_t{ 1 } << shift ) - 1U;
133 while( read < digit_count ) {
134 auto const digit =
static_cast<std::uint8_t
>( value >> shift );
135 value = 10U * ( value & mask ) +
136 static_cast<std::uint64_t
>( digits[read++] );
137 digits[write++] = digit;
139 while( value != 0 ) {
140 auto const digit =
static_cast<std::uint8_t
>( value >> shift );
141 value = 10U * ( value & mask );
142 if( write < max_digits ) {
143 digits[write++] = digit;
145 truncated |= digit != 0;
152 [[nodiscard]]
constexpr std::uint64_t round( )
const {
153 if( digit_count == 0 or decimal_point < 0 ) {
156 if( decimal_point >= 19 ) {
157 return daw::max_value<std::uint64_t>;
160 auto const point =
static_cast<std::size_t
>( decimal_point );
161 std::uint64_t result = 0;
162 for( std::size_t n = 0; n < point; ++n ) {
164 if( n < digit_count ) {
169 bool round_up =
false;
170 if( point < digit_count ) {
171 round_up = digits[point] >= 5;
172 if( digits[point] == 5 and point + 1 == digit_count ) {
174 truncated or ( point != 0 and ( digits[point - 1] & 1U ) );
177 return result +
static_cast<std::uint64_t
>( round_up );
181 [[nodiscard]]
constexpr std::int64_t
182 saturating_add( std::int64_t lhs, std::int64_t rhs ) {
183 DAW_CPP23_STATIC_LOCAL
constexpr auto max_value =
184 daw::max_value<std::int64_t>;
185 DAW_CPP23_STATIC_LOCAL
constexpr auto lowest_value =
186 daw::lowest_value<std::int64_t>;
188 if( rhs > 0 and lhs > max_value - rhs ) {
191 if( rhs < 0 and lhs < lowest_value - rhs ) {
197 [[nodiscard]]
constexpr std::int64_t
198 parse_exponent(
char const *first,
char const *last ) {
199 if( first ==
nullptr or first == last ) {
203 bool negative =
false;
204 if( *first ==
'+' or *first ==
'-' ) {
205 negative = *first ==
'-';
209 DAW_CPP23_STATIC_LOCAL
constexpr auto positive_limit =
210 static_cast<std::uint64_t
>( daw::max_value<std::int64_t> );
211 DAW_CPP23_STATIC_LOCAL
constexpr auto negative_limit =
213 auto const limit = negative ? negative_limit : positive_limit;
214 std::uint64_t result = 0;
215 bool overflow =
false;
216 while( first < last ) {
217 auto const digit = parse_digit( *first++ );
221 if( result > ( limit - digit ) / 10U ) {
224 }
else if( not overflow ) {
225 result = result * 10U + digit;
230 if( result == negative_limit ) {
231 return daw::lowest_value<std::int64_t>;
233 return -
static_cast<std::int64_t
>( result );
235 return static_cast<std::int64_t
>( result );
238 [[nodiscard]]
constexpr decimal_sequence
239 parse_json_decimal( daw::not_null<char const *> first,
240 daw::not_null<char const *>
const last ) {
241 decimal_sequence result{ };
242 if( *first ==
'-' ) {
246 std::int64_t decimal_point = 0;
247 bool seen_nonzero =
false;
248 while( first < last and parse_digit( *first ) < 10U ) {
249 auto const digit = parse_digit( *first++ );
250 if( seen_nonzero or digit != 0 ) {
252 result.push_digit( digit );
257 if( first < last and *first ==
'.' ) {
259 while( first < last and parse_digit( *first ) < 10U ) {
260 auto const digit = parse_digit( *first++ );
261 if( seen_nonzero or digit != 0 ) {
263 result.push_digit( digit );
270 char const *exponent_first =
nullptr;
271 if( first < last and ( *first ==
'e' or *first ==
'E' ) ) {
272 exponent_first = ++first;
274 decimal_point = saturating_add(
275 decimal_point, parse_exponent( exponent_first, last.get( ) ) );
277 if( not seen_nonzero ) {
278 result.digit_count = 0;
279 result.decimal_point = 0;
280 result.truncated =
false;
284 if( decimal_point > decimal_sequence::decimal_point_limit ) {
285 result.decimal_point = decimal_sequence::decimal_point_limit;
286 }
else if( decimal_point < -decimal_sequence::decimal_point_limit ) {
287 result.decimal_point = -decimal_sequence::decimal_point_limit;
289 result.decimal_point =
static_cast<std::int32_t
>( decimal_point );
295 [[nodiscard]]
constexpr unsigned
296 shift_amount( std::int32_t decimal_places ) {
297 constexpr unsigned powers[19] = {
298 0, 3, 6, 9, 13, 16, 19, 23, 26, 29,
299 33, 36, 39, 43, 46, 49, 53, 56, 59,
301 auto const places =
static_cast<std::uint32_t
>(
302 decimal_places < 0 ? -decimal_places : decimal_places );
303 return places < 19U ? powers[places] : 60U;
306 template<
typename Real>
307 [[nodiscard]]
constexpr Real pack_real(
bool negative,
308 std::uint64_t mantissa,
309 std::int32_t power2 ) {
310 using format = eisellemire_details::binary_format<Real>;
311 using uint_type =
typename format::uint_type;
312 auto const bits =
static_cast<uint_type
>(
314 (
static_cast<std::uint64_t
>( power2 ) << format::mantissa_bits ) |
315 (
static_cast<std::uint64_t
>( negative ) << format::sign_bit ) );
316 return DAW_BIT_CAST( Real, bits );
320 template<
typename Real>
321 [[nodiscard]]
constexpr Real
322 parse_json_real_exact(
bool negative, daw::not_null<char const *> first,
323 daw::not_null<char const *> last ) {
324 static_assert( std::is_same_v<Real, float> or
325 std::is_same_v<Real, double> );
326 using format = eisellemire_details::binary_format<Real>;
327 auto decimal = decimal_details::parse_json_decimal( first, last );
329 if( decimal.digit_count == 0 ) {
330 return decimal_details::pack_real<Real>( negative, 0, 0 );
333 DAW_CPP23_STATIC_LOCAL
constexpr std::int32_t
334 smallest_decimal_point = std::is_same_v<Real, double> ? -324 : -45;
335 DAW_CPP23_STATIC_LOCAL
constexpr std::int32_t largest_decimal_point =
336 std::is_same_v<Real, double> ? 310 : 40;
337 if( decimal.decimal_point < smallest_decimal_point ) {
338 return decimal_details::pack_real<Real>( negative, 0, 0 );
340 if( decimal.decimal_point >= largest_decimal_point ) {
341 return decimal_details::pack_real<Real>(
342 negative, 0, format::infinite_power );
345 std::int32_t exponent2 = 0;
346 while( decimal.decimal_point > 0 ) {
348 decimal_details::shift_amount( decimal.decimal_point );
349 decimal.shift_right( shift );
350 exponent2 +=
static_cast<std::int32_t
>( shift );
352 while( decimal.decimal_point <= 0 ) {
354 if( decimal.decimal_point == 0 ) {
355 if( decimal.digits[0] >= 5 ) {
358 shift = decimal.digits[0] <= 1 ? 2U : 1U;
360 shift = decimal_details::shift_amount( decimal.decimal_point );
362 decimal.shift_left( shift );
363 exponent2 -=
static_cast<std::int32_t
>( shift );
368 DAW_CPP23_STATIC_LOCAL
constexpr auto minimum_exponent =
369 1 - format::exponent_bias;
370 while( exponent2 < minimum_exponent ) {
371 auto shift = minimum_exponent - exponent2;
375 decimal.shift_right(
static_cast<unsigned>( shift ) );
379 if( exponent2 - minimum_exponent + 1 >= format::infinite_power ) {
380 return decimal_details::pack_real<Real>(
381 negative, 0, format::infinite_power );
385 static_cast<unsigned>( format::mantissa_bits + 1 ) );
386 auto mantissa = decimal.round( );
388 ( std::uint64_t{ 1 } << ( format::mantissa_bits + 1 ) ) ) {
389 decimal.shift_right( 1 );
391 mantissa = decimal.round( );
392 if( exponent2 - minimum_exponent + 1 >= format::infinite_power ) {
393 return decimal_details::pack_real<Real>(
394 negative, 0, format::infinite_power );
398 auto power2 = exponent2 - minimum_exponent + 1;
399 if( mantissa < ( std::uint64_t{ 1 } << format::mantissa_bits ) ) {
402 mantissa &= ( std::uint64_t{ 1 } << format::mantissa_bits ) - 1U;
403 return decimal_details::pack_real<Real>( negative, mantissa, power2 );