27 namespace json_details {
28 namespace decimal_details {
33 struct decimal_sequence {
34 static constexpr std::size_t max_digits = 768;
35 static constexpr std::int32_t decimal_point_limit = 2047;
37 std::uint8_t digits[max_digits]{ };
38 std::size_t digit_count = 0;
39 std::int32_t decimal_point = 0;
40 bool truncated =
false;
42 constexpr void push_digit(
unsigned digit ) {
43 if( digit_count < max_digits ) {
44 digits[digit_count++] =
static_cast<std::uint8_t
>( digit );
46 truncated |= digit != 0;
50 constexpr void trim( ) {
51 while( digit_count != 0 and digits[digit_count - 1] == 0 ) {
54 if( digit_count == 0 ) {
61 constexpr void shift_left(
unsigned shift ) {
62 if( digit_count == 0 or shift == 0 ) {
66 DAW_CPP23_STATIC_LOCAL
constexpr std::size_t max_growth = 19;
67 std::uint8_t result[max_digits + max_growth]{ };
68 auto write = max_digits + max_growth;
69 auto read = digit_count;
70 std::uint64_t carry = 0;
71 auto const factor = std::uint64_t{ 1 } << shift;
76 static_cast<std::uint64_t
>( digits[read] ) * factor + carry;
77 result[--write] =
static_cast<std::uint8_t
>( value % 10U );
81 result[--write] =
static_cast<std::uint8_t
>( carry % 10U );
85 auto const result_count = max_digits + max_growth - write;
86 auto const growth = result_count - digit_count;
87 decimal_point +=
static_cast<std::int32_t
>( growth );
89 auto const stored_count =
90 result_count < max_digits ? result_count : max_digits;
91 for( std::size_t n = 0; n < stored_count; ++n ) {
92 digits[n] = result[write + n];
94 for(
auto n = stored_count; n < result_count; ++n ) {
95 truncated |= result[write + n] != 0;
97 digit_count = stored_count;
102 constexpr void shift_right(
unsigned shift ) {
103 if( digit_count == 0 or shift == 0 ) {
107 std::size_t read = 0;
108 std::size_t write = 0;
109 std::uint64_t value = 0;
110 while( ( value >> shift ) == 0 ) {
111 if( read < digit_count ) {
113 value * 10U +
static_cast<std::uint64_t
>( digits[read++] );
114 }
else if( value == 0 ) {
120 }
while( ( value >> shift ) == 0 );
125 decimal_point -=
static_cast<std::int32_t
>( read - 1 );
126 if( decimal_point < -decimal_point_limit ) {
133 auto const mask = ( std::uint64_t{ 1 } << shift ) - 1U;
134 while( read < digit_count ) {
135 auto const digit =
static_cast<std::uint8_t
>( value >> shift );
136 value = 10U * ( value & mask ) +
137 static_cast<std::uint64_t
>( digits[read++] );
138 digits[write++] = digit;
140 while( value != 0 ) {
141 auto const digit =
static_cast<std::uint8_t
>( value >> shift );
142 value = 10U * ( value & mask );
143 if( write < max_digits ) {
144 digits[write++] = digit;
146 truncated |= digit != 0;
153 [[nodiscard]]
constexpr std::uint64_t round( )
const {
154 if( digit_count == 0 or decimal_point < 0 ) {
157 if( decimal_point >= 19 ) {
158 return daw::max_value<std::uint64_t>;
161 auto const point =
static_cast<std::size_t
>( decimal_point );
162 std::uint64_t result = 0;
163 for( std::size_t n = 0; n < point; ++n ) {
165 if( n < digit_count ) {
170 bool round_up =
false;
171 if( point < digit_count ) {
172 round_up = digits[point] >= 5;
173 if( digits[point] == 5 and point + 1 == digit_count ) {
175 truncated or ( point != 0 and ( digits[point - 1] & 1U ) );
178 return result +
static_cast<std::uint64_t
>( round_up );
182 [[nodiscard]]
constexpr std::int64_t
183 saturating_add( std::int64_t lhs, std::int64_t rhs ) {
184 DAW_CPP23_STATIC_LOCAL
constexpr auto max_value =
185 daw::max_value<std::int64_t>;
186 DAW_CPP23_STATIC_LOCAL
constexpr auto lowest_value =
187 daw::lowest_value<std::int64_t>;
189 if( rhs > 0 and lhs > max_value - rhs ) {
192 if( rhs < 0 and lhs < lowest_value - rhs ) {
198 [[nodiscard]]
constexpr std::int64_t
199 parse_exponent(
char const *first,
char const *last ) {
200 if( first ==
nullptr or first == last ) {
204 bool negative =
false;
205 if( *first ==
'+' or *first ==
'-' ) {
206 negative = *first ==
'-';
210 DAW_CPP23_STATIC_LOCAL
constexpr auto positive_limit =
211 static_cast<std::uint64_t
>( daw::max_value<std::int64_t> );
212 DAW_CPP23_STATIC_LOCAL
constexpr auto negative_limit =
214 auto const limit = negative ? negative_limit : positive_limit;
215 std::uint64_t result = 0;
216 bool overflow =
false;
217 while( first < last ) {
218 auto const digit = parse_digit( *first++ );
222 if( result > ( limit - digit ) / 10U ) {
225 }
else if( not overflow ) {
226 result = result * 10U + digit;
231 if( result == negative_limit ) {
232 return daw::lowest_value<std::int64_t>;
234 return -
static_cast<std::int64_t
>( result );
236 return static_cast<std::int64_t
>( result );
239 [[nodiscard]]
constexpr decimal_sequence
240 parse_json_decimal( daw::not_null<char const *> first,
241 daw::not_null<char const *>
const last ) {
242 decimal_sequence result{ };
243 if( *first ==
'-' ) {
247 std::int64_t decimal_point = 0;
248 bool seen_nonzero =
false;
249 while( first < last and parse_digit( *first ) < 10U ) {
250 auto const digit = parse_digit( *first++ );
251 if( seen_nonzero or digit != 0 ) {
253 result.push_digit( digit );
258 if( first < last and *first ==
'.' ) {
260 while( first < last and parse_digit( *first ) < 10U ) {
261 auto const digit = parse_digit( *first++ );
262 if( seen_nonzero or digit != 0 ) {
264 result.push_digit( digit );
271 char const *exponent_first =
nullptr;
272 if( first < last and ( *first ==
'e' or *first ==
'E' ) ) {
273 exponent_first = ++first;
275 decimal_point = saturating_add(
276 decimal_point, parse_exponent( exponent_first, last.get( ) ) );
278 if( not seen_nonzero ) {
279 result.digit_count = 0;
280 result.decimal_point = 0;
281 result.truncated =
false;
285 if( decimal_point > decimal_sequence::decimal_point_limit ) {
286 result.decimal_point = decimal_sequence::decimal_point_limit;
287 }
else if( decimal_point < -decimal_sequence::decimal_point_limit ) {
288 result.decimal_point = -decimal_sequence::decimal_point_limit;
290 result.decimal_point =
static_cast<std::int32_t
>( decimal_point );
296 [[nodiscard]]
constexpr unsigned
297 shift_amount( std::int32_t decimal_places ) {
298 constexpr unsigned powers[19] = {
299 0, 3, 6, 9, 13, 16, 19, 23, 26, 29,
300 33, 36, 39, 43, 46, 49, 53, 56, 59,
302 auto const places =
static_cast<std::uint32_t
>(
303 decimal_places < 0 ? -decimal_places : decimal_places );
304 return places < 19U ? powers[places] : 60U;
307 template<
typename Real>
308 [[nodiscard]]
constexpr Real pack_real(
bool negative,
309 std::uint64_t mantissa,
310 std::int32_t power2 ) {
311 using format = eisellemire_details::binary_format<Real>;
312 using uint_type =
typename format::uint_type;
313 auto const bits =
static_cast<uint_type
>(
315 (
static_cast<std::uint64_t
>( power2 ) << format::mantissa_bits ) |
316 (
static_cast<std::uint64_t
>( negative ) << format::sign_bit ) );
317 return DAW_BIT_CAST( Real, bits );
321 template<
typename Real>
322 [[nodiscard]]
constexpr Real
323 parse_json_real_exact(
bool negative, daw::not_null<char const *> first,
324 daw::not_null<char const *> last ) {
325 using format = eisellemire_details::binary_format<Real>;
326 auto decimal = decimal_details::parse_json_decimal( first, last );
328 if( decimal.digit_count == 0 ) {
329 return decimal_details::pack_real<Real>( negative, 0, 0 );
334 DAW_CPP23_STATIC_LOCAL
constexpr std::int32_t smallest_decimal_point =
335 std::numeric_limits<Real>::min_exponent10 -
336 std::numeric_limits<Real>::digits10 - 2;
337 DAW_CPP23_STATIC_LOCAL
constexpr std::int32_t largest_decimal_point =
338 std::numeric_limits<Real>::max_exponent10 + 2;
339 if( decimal.decimal_point < smallest_decimal_point ) {
340 return decimal_details::pack_real<Real>( negative, 0, 0 );
342 if( decimal.decimal_point >= largest_decimal_point ) {
343 return decimal_details::pack_real<Real>(
344 negative, 0, format::infinite_power );
347 std::int32_t exponent2 = 0;
348 while( decimal.decimal_point > 0 ) {
350 decimal_details::shift_amount( decimal.decimal_point );
351 decimal.shift_right( shift );
352 exponent2 +=
static_cast<std::int32_t
>( shift );
354 while( decimal.decimal_point <= 0 ) {
356 if( decimal.decimal_point == 0 ) {
357 if( decimal.digits[0] >= 5 ) {
360 shift = decimal.digits[0] <= 1 ? 2U : 1U;
362 shift = decimal_details::shift_amount( decimal.decimal_point );
364 decimal.shift_left( shift );
365 exponent2 -=
static_cast<std::int32_t
>( shift );
370 DAW_CPP23_STATIC_LOCAL
constexpr auto minimum_exponent =
371 1 - format::exponent_bias;
372 while( exponent2 < minimum_exponent ) {
373 auto shift = minimum_exponent - exponent2;
377 decimal.shift_right(
static_cast<unsigned>( shift ) );
381 if( exponent2 - minimum_exponent + 1 >= format::infinite_power ) {
382 return decimal_details::pack_real<Real>(
383 negative, 0, format::infinite_power );
387 static_cast<unsigned>( format::mantissa_bits + 1 ) );
388 auto mantissa = decimal.round( );
390 ( std::uint64_t{ 1 } << ( format::mantissa_bits + 1 ) ) ) {
391 decimal.shift_right( 1 );
393 mantissa = decimal.round( );
394 if( exponent2 - minimum_exponent + 1 >= format::infinite_power ) {
395 return decimal_details::pack_real<Real>(
396 negative, 0, format::infinite_power );
400 auto power2 = exponent2 - minimum_exponent + 1;
401 if( mantissa < ( std::uint64_t{ 1 } << format::mantissa_bits ) ) {
404 mantissa &= ( std::uint64_t{ 1 } << format::mantissa_bits ) - 1U;
405 return decimal_details::pack_real<Real>( negative, mantissa, power2 );