1#ifndef SIMDJSON_GENERIC_NUMBERPARSING_H
3#ifndef SIMDJSON_CONDITIONAL_INCLUDE
4#define SIMDJSON_GENERIC_NUMBERPARSING_H
5#include "simdjson/generic/base.h"
6#include "simdjson/generic/jsoncharutils.h"
7#include "simdjson/generic/atomparsing.h"
8#include "simdjson/internal/numberparsing_tables.h"
16namespace SIMDJSON_IMPLEMENTATION {
17namespace numberparsing {
19#ifdef JSON_TEST_NUMBERS
20#define INVALID_NUMBER(SRC) (found_invalid_number((SRC)), NUMBER_ERROR)
21#define WRITE_INTEGER(VALUE, SRC, WRITER) (found_integer((VALUE), (SRC)), (WRITER).append_s64((VALUE)))
22#define WRITE_UNSIGNED(VALUE, SRC, WRITER) (found_unsigned_integer((VALUE), (SRC)), (WRITER).append_u64((VALUE)))
23#define WRITE_DOUBLE(VALUE, SRC, WRITER) (found_float((VALUE), (SRC)), (WRITER).append_double((VALUE)))
24#define BIGINT_NUMBER(SRC) (found_invalid_number((SRC)), BIGINT_ERROR)
26#define INVALID_NUMBER(SRC) (NUMBER_ERROR)
27#define WRITE_INTEGER(VALUE, SRC, WRITER) (WRITER).append_s64((VALUE))
28#define WRITE_UNSIGNED(VALUE, SRC, WRITER) (WRITER).append_u64((VALUE))
29#define WRITE_DOUBLE(VALUE, SRC, WRITER) (WRITER).append_double((VALUE))
30#define BIGINT_NUMBER(SRC) (BIGINT_ERROR)
38simdjson_inline
double to_double(uint64_t mantissa, uint64_t real_exponent,
bool negative) {
40 mantissa &= ~(1ULL << 52);
41 mantissa |= real_exponent << 52;
42 mantissa |= ((
static_cast<uint64_t
>(negative)) << 63);
43 std::memcpy(&d, &mantissa,
sizeof(d));
50simdjson_inline
float to_float(uint32_t mantissa, uint32_t real_exponent,
bool negative) {
52 mantissa &= ~(uint32_t(1) << 23);
53 mantissa |= real_exponent << 23;
54 mantissa |= ((
static_cast<uint32_t
>(negative)) << 31);
55 std::memcpy(&f, &mantissa,
sizeof(f));
65simdjson_inline
bool compute_float_64(int64_t power, uint64_t i,
bool negative,
double &d) {
70#ifndef FLT_EVAL_METHOD
71#error "FLT_EVAL_METHOD should be defined, please include cfloat."
73#if (FLT_EVAL_METHOD != 1) && (FLT_EVAL_METHOD != 0)
75 if (0 <= power && power <= 22 && i <= 9007199254740991)
77 if (-22 <= power && power <= 22 && i <= 9007199254740991)
94 d = d / simdjson::internal::power_of_ten[-power];
96 d = d * simdjson::internal::power_of_ten[power];
126 d = negative ? -0.0 : 0.0;
157 int64_t exponent = (((152170 + 65536) * power) >> 16) + 1024 + 63;
161 int lz = leading_zeroes(i);
176 const uint32_t index = 2 * uint32_t(power - simdjson::internal::smallest_power);
183#if SIMDJSON_STATIC_REFLECTION
184 simdjson::internal::value128 firstproduct = full_multiplication(i, simdjson::internal::powers_template<>::power_of_five_128[index]);
186 simdjson::internal::value128 firstproduct = full_multiplication(i, simdjson::internal::power_of_five_128[index]);
200 if((firstproduct.high & 0x1FF) == 0x1FF) {
221#if SIMDJSON_STATIC_REFLECTION
222 simdjson::internal::value128 secondproduct = full_multiplication(i, simdjson::internal::powers_template<>::power_of_five_128[index + 1]);
224 simdjson::internal::value128 secondproduct = full_multiplication(i, simdjson::internal::power_of_five_128[index + 1]);
226 firstproduct.low += secondproduct.high;
227 if(secondproduct.high > firstproduct.low) { firstproduct.high++; }
232 uint64_t lower = firstproduct.low;
233 uint64_t upper = firstproduct.high;
237 uint64_t upperbit = upper >> 63;
238 uint64_t mantissa = upper >> (upperbit + 9);
239 lz += int(1 ^ upperbit);
242 int64_t real_exponent = exponent - lz;
243 if (simdjson_unlikely(real_exponent <= 0)) {
245 if(-real_exponent + 1 >= 64) {
246 d = negative ? -0.0 : 0.0;
250 mantissa >>= -real_exponent + 1;
253 mantissa += (mantissa & 1);
262 real_exponent = (mantissa < (uint64_t(1) << 52)) ? 0 : 1;
263 d = to_double(mantissa, real_exponent, negative);
288 if (simdjson_unlikely((lower <= 1) && (power >= -4) && (power <= 23) && ((mantissa & 3) == 1))) {
289 if((mantissa << (upperbit + 64 - 53 - 2)) == upper) {
294 mantissa += mantissa & 1;
298 if (mantissa >= (1ULL << 53)) {
302 mantissa = (1ULL << 52);
305 mantissa &= ~(1ULL << 52);
307 if (simdjson_unlikely(real_exponent > 2046)) {
311 d = to_double(mantissa, real_exponent, negative);
340simdjson_inline
bool compute_float_32(int64_t power, uint64_t i,
bool negative,
float &d) {
343 static constexpr float power_of_ten_float[] = {
344 1e0f, 1e1f, 1e2f, 1e3f, 1e4f, 1e5f,
345 1e6f, 1e7f, 1e8f, 1e9f, 1e10f};
350 constexpr int smallest_power_binary32 = -65;
351 constexpr int largest_power_binary32 = 38;
356#ifndef FLT_EVAL_METHOD
357#error "FLT_EVAL_METHOD should be defined, please include cfloat."
359#if (FLT_EVAL_METHOD != 1) && (FLT_EVAL_METHOD != 0)
361 if (0 <= power && power <= 10 && i <= 16777215)
363 if (-10 <= power && power <= 10 && i <= 16777215)
372 d = d / power_of_ten_float[-power];
374 d = d * power_of_ten_float[power];
387 if (i == 0 || power < smallest_power_binary32) {
388 d = negative ? -0.0f : 0.0f;
391 if (power > largest_power_binary32) {
400 int64_t exponent = (((152170 + 65536) * power) >> 16) + 128 + 63;
403 int lz = leading_zeroes(i);
410 const uint32_t index = 2 * uint32_t(power - simdjson::internal::smallest_power);
411#if SIMDJSON_STATIC_REFLECTION
412 simdjson::internal::value128 firstproduct = full_multiplication(i, simdjson::internal::powers_template<>::power_of_five_128[index]);
414 simdjson::internal::value128 firstproduct = full_multiplication(i, simdjson::internal::power_of_five_128[index]);
423 if((firstproduct.high & 0x3FFFFFFFFF) == 0x3FFFFFFFFF) {
427#if SIMDJSON_STATIC_REFLECTION
428 simdjson::internal::value128 secondproduct = full_multiplication(i, simdjson::internal::powers_template<>::power_of_five_128[index + 1]);
430 simdjson::internal::value128 secondproduct = full_multiplication(i, simdjson::internal::power_of_five_128[index + 1]);
432 firstproduct.low += secondproduct.high;
433 if(secondproduct.high > firstproduct.low) { firstproduct.high++; }
435 uint64_t lower = firstproduct.low;
436 uint64_t upper = firstproduct.high;
440 uint64_t upperbit = upper >> 63;
441 uint64_t mantissa = upper >> (upperbit + 38);
442 lz += int(1 ^ upperbit);
445 int64_t real_exponent = exponent - lz;
446 if (simdjson_unlikely(real_exponent <= 0)) {
448 if(-real_exponent + 1 >= 64) {
449 d = negative ? -0.0f : 0.0f;
453 mantissa >>= -real_exponent + 1;
456 mantissa += (mantissa & 1);
460 real_exponent = (mantissa < (uint64_t(1) << 23)) ? 0 : 1;
461 d = to_float(uint32_t(mantissa), uint32_t(real_exponent), negative);
470 if (simdjson_unlikely((lower <= 1) && (power >= -17) && (power <= 10) && ((mantissa & 3) == 1))) {
471 if((mantissa << (upperbit + 38)) == upper) {
472 mantissa &= ~uint64_t(1);
476 mantissa += mantissa & 1;
480 if (mantissa >= (uint64_t(1) << 24)) {
481 mantissa = (uint64_t(1) << 23);
484 mantissa &= ~(uint64_t(1) << 23);
486 if (simdjson_unlikely(real_exponent > 254)) {
490 d = to_float(uint32_t(mantissa), uint32_t(real_exponent), negative);
494#if SIMDJSON_ENABLE_NAN_INF
496simdjson_unused simdjson_inline
bool compute_nan_inf(
const uint8_t* src,
bool negative,
double& d)
noexcept {
497 if (atomparsing::is_valid_inf_atom(src)) {
498 double inf = std::numeric_limits<double>::infinity();
499 d = negative ? -inf : inf;
503 if (atomparsing::is_valid_nan_atom(src)) {
504 d = std::numeric_limits<double>::quiet_NaN();
512simdjson_unused simdjson_inline
bool compute_nan_inf(
const uint8_t* src,
bool negative,
float& d)
noexcept {
513 if (atomparsing::is_valid_inf_atom(src)) {
514 float inf = std::numeric_limits<float>::infinity();
515 d = negative ? -inf : inf;
519 if (atomparsing::is_valid_nan_atom(src)) {
520 d = std::numeric_limits<float>::quiet_NaN();
535static bool parse_float_fallback(
const uint8_t *ptr,
double *outDouble) {
536 *outDouble = simdjson::internal::from_chars(
reinterpret_cast<const char *
>(ptr));
547 return !(*outDouble > (std::numeric_limits<double>::max)() || *outDouble < std::numeric_limits<double>::lowest());
550static bool parse_float_fallback(
const uint8_t *ptr,
const uint8_t *end_ptr,
double *outDouble) {
551 *outDouble = simdjson::internal::from_chars(
reinterpret_cast<const char *
>(ptr),
reinterpret_cast<const char *
>(end_ptr));
562 return !(*outDouble > (std::numeric_limits<double>::max)() || *outDouble < std::numeric_limits<double>::lowest());
568static bool parse_float_fallback(
const uint8_t *ptr,
float *outFloat) {
569 *outFloat = simdjson::internal::from_chars_float(
reinterpret_cast<const char *
>(ptr));
572 return !(*outFloat > (std::numeric_limits<float>::max)() || *outFloat < std::numeric_limits<float>::lowest());
578simdjson_inline
bool is_made_of_eight_digits_fast(
const uint8_t *chars) {
582 static_assert(7 <=
SIMDJSON_PADDING,
"SIMDJSON_PADDING must be bigger than 7");
583 std::memcpy(&val, chars, 8);
588 return (((val & 0xF0F0F0F0F0F0F0F0) |
589 (((val + 0x0606060606060606) & 0xF0F0F0F0F0F0F0F0) >> 4)) ==
597simdjson_inline
bool is_made_of_four_digits_fast(
const uint8_t *chars) {
600 static_assert(3 <=
SIMDJSON_PADDING,
"SIMDJSON_PADDING must be bigger than 3");
601 std::memcpy(&val, chars, 4);
602 return !(((val + 0x46464646) | (val - 0x30303030)) & 0x80808080);
607simdjson_inline uint32_t parse_four_digits_unrolled(
const uint8_t *chars) {
609 std::memcpy(&val, chars, 4);
611 val = (val * 10) + (val >> 8);
612 return (((val & 0x00FF00FF) * 0x00640001) >> 16) & 0xFFFF;
616SIMDJSON_NO_SANITIZE_UNDEFINED
617simdjson_inline
bool parse_digit(
const uint8_t c, I &i) {
618 const uint8_t digit =
static_cast<uint8_t
>(c -
'0');
627simdjson_inline
bool is_digit(
const uint8_t c) {
628 return static_cast<uint8_t
>(c -
'0') <= 9;
640SIMDJSON_NO_SANITIZE_UNDEFINED
641simdjson_inline
void parse_fraction_digits(
const uint8_t *&p, uint64_t &i) {
642#ifdef SIMDJSON_SWAR_NUMBER_PARSING
643#if SIMDJSON_SWAR_NUMBER_PARSING
644 while (is_made_of_eight_digits_fast(p)) {
645 i = i * 100000000 + parse_eight_digits_unrolled(p);
650 if (is_made_of_four_digits_fast(p)) {
651 i = i * 10000 + parse_four_digits_unrolled(p);
656 while (parse_digit(*p, i)) { p++; }
659SIMDJSON_NO_SANITIZE_UNDEFINED
660simdjson_inline
void parse_float_integer_digits(
const uint8_t *&p, uint64_t &i,
661 bool &leading_zero) {
662 if (!parse_digit(*p, i)) { leading_zero =
true;
return; }
664 leading_zero = (i == 0);
665 while (parse_digit(*p, i)) { p++; }
668SIMDJSON_NO_SANITIZE_UNDEFINED
669simdjson_inline
void parse_integer_digits(
const uint8_t *&p, uint64_t &i) {
670#ifdef SIMDJSON_SWAR_NUMBER_PARSING
671#if SIMDJSON_SWAR_NUMBER_PARSING
673 if (is_made_of_eight_digits_fast(p)) {
674 i = i * 100000000 + parse_eight_digits_unrolled(p);
677 const uint8_t *
const swar_end = p + 8;
678 while (p < swar_end && is_made_of_four_digits_fast(p)) {
679 i = i * 10000 + parse_four_digits_unrolled(p);
684 while (parse_digit(*p, i)) { p++; }
687simdjson_warn_unused simdjson_inline
error_code parse_decimal_after_separator(simdjson_unused
const uint8_t *
const src,
const uint8_t *&p, uint64_t &i, int64_t &exponent) {
692 const uint8_t *
const first_after_period = p;
693 parse_fraction_digits(p, i);
694 exponent = first_after_period - p;
697 return INVALID_NUMBER(src);
702simdjson_warn_unused simdjson_inline
error_code parse_exponent(simdjson_unused
const uint8_t *
const src,
const uint8_t *&p, int64_t &exponent) {
704 bool neg_exp = (
'-' == *p);
705 if (neg_exp ||
'+' == *p) { p++; }
709 int64_t exp_number = 0;
710 while (parse_digit(*p, exp_number)) { ++p; }
722 if (simdjson_unlikely(p == start_exp)) {
723 return INVALID_NUMBER(src);
730 if (simdjson_unlikely(p > start_exp+18)) {
732 while (*start_exp ==
'0') { start_exp++; }
742 if (p > start_exp+18) { exp_number = 999999999999999999; }
749 exponent += (neg_exp ? -exp_number : exp_number);
753simdjson_inline
bool check_if_integer(
const uint8_t *
const src,
size_t max_length) {
754 const uint8_t *
const srcend = src + max_length;
755 bool negative = (*src ==
'-');
756 const uint8_t *p = src + uint8_t(negative);
757 if(p == srcend) {
return false; }
760 if(p == srcend) {
return true; }
761 if(jsoncharutils::is_not_structural_or_whitespace(*p)) {
return false; }
764 while(p != srcend && is_digit(*p)) { ++p; }
765 if(p == srcend) {
return true; }
766 if(jsoncharutils::is_not_structural_or_whitespace(*p)) {
return false; }
770simdjson_inline
size_t significant_digits(
const uint8_t * start_digits,
size_t digit_count) {
773 const uint8_t *start = start_digits;
774 while ((*start ==
'0') || (*start ==
'.')) { ++start; }
776 return digit_count - size_t(start - start_digits);
782inline error_code slow_float_parsing(simdjson_unused
const uint8_t * src,
double* answer) {
783 if (parse_float_fallback(src, answer)) {
786 return INVALID_NUMBER(src);
791simdjson_warn_unused simdjson_inline
error_code write_float(
const uint8_t *
const src,
bool negative, uint64_t i,
const uint8_t * start_digits,
size_t digit_count, int64_t exponent, W &writer) {
799 if (simdjson_unlikely(digit_count > 19 && significant_digits(start_digits, digit_count) > 19)) {
812 error_code error = slow_float_parsing(src, &d);
813 writer.append_double(d);
819 if (simdjson_unlikely(exponent < simdjson::internal::smallest_power) || (exponent > simdjson::internal::largest_power)) {
824 static_assert(simdjson::internal::smallest_power <= -342,
"smallest_power is not small enough");
826 if((exponent < simdjson::internal::smallest_power) || (i == 0)) {
828 WRITE_DOUBLE(negative ? -0.0 : 0.0, src, writer);
832 return INVALID_NUMBER(src);
836 if (!compute_float_64(exponent, i, negative, d)) {
838 if (!parse_float_fallback(src, &d)) {
return INVALID_NUMBER(src); }
840 WRITE_DOUBLE(d, src, writer);
854simdjson_warn_unused simdjson_inline
error_code parse_number(
const uint8_t *
const src, W &writer);
857#ifdef SIMDJSON_SKIPNUMBERPARSING
860simdjson_warn_unused simdjson_inline
error_code parse_number(
const uint8_t *
const, W &writer) {
861 writer.append_s64(0);
865simdjson_unused simdjson_inline simdjson_result<uint64_t> parse_unsigned(
const uint8_t *
const)
noexcept {
return 0; }
866simdjson_unused simdjson_inline simdjson_result<int64_t> parse_integer(
const uint8_t *
const)
noexcept {
return 0; }
867simdjson_unused simdjson_inline simdjson_result<double> parse_double(
const uint8_t *
const)
noexcept {
return 0; }
868simdjson_unused simdjson_inline simdjson_result<float> parse_float(
const uint8_t *
const)
noexcept {
return 0; }
869simdjson_unused simdjson_inline simdjson_result<uint64_t> parse_unsigned_in_string(
const uint8_t *
const)
noexcept {
return 0; }
870simdjson_unused simdjson_inline simdjson_result<int64_t> parse_integer_in_string(
const uint8_t *
const)
noexcept {
return 0; }
871simdjson_unused simdjson_inline simdjson_result<double> parse_double_in_string(
const uint8_t *
const)
noexcept {
return 0; }
872simdjson_unused simdjson_inline simdjson_result<float> parse_float_in_string(
const uint8_t *
const)
noexcept {
return 0; }
873simdjson_unused simdjson_inline
bool is_negative(
const uint8_t *)
noexcept {
return false; }
874simdjson_unused simdjson_inline simdjson_result<bool> is_integer(
const uint8_t *)
noexcept {
return false; }
875simdjson_unused simdjson_inline simdjson_result<number_type> get_number_type(
const uint8_t *)
noexcept {
return number_type::signed_integer; }
888simdjson_warn_unused simdjson_inline
error_code parse_number(
const uint8_t *
const src, W &writer) {
892 bool negative = (*src ==
'-');
893 const uint8_t *p = src + uint8_t(negative);
899 const uint8_t *
const start_digits = p;
901 while (parse_digit(*p, i)) { p++; }
905 size_t digit_count = size_t(p - start_digits);
906 if (digit_count == 0 || (
'0' == *start_digits && digit_count > 1)) {
908#if SIMDJSON_ENABLE_NAN_INF
913 if (compute_nan_inf(p, negative, d)) {
914 writer.append_double(d);
919 return INVALID_NUMBER(src);
925 int64_t exponent = 0;
926 bool is_float =
false;
930 SIMDJSON_TRY( parse_decimal_after_separator(src, p, i, exponent) );
931 digit_count = int(p - start_digits);
933 if ((
'e' == *p) || (
'E' == *p)) {
936 SIMDJSON_TRY( parse_exponent(src, p, exponent) );
939 const bool dirty_end = jsoncharutils::is_not_structural_or_whitespace(*p);
940 SIMDJSON_TRY( write_float(src, negative, i, start_digits, digit_count, exponent, writer) );
941 if (dirty_end) {
return INVALID_NUMBER(src); }
948 size_t longest_digit_count = negative ? 19 : 20;
949 if (digit_count > longest_digit_count) {
return BIGINT_NUMBER(src); }
950 if (digit_count == longest_digit_count) {
953 if (i > uint64_t(INT64_MAX)+1) {
return BIGINT_NUMBER(src); }
954 WRITE_INTEGER(~i+1, src, writer);
955 if (jsoncharutils::is_not_structural_or_whitespace(*p)) {
return INVALID_NUMBER(src); }
969 }
else if (src[0] != uint8_t(
'1') || i <= uint64_t(INT64_MAX)) {
return BIGINT_NUMBER(src); }
973 if (i > uint64_t(INT64_MAX)) {
974 WRITE_UNSIGNED(i, src, writer);
976#if SIMDJSON_MINUS_ZERO_AS_FLOAT
977 if(i == 0 && negative) {
979 WRITE_DOUBLE(-0.0, src, writer);
981 WRITE_INTEGER(negative ? (~i+1) : i, src, writer);
984 WRITE_INTEGER(negative ? (~i+1) : i, src, writer);
987 if (jsoncharutils::is_not_structural_or_whitespace(*p)) {
return INVALID_NUMBER(src); }
1005const uint8_t integer_string_finisher[256] = {
1060simdjson_unused simdjson_inline simdjson_result<uint64_t> parse_unsigned(
const uint8_t *
const src)
noexcept {
1061 const uint8_t *p = src;
1066 const uint8_t *
const start_digits = p;
1068 parse_integer_digits(p, i);
1072 size_t digit_count = size_t(p - start_digits);
1078 if ((digit_count == 0) || (digit_count > 20)) {
return INCORRECT_TYPE; }
1080 if ((
'0' == *start_digits) && (digit_count > 1)) {
return NUMBER_ERROR; }
1086 if (integer_string_finisher[*p] !=
SUCCESS) {
return error_code(integer_string_finisher[*p]); }
1088 if (digit_count == 20) {
1101 if (src[0] != uint8_t(
'1') || i <= uint64_t(INT64_MAX)) {
return INCORRECT_TYPE; }
1110simdjson_unused simdjson_inline simdjson_result<uint64_t> parse_unsigned(
const uint8_t *
const src,
const uint8_t *
const src_end)
noexcept {
1111 const uint8_t *p = src;
1116 const uint8_t *
const start_digits = p;
1118 while ((p != src_end) && parse_digit(*p, i)) { p++; }
1122 size_t digit_count = size_t(p - start_digits);
1128 if ((digit_count == 0) || (digit_count > 20)) {
return INCORRECT_TYPE; }
1130 if ((
'0' == *start_digits) && (digit_count > 1)) {
return NUMBER_ERROR; }
1136 if ((p != src_end) && integer_string_finisher[*p] !=
SUCCESS) {
return error_code(integer_string_finisher[*p]); }
1138 if (digit_count == 20) {
1151 if (src[0] != uint8_t(
'1') || i <= uint64_t(INT64_MAX)) {
return INCORRECT_TYPE; }
1158simdjson_unused simdjson_inline simdjson_result<uint64_t> parse_unsigned_in_string(
const uint8_t *
const src)
noexcept {
1159 const uint8_t *p = src + 1;
1164 const uint8_t *
const start_digits = p;
1166 parse_integer_digits(p, i);
1170 size_t digit_count = size_t(p - start_digits);
1176 if ((digit_count == 0) || (digit_count > 20)) {
return INCORRECT_TYPE; }
1178 if ((
'0' == *start_digits) && (digit_count > 1)) {
return NUMBER_ERROR; }
1186 if (digit_count == 20) {
1201 if (src[1] != uint8_t(
'1') || i <= uint64_t(INT64_MAX)) {
return INCORRECT_TYPE; }
1208simdjson_unused simdjson_inline simdjson_result<int64_t> parse_integer(
const uint8_t *src)
noexcept {
1212 bool negative = (*src ==
'-');
1213 const uint8_t *p = src + uint8_t(negative);
1219 const uint8_t *
const start_digits = p;
1221 parse_integer_digits(p, i);
1225 size_t digit_count = size_t(p - start_digits);
1229 size_t longest_digit_count = 19;
1233 if ((digit_count == 0) || (digit_count > longest_digit_count)) {
return INCORRECT_TYPE; }
1235 if ((
'0' == *start_digits) && (digit_count > 1)) {
return NUMBER_ERROR; }
1241 if(integer_string_finisher[*p] !=
SUCCESS) {
return error_code(integer_string_finisher[*p]); }
1245 if(i > uint64_t(INT64_MAX) + uint64_t(negative)) {
return INCORRECT_TYPE; }
1246 return negative ? (~i+1) : i;
1251simdjson_unused simdjson_inline simdjson_result<int64_t> parse_integer(
const uint8_t *
const src,
const uint8_t *
const src_end)
noexcept {
1256 bool negative = (*src ==
'-');
1257 const uint8_t *p = src + uint8_t(negative);
1263 const uint8_t *
const start_digits = p;
1265 while ((p != src_end) && parse_digit(*p, i)) { p++; }
1269 size_t digit_count = size_t(p - start_digits);
1273 size_t longest_digit_count = 19;
1277 if ((digit_count == 0) || (digit_count > longest_digit_count)) {
return INCORRECT_TYPE; }
1279 if ((
'0' == *start_digits) && (digit_count > 1)) {
return NUMBER_ERROR; }
1285 if((p != src_end) && integer_string_finisher[*p] !=
SUCCESS) {
return error_code(integer_string_finisher[*p]); }
1289 if(i > uint64_t(INT64_MAX) + uint64_t(negative)) {
return INCORRECT_TYPE; }
1290 return negative ? (~i+1) : i;
1294simdjson_unused simdjson_inline simdjson_result<int64_t> parse_integer_in_string(
const uint8_t *src)
noexcept {
1298 bool negative = (*(src + 1) ==
'-');
1299 src += uint8_t(negative) + 1;
1305 const uint8_t *
const start_digits = src;
1307 parse_integer_digits(src, i);
1311 size_t digit_count = size_t(src - start_digits);
1315 size_t longest_digit_count = 19;
1319 if ((digit_count == 0) || (digit_count > longest_digit_count)) {
return INCORRECT_TYPE; }
1321 if ((
'0' == *start_digits) && (digit_count > 1)) {
return NUMBER_ERROR; }
1331 if(i > uint64_t(INT64_MAX) + uint64_t(negative)) {
return INCORRECT_TYPE; }
1332 return negative ? (~i+1) : i;
1335simdjson_unused simdjson_inline simdjson_result<double> parse_double(
const uint8_t * src)
noexcept {
1339 bool negative = (*src ==
'-');
1340 src += uint8_t(negative);
1346 const uint8_t *p = src;
1348 parse_float_integer_digits(p, i, leading_zero);
1352#if SIMDJSON_ENABLE_NAN_INF
1356 if (compute_nan_inf(p, negative, d)) {
return d; }
1361 if ( (leading_zero && p != src+1)) {
return NUMBER_ERROR; }
1366 int64_t exponent = 0;
1368 if (simdjson_likely(*p ==
'.')) {
1370 const uint8_t *start_decimal_digits = p;
1371 parse_fraction_digits(p, i);
1372 if (p == start_decimal_digits) {
return NUMBER_ERROR; }
1373 exponent = -(p - start_decimal_digits);
1376 overflow = p-src-1 > 19;
1377 if (simdjson_unlikely(overflow && leading_zero)) {
1379 const uint8_t *start_digits = src + 2;
1380 while (*start_digits ==
'0') { start_digits++; }
1381 overflow = p-start_digits > 19;
1384 overflow = p-src > 19;
1390 if (*p ==
'e' || *p ==
'E') {
1392 bool exp_neg = *p ==
'-';
1393 p += exp_neg || *p ==
'+';
1396 const uint8_t *start_exp_digits = p;
1397 while (parse_digit(*p, exp)) { p++; }
1399 if (p-start_exp_digits == 0 || p-start_exp_digits > 19) {
return NUMBER_ERROR; }
1401 exponent += exp_neg ? 0-exp : exp;
1404 if (jsoncharutils::is_not_structural_or_whitespace(*p)) {
return NUMBER_ERROR; }
1406 overflow = overflow || exponent < simdjson::internal::smallest_power || exponent > simdjson::internal::largest_power;
1412 if (simdjson_likely(!overflow)) {
1413 if (compute_float_64(exponent, i, negative, d)) {
return d; }
1415 if (!parse_float_fallback(src - uint8_t(negative), &d)) {
1426simdjson_unused simdjson_inline simdjson_result<float> parse_float(
const uint8_t * src)
noexcept {
1430 bool negative = (*src ==
'-');
1431 src += uint8_t(negative);
1437 const uint8_t *p = src;
1439 parse_float_integer_digits(p, i, leading_zero);
1443#if SIMDJSON_ENABLE_NAN_INF
1447 if (compute_nan_inf(p, negative, f)) {
return f; }
1452 if ( (leading_zero && p != src+1)) {
return NUMBER_ERROR; }
1457 int64_t exponent = 0;
1459 if (simdjson_likely(*p ==
'.')) {
1461 const uint8_t *start_decimal_digits = p;
1462 parse_fraction_digits(p, i);
1463 if (p == start_decimal_digits) {
return NUMBER_ERROR; }
1464 exponent = -(p - start_decimal_digits);
1467 overflow = p-src-1 > 19;
1468 if (simdjson_unlikely(overflow && leading_zero)) {
1470 const uint8_t *start_digits = src + 2;
1471 while (*start_digits ==
'0') { start_digits++; }
1472 overflow = p-start_digits > 19;
1475 overflow = p-src > 19;
1481 if (*p ==
'e' || *p ==
'E') {
1483 bool exp_neg = *p ==
'-';
1484 p += exp_neg || *p ==
'+';
1487 const uint8_t *start_exp_digits = p;
1488 while (parse_digit(*p, exp)) { p++; }
1490 if (p-start_exp_digits == 0 || p-start_exp_digits > 19) {
return NUMBER_ERROR; }
1492 exponent += exp_neg ? 0-exp : exp;
1495 if (jsoncharutils::is_not_structural_or_whitespace(*p)) {
return NUMBER_ERROR; }
1497 overflow = overflow || exponent < simdjson::internal::smallest_power || exponent > simdjson::internal::largest_power;
1503 if (simdjson_likely(!overflow)) {
1504 if (compute_float_32(exponent, i, negative, d)) {
return d; }
1506 if (!parse_float_fallback(src - uint8_t(negative), &d)) {
1512simdjson_unused simdjson_inline
bool is_negative(
const uint8_t * src)
noexcept {
1513 return (*src ==
'-');
1516simdjson_unused simdjson_inline simdjson_result<bool> is_integer(
const uint8_t * src)
noexcept {
1517 bool negative = (*src ==
'-');
1518 src += uint8_t(negative);
1519 const uint8_t *p = src;
1520 while(
static_cast<uint8_t
>(*p -
'0') <= 9) { p++; }
1522 if (jsoncharutils::is_structural_or_whitespace(*p)) {
return true; }
1526simdjson_unused simdjson_inline simdjson_result<number_type> get_number_type(
const uint8_t * src)
noexcept {
1527 bool negative = (*src ==
'-');
1528 src += uint8_t(negative);
1529 const uint8_t *p = src;
1530 while(
static_cast<uint8_t
>(*p -
'0') <= 9) { p++; }
1531 size_t digit_count = size_t(p - src);
1533 if (jsoncharutils::is_structural_or_whitespace(*p)) {
1534 static const uint8_t * smaller_big_integer =
reinterpret_cast<const uint8_t *
>(
"9223372036854775808");
1536 if(simdjson_unlikely(digit_count > 20)) {
1537 return number_type::big_integer;
1541 if (simdjson_unlikely(digit_count > 19))
return number_type::big_integer;
1542 if (simdjson_unlikely(digit_count == 19 && memcmp(src, smaller_big_integer, 19) > 0)) {
1543 return number_type::big_integer;
1545#if SIMDJSON_MINUS_ZERO_AS_FLOAT
1546 if(digit_count == 1 && src[0] ==
'0') {
1548 return number_type::floating_point_number;
1551 return number_type::signed_integer;
1554 static const uint8_t * two_to_sixtyfour =
reinterpret_cast<const uint8_t *
>(
"18446744073709551616");
1555 if((digit_count > 20) || (digit_count == 20 && memcmp(src, two_to_sixtyfour, 20) >= 0)) {
1556 return number_type::big_integer;
1561 if((digit_count == 20) || (digit_count >= 19 && memcmp(src, smaller_big_integer, 19) >= 0)) {
1562 return number_type::unsigned_integer;
1564 return number_type::signed_integer;
1567 return number_type::floating_point_number;
1571simdjson_unused simdjson_inline simdjson_result<double> parse_double(
const uint8_t * src,
const uint8_t *
const src_end)
noexcept {
1576 bool negative = (*src ==
'-');
1577 src += uint8_t(negative);
1583 const uint8_t *p = src;
1585 p += parse_digit(*p, i);
1586 bool leading_zero = (i == 0);
1587 while ((p != src_end) && parse_digit(*p, i)) { p++; }
1590 if ( (leading_zero && p != src+1)) {
return NUMBER_ERROR; }
1595 int64_t exponent = 0;
1597 if (simdjson_likely((p != src_end) && (*p ==
'.'))) {
1599 const uint8_t *start_decimal_digits = p;
1600 if ((p == src_end) || !parse_digit(*p, i)) {
return NUMBER_ERROR; }
1602 while ((p != src_end) && parse_digit(*p, i)) { p++; }
1603 exponent = -(p - start_decimal_digits);
1606 overflow = p-src-1 > 19;
1607 if (simdjson_unlikely(overflow && leading_zero)) {
1609 const uint8_t *start_digits = src + 2;
1610 while (*start_digits ==
'0') { start_digits++; }
1611 overflow = start_digits-src > 19;
1614 overflow = p-src > 19;
1620 if ((p != src_end) && (*p ==
'e' || *p ==
'E')) {
1623 bool exp_neg = *p ==
'-';
1624 p += exp_neg || *p ==
'+';
1627 const uint8_t *start_exp_digits = p;
1628 while ((p != src_end) && parse_digit(*p, exp)) { p++; }
1630 if (p-start_exp_digits == 0 || p-start_exp_digits > 19) {
return NUMBER_ERROR; }
1632 exponent += exp_neg ? 0-exp : exp;
1635 if ((p != src_end) && jsoncharutils::is_not_structural_or_whitespace(*p)) {
return NUMBER_ERROR; }
1637 overflow = overflow || exponent < simdjson::internal::smallest_power || exponent > simdjson::internal::largest_power;
1643 if (simdjson_likely(!overflow)) {
1644 if (compute_float_64(exponent, i, negative, d)) {
return d; }
1646 if (!parse_float_fallback(src - uint8_t(negative), src_end, &d)) {
1652simdjson_unused simdjson_inline simdjson_result<double> parse_double_in_string(
const uint8_t * src)
noexcept {
1656 bool negative = (*(src + 1) ==
'-');
1657 src += uint8_t(negative) + 1;
1663 const uint8_t *p = src;
1665 parse_float_integer_digits(p, i, leading_zero);
1668#if SIMDJSON_ENABLE_NAN_INF
1671 if (atomparsing::is_valid_inf_in_string(src)) {
1672 double inf = std::numeric_limits<double>::infinity();
1673 return negative ? -inf : inf;
1676 if (atomparsing::is_valid_nan_in_string(src)) {
1677 return std::numeric_limits<double>::quiet_NaN();
1683 if ( (leading_zero && p != src+1)) {
return NUMBER_ERROR; }
1688 int64_t exponent = 0;
1690 if (simdjson_likely(*p ==
'.')) {
1692 const uint8_t *start_decimal_digits = p;
1693 parse_fraction_digits(p, i);
1694 if (p == start_decimal_digits) {
return NUMBER_ERROR; }
1695 exponent = -(p - start_decimal_digits);
1698 overflow = p-src-1 > 19;
1699 if (simdjson_unlikely(overflow && leading_zero)) {
1701 const uint8_t *start_digits = src + 2;
1702 while (*start_digits ==
'0') { start_digits++; }
1703 overflow = p-start_digits > 19;
1706 overflow = p-src > 19;
1712 if (*p ==
'e' || *p ==
'E') {
1714 bool exp_neg = *p ==
'-';
1715 p += exp_neg || *p ==
'+';
1718 const uint8_t *start_exp_digits = p;
1719 while (parse_digit(*p, exp)) { p++; }
1721 if (p-start_exp_digits == 0 || p-start_exp_digits > 19) {
return NUMBER_ERROR; }
1723 exponent += exp_neg ? 0-exp : exp;
1728 overflow = overflow || exponent < simdjson::internal::smallest_power || exponent > simdjson::internal::largest_power;
1734 if (simdjson_likely(!overflow)) {
1735 if (compute_float_64(exponent, i, negative, d)) {
return d; }
1737 if (!parse_float_fallback(src - uint8_t(negative), &d)) {
1745simdjson_unused simdjson_inline simdjson_result<float> parse_float_in_string(
const uint8_t * src)
noexcept {
1749 bool negative = (*(src + 1) ==
'-');
1750 src += uint8_t(negative) + 1;
1756 const uint8_t *p = src;
1758 parse_float_integer_digits(p, i, leading_zero);
1761#if SIMDJSON_ENABLE_NAN_INF
1764 if (atomparsing::is_valid_inf_in_string(src)) {
1765 float inf = std::numeric_limits<float>::infinity();
1766 return negative ? -inf : inf;
1769 if (atomparsing::is_valid_nan_in_string(src)) {
1770 return std::numeric_limits<float>::quiet_NaN();
1776 if ( (leading_zero && p != src+1)) {
return NUMBER_ERROR; }
1781 int64_t exponent = 0;
1783 if (simdjson_likely(*p ==
'.')) {
1785 const uint8_t *start_decimal_digits = p;
1786 parse_fraction_digits(p, i);
1787 if (p == start_decimal_digits) {
return NUMBER_ERROR; }
1788 exponent = -(p - start_decimal_digits);
1791 overflow = p-src-1 > 19;
1792 if (simdjson_unlikely(overflow && leading_zero)) {
1794 const uint8_t *start_digits = src + 2;
1795 while (*start_digits ==
'0') { start_digits++; }
1796 overflow = p-start_digits > 19;
1799 overflow = p-src > 19;
1805 if (*p ==
'e' || *p ==
'E') {
1807 bool exp_neg = *p ==
'-';
1808 p += exp_neg || *p ==
'+';
1811 const uint8_t *start_exp_digits = p;
1812 while (parse_digit(*p, exp)) { p++; }
1814 if (p-start_exp_digits == 0 || p-start_exp_digits > 19) {
return NUMBER_ERROR; }
1816 exponent += exp_neg ? 0-exp : exp;
1821 overflow = overflow || exponent < simdjson::internal::smallest_power || exponent > simdjson::internal::largest_power;
1827 if (simdjson_likely(!overflow)) {
1828 if (compute_float_32(exponent, i, negative, d)) {
return d; }
1830 if (!parse_float_fallback(src - uint8_t(negative), &d)) {
1841inline std::ostream& operator<<(std::ostream& out, number_type type)
noexcept {
1843 case number_type::signed_integer: out <<
"integer in [-9223372036854775808,9223372036854775808)";
break;
1844 case number_type::unsigned_integer: out <<
"unsigned integer in [9223372036854775808,18446744073709551616)";
break;
1845 case number_type::floating_point_number: out <<
"floating-point number (binary64)";
break;
1846 case number_type::big_integer: out <<
"big integer";
break;
1847 default: SIMDJSON_UNREACHABLE();
The top level simdjson namespace, containing everything the library provides.
error_code
All possible errors returned by simdjson.
@ INCORRECT_TYPE
JSON element has a different type than user expected.
@ NUMBER_ERROR
Problem while parsing a number.
constexpr size_t SIMDJSON_PADDING
The amount of padding needed in a buffer to parse JSON.