10#ifndef SIMDJSON_GENERIC_COMPILE_TIME_JSON_INL_H
12#if SIMDJSON_STATIC_REFLECTION
30#define simdjson_consteval_error(...) \
36namespace compile_time {
47namespace number_parsing {
50consteval int leading_zeroes(uint64_t input_num,
int last_bit = 0) {
51 if (input_num & uint64_t(0xffffffff00000000)) {
55 if (input_num & uint64_t(0xffff0000)) {
59 if (input_num & uint64_t(0xff00)) {
63 if (input_num & uint64_t(0xf0)) {
67 if (input_num & uint64_t(0xc)) {
71 if (input_num & uint64_t(0x2)) {
77consteval uint64_t emulu(uint32_t x, uint32_t y) {
return x * (uint64_t)y; }
78consteval uint64_t umul128_generic(uint64_t ab, uint64_t cd, uint64_t *hi) {
79 uint64_t ad = emulu((uint32_t)(ab >> 32), (uint32_t)cd);
80 uint64_t bd = emulu((uint32_t)ab, (uint32_t)cd);
81 uint64_t adbc = ad + emulu((uint32_t)ab, (uint32_t)(cd >> 32));
82 uint64_t adbc_carry = (uint64_t)(adbc < ad);
83 uint64_t lo = bd + (adbc << 32);
84 *hi = emulu((uint32_t)(ab >> 32), (uint32_t)(cd >> 32)) + (adbc >> 32) +
85 (adbc_carry << 32) + (uint64_t)(lo < bd);
96 constexpr value128(uint64_t _low, uint64_t _high) : low(_low), high(_high) {}
97 constexpr value128() : low(0), high(0) {}
101consteval value128 full_multiplication(uint64_t a, uint64_t b) {
103 answer.low = umul128_generic(a, b, &answer.high);
108consteval double to_double(uint64_t mantissa, int64_t exponent,
bool negative) {
109 uint64_t sign_bit = negative ? (1ULL << 63) : 0;
110 uint64_t exponent_bits = (uint64_t(exponent) & 0x7FF) << 52;
111 uint64_t bits = sign_bit | exponent_bits | (mantissa & ((1ULL << 52) - 1));
112 return std::bit_cast<double>(bits);
119consteval bool compute_float_64(int64_t power, uint64_t i,
bool negative,
122 d = negative ? -0.0 : 0.0;
125 int64_t exponent = (((152170 + 65536) * power) >> 16) + 1024 + 63;
126 int lz = leading_zeroes(i);
128 const uint32_t index =
129 2 * uint32_t(power - simdjson::internal::smallest_power);
130 value128 firstproduct = full_multiplication(
131 i, simdjson::internal::powers_template<>::power_of_five_128[index]);
132 if ((firstproduct.high & 0x1FF) == 0x1FF) {
133 value128 secondproduct = full_multiplication(
134 i, simdjson::internal::powers_template<>::power_of_five_128[index + 1]);
135 firstproduct.low += secondproduct.high;
136 if (secondproduct.high > firstproduct.low) {
140 uint64_t lower = firstproduct.low;
141 uint64_t upper = firstproduct.high;
142 uint64_t upperbit = upper >> 63;
143 uint64_t mantissa = upper >> (upperbit + 9);
144 lz += int(1 ^ upperbit);
145 int64_t real_exponent = exponent - lz;
146 if (real_exponent <= 0) {
147 if (-real_exponent + 1 >= 64) {
148 d = negative ? -0.0 : 0.0;
151 mantissa >>= -real_exponent + 1;
152 mantissa += (mantissa & 1);
154 real_exponent = (mantissa < (uint64_t(1) << 52)) ? 0 : 1;
155 d = to_double(mantissa, real_exponent, negative);
158 if ((lower <= 1) && (power >= -4) && (power <= 23) && ((mantissa & 3) == 1)) {
159 if ((mantissa << (upperbit + 64 - 53 - 2)) == upper) {
163 mantissa += mantissa & 1;
165 if (mantissa >= (1ULL << 53)) {
166 mantissa = (1ULL << 52);
169 mantissa &= ~(1ULL << 52);
170 if (real_exponent > 2046) {
173 d = to_double(mantissa, real_exponent, negative);
178consteval bool parse_digit(
const char c, uint64_t &i) {
179 const uint8_t digit =
static_cast<uint8_t
>(c -
'0');
189consteval std::pair<double, size_t> parse_double(
const char *src,
191 auto get_value = [&](
const char *pointer) ->
char {
192 if (pointer == end) {
197 const char *srcinit = src;
198 bool negative = (get_value(src) ==
'-');
199 src += uint8_t(negative);
202 p += parse_digit(get_value(p), i);
203 bool leading_zero = (i == 0);
204 while (parse_digit(get_value(p), i)) {
208 simdjson_consteval_error(
"Invalid float value");
210 if ((leading_zero && p != src + 1)) {
211 simdjson_consteval_error(
"Invalid float value");
213 int64_t exponent = 0;
215 if (get_value(p) ==
'.') {
217 const char *start_decimal_digits = p;
218 if (!parse_digit(get_value(p), i)) {
219 simdjson_consteval_error(
"Invalid float value");
222 while (parse_digit(get_value(p), i)) {
225 exponent = -(p - start_decimal_digits);
226 overflow = p - src - 1 > 19;
227 if (overflow && leading_zero) {
228 const char *start_digits = src + 2;
229 while (get_value(start_digits) ==
'0') {
232 overflow = p - start_digits > 19;
235 overflow = p - src > 19;
238 simdjson_consteval_error(
239 "Overflow while computing the float value: too many digits");
241 if (get_value(p) ==
'e' || get_value(p) ==
'E') {
243 bool exp_neg = get_value(p) ==
'-';
244 p += exp_neg || get_value(p) ==
'+';
246 const char *start_exp_digits = p;
247 while (parse_digit(get_value(p), exp)) {
250 if (p - start_exp_digits == 0 || p - start_exp_digits > 19) {
251 simdjson_consteval_error(
"Invalid float value");
253 exponent += exp_neg ? 0 - exp : exp;
256 overflow = overflow || exponent < simdjson::internal::smallest_power ||
257 exponent > simdjson::internal::largest_power;
259 simdjson_consteval_error(
"Overflow while computing the float value");
262 if (!compute_float_64(exponent, i, negative, d)) {
263 simdjson_consteval_error(
"Overflow while computing the float value");
265 return {d, size_t(p - srcinit)};
272template <
char... Vals>
struct fixed_json_string {
274 static constexpr char inner_data[] = {Vals...,
'\0'};
277 static constexpr std::size_t inner_size =
sizeof...(Vals);
281 static constexpr std::string_view view = {inner_data, inner_size};
283 constexpr operator std::string_view() {
return view; }
284 constexpr const char *c_str() {
return view.data(); }
285 constexpr const char *data() {
return view.data(); }
286 constexpr size_t size() {
return view.size(); }
289consteval std::meta::info to_fixed_json_string(std::string_view in) {
290 std::vector<std::meta::info> Args = {};
292 Args.push_back(std::meta::reflect_constant(c));
294 return std::meta::substitute(^^fixed_json_string, Args);
300template <std::meta::info... meta_info>
struct type_builder {
301 struct constructed_type;
303 std::meta::define_aggregate(^^constructed_type, {
314template <std::meta::info... meta_info>
315using class_type = type_builder<meta_info...>::constructed_type;
323template <
typename T,
auto... Vs>
constexpr auto construct_from = T{Vs...};
327[[nodiscard]]
constexpr bool is_whitespace(
char c) {
328 return c ==
' ' || c ==
'\n' || c ==
'\t' || c ==
'\r';
331[[nodiscard]]
constexpr std::string_view trim_whitespace(std::string_view str) {
333 size_t end = str.size();
335 while (start < end && is_whitespace(str[start])) {
338 while (end > start && is_whitespace(str[end - 1])) {
341 return str.substr(start, end - start);
345consteval std::pair<std::meta::info, size_t>
346parse_json_object_impl(std::string_view json);
355[[nodiscard]]
consteval size_t
356parse_number(std::string_view json,
357 std::variant<int64_t, uint64_t, double> &out) {
359 simdjson_consteval_error(
"Empty string is not a valid JSON number");
361 if (json[0] ==
'+') {
362 simdjson_consteval_error(
"Invalid number: leading '+' sign is not allowed");
365 auto it = json.begin();
366 if (it != json.end() && (*it ==
'-')) {
369 while (it != json.end() && (*it >=
'0' && *it <=
'9')) {
372 bool is_float =
false;
373 if (it != json.end() && (*it ==
'.' || *it ==
'e' || *it ==
'E')) {
377 while (it != json.end() && (*it >=
'0' && *it <=
'9')) {
381 if (it != json.end() && (*it ==
'e' || *it ==
'E')) {
383 if (it != json.end() && (*it ==
'+' || *it ==
'-')) {
386 while (it != json.end() && (*it >=
'0' && *it <=
'9')) {
391 size_t scope = it - json.begin();
393 bool is_negative = json[0] ==
'-';
399 auto [value, offset] =
400 number_parsing::parse_double(json.data(), json.data() + json.size());
401 if (offset != scope) {
402 simdjson_consteval_error(
403 "Internal error: cannot agree on the character range of the float");
407 }
else if (is_negative) {
408 int64_t int_value = 0;
409 std::from_chars_result res =
410 std::from_chars(json.data(), json.data() + json.size(), int_value);
411 if (res.ec == std::errc()) {
413 if ((res.ptr - json.data()) != scope) {
414 simdjson_consteval_error(
415 "Internal error: cannot agree on the character range of the float");
417 return (res.ptr - json.data());
419 simdjson_consteval_error(
"Invalid integer value");
422 uint64_t uint_value = 0;
423 std::from_chars_result res =
424 std::from_chars(json.data(), json.data() + json.size(), uint_value);
425 if (res.ec == std::errc()) {
427 if ((res.ptr - json.data()) != scope) {
428 simdjson_consteval_error(
429 "Internal error: cannot agree on the character range of the float");
431 return (res.ptr - json.data());
433 simdjson_consteval_error(
"Invalid unsigned integer value");
447[[nodiscard]]
consteval std::pair<std::string, size_t>
448parse_string(std::string_view json) {
449 auto cursor = json.begin();
450 auto end = json.end();
454 if (cursor == end || *(cursor++) !=
'"') {
455 simdjson_consteval_error(
"Expected opening quote for string");
461 auto process_escaped_unicode = [&] [[nodiscard]] () ->
bool {
468 auto hex_to_u32 = [&] [[nodiscard]] () -> uint32_t {
469 auto digit = [](uint8_t c) -> uint32_t {
470 if (c >=
'0' && c <=
'9')
472 if (c >=
'A' && c <=
'F')
474 if (c >=
'a' && c <=
'f')
478 if (end - cursor < 4) {
481 uint32_t d0 = digit(*cursor++);
482 uint32_t d1 = digit(*cursor++);
483 uint32_t d2 = digit(*cursor++);
484 uint32_t d3 = digit(*cursor++);
486 return (d0 << 12) | (d1 << 8) | (d2 << 4) | d3;
491 auto codepoint_to_utf8 = [&out] [[nodiscard]] (uint32_t cp) ->
bool {
494 if (cp > 0x10FFFF || (cp >= 0xD800 && cp <= 0xDFFF)) {
498 out.push_back(uint8_t(cp));
499 }
else if (cp <= 0x7FF) {
500 out.push_back(uint8_t((cp >> 6) + 192));
501 out.push_back(uint8_t((cp & 63) + 128));
502 }
else if (cp <= 0xFFFF) {
503 out.push_back(uint8_t((cp >> 12) + 224));
504 out.push_back(uint8_t(((cp >> 6) & 63) + 128));
505 out.push_back(uint8_t((cp & 63) + 128));
506 }
else if (cp <= 0x10FFFF) {
507 out.push_back(uint8_t((cp >> 18) + 240));
508 out.push_back(uint8_t(((cp >> 12) & 63) + 128));
509 out.push_back(uint8_t(((cp >> 6) & 63) + 128));
510 out.push_back(uint8_t((cp & 63) + 128));
519 constexpr uint32_t substitution_code_point = 0xfffd;
521 if (end - cursor < 4) {
525 uint32_t code_point = hex_to_u32();
527 if (code_point > 0xFFFF) {
531 if (code_point >= 0xd800 && code_point < 0xdc00) {
535 if (end - cursor < 6 || *cursor !=
'\\' ||
536 *(cursor + 1) !=
'u' > 0xFFFF) {
537 code_point = substitution_code_point;
540 uint32_t code_point_2 = hex_to_u32();
541 if (code_point_2 > 0xFFFF) {
544 uint32_t low_bit = code_point_2 - 0xdc00;
547 code_point = substitution_code_point;
549 code_point = ((code_point - 0xd800) << 10 | low_bit) + 0x10000;
552 }
else if (code_point >= 0xdc00 && code_point < 0xe000) {
554 code_point = substitution_code_point;
557 return codepoint_to_utf8(code_point);
560 while (cursor != end && *cursor !=
'"') {
563 simdjson_consteval_error(
"Unterminated string");
566 char c = *(cursor++);
572 size_t how_many_backslashes = 1;
573 while (cursor != end && *(cursor) ==
'\\') {
575 how_many_backslashes++;
577 size_t backslashes_to_add = how_many_backslashes / 2;
579 for (
size_t i = 0; i < backslashes_to_add; i++) {
584 if (how_many_backslashes % 2 == 1) {
588 simdjson_consteval_error(
"Truncated escape sequence in string");
590 char next_char = *cursor;
615 if (!process_escaped_unicode()) {
616 simdjson_consteval_error(
617 "Invalid unicode escape sequence in string");
621 simdjson_consteval_error(
"Invalid escape character in string");
629 if (
static_cast<unsigned char>(c) < 0x20) {
630 simdjson_consteval_error(
"Invalid control character in string");
632 if (
static_cast<unsigned char>(c) >= 0x80) {
635 uint8_t first_byte =
static_cast<uint8_t
>(c);
637 if ((first_byte & 0b11100000) == 0b11000000) {
639 simdjson_consteval_error(
"Truncated UTF-8 sequence in string");
642 char second_byte = *cursor;
645 if ((
static_cast<uint8_t
>(second_byte) & 0b11000000) != 0b10000000) {
646 simdjson_consteval_error(
"Invalid UTF-8 continuation byte in string");
649 uint32_t code_point = (first_byte & 0b00011111) << 6 |
650 (
static_cast<uint8_t
>(second_byte) & 0b00111111);
651 if ((code_point < 0x80) || (0x7ff < code_point)) {
652 simdjson_consteval_error(
"Invalid UTF-8 code point in string");
654 }
else if ((first_byte & 0b11110000) == 0b11100000) {
656 simdjson_consteval_error(
"Truncated UTF-8 sequence in string");
658 char second_byte = *cursor;
661 if ((
static_cast<uint8_t
>(second_byte) & 0b11000000) != 0b10000000) {
662 simdjson_consteval_error(
"Invalid UTF-8 continuation byte in string");
665 simdjson_consteval_error(
"Truncated UTF-8 sequence in string");
667 char third_byte = *cursor;
670 if ((
static_cast<uint8_t
>(third_byte) & 0b11000000) != 0b10000000) {
671 simdjson_consteval_error(
"Invalid UTF-8 continuation byte in string");
674 uint32_t code_point = (first_byte & 0b00001111) << 12 |
675 (
static_cast<uint8_t
>(second_byte) & 0b00111111)
677 (
static_cast<uint8_t
>(third_byte) & 0b00111111);
678 if ((code_point < 0x800) || (0xffff < code_point) ||
679 (0xd7ff < code_point && code_point < 0xe000)) {
680 simdjson_consteval_error(
"Invalid UTF-8 code point in string");
682 }
else if ((first_byte & 0b11111000) == 0b11110000) {
684 simdjson_consteval_error(
"Truncated UTF-8 sequence in string");
686 char second_byte = *cursor;
690 simdjson_consteval_error(
"Truncated UTF-8 sequence in string");
692 char third_byte = *cursor;
696 simdjson_consteval_error(
"Truncated UTF-8 sequence in string");
698 char fourth_byte = *cursor;
701 if ((
static_cast<uint8_t
>(second_byte) & 0b11000000) != 0b10000000) {
702 simdjson_consteval_error(
"Invalid UTF-8 continuation byte in string");
704 if ((
static_cast<uint8_t
>(third_byte) & 0b11000000) != 0b10000000) {
705 simdjson_consteval_error(
"Invalid UTF-8 continuation byte in string");
707 if ((
static_cast<uint8_t
>(fourth_byte) & 0b11000000) != 0b10000000) {
708 simdjson_consteval_error(
"Invalid UTF-8 continuation byte in string");
711 uint32_t code_point =
712 (first_byte & 0b00000111) << 18 |
713 (
static_cast<uint8_t
>(second_byte) & 0b00111111) << 12 |
714 (
static_cast<uint8_t
>(third_byte) & 0b00111111) << 6 |
715 (
static_cast<uint8_t
>(fourth_byte) & 0b00111111);
716 if (code_point <= 0xffff || 0x10ffff < code_point) {
717 simdjson_consteval_error(
"Invalid UTF-8 code point in string");
721 simdjson_consteval_error(
"Invalid UTF-8 continuation byte in string");
727 simdjson_consteval_error(
"Unterminated string");
729 if (*cursor !=
'"') {
730 simdjson_consteval_error(
"Internal error: expected closing quote");
735 return {out, size_t(cursor - json.begin())};
744consteval std::pair<std::meta::info, size_t>
745parse_json_array_impl(
const std::string_view json) {
747 auto cursor = json.begin();
748 auto end = json.end();
749 auto is_whitespace = [](
char c) {
750 return c ==
' ' || c ==
'\n' || c ==
'\t' || c ==
'\r';
753 auto skip_whitespace = [&]() ->
void {
754 while (cursor != end && is_whitespace(*cursor))
758 auto expect_consume = [&] [[nodiscard]] (
char c) ->
bool {
760 if (cursor == end || *(cursor++) != c) {
766 if (!expect_consume(
'[')) {
767 simdjson_consteval_error(
"Expected '['");
770 std::vector<std::meta::info> values = {^^
void};
772 if (cursor != end && *cursor ==
']') {
773 if (!expect_consume(
']')) {
774 simdjson_consteval_error(
"Expected ']'");
777 auto array_type = std::meta::substitute(
779 ^^int, std::meta::reflect_constant(0uz)});
780 values[0] = array_type;
781 consumed = size_t(cursor - json.begin());
782 if (json[consumed - 1] !=
']') {
783 simdjson_consteval_error(
"Expected ']'");
785 return {std::meta::substitute(^^construct_from, values), consumed};
787 while (cursor != end && *cursor !=
']') {
791 std::string_view value(cursor, end);
792 auto [parsed, object_size] = parse_json_object_impl(value);
793 if (*(cursor + object_size - 1) !=
'}') {
794 simdjson_consteval_error(
"Expected '}'");
796 values.push_back(parsed);
797 cursor += object_size;
801 std::string_view value(cursor, end);
802 auto [parsed, array_size] = parse_json_array_impl(value);
803 if (*(cursor + array_size - 1) !=
']') {
804 simdjson_consteval_error(
"Expected ']'");
806 values.push_back(parsed);
807 cursor += array_size;
811 auto res = parse_string(std::string_view(cursor, end));
812 cursor += res.second;
813 for (
char ch : res.first) {
815 simdjson_consteval_error(
816 "Field string values cannot contain embedded nulls");
819 values.push_back(std::meta::reflect_constant_string(res.first));
823 if (end - cursor < 4 || std::string_view(cursor, 4) !=
"true") {
824 simdjson_consteval_error(
"Invalid value");
827 values.push_back(std::meta::reflect_constant(
true));
831 if (end - cursor < 5 || std::string_view(cursor, 5) !=
"false") {
832 simdjson_consteval_error(
"Invalid value");
835 values.push_back(std::meta::reflect_constant(
false));
839 if (end - cursor < 4 || std::string_view(cursor, 4) !=
"null") {
840 simdjson_consteval_error(
"Invalid value");
843 values.push_back(std::meta::reflect_constant(
nullptr));
858 std::string_view suffix = std::string_view(cursor, end);
859 std::variant<int64_t, uint64_t, double> out;
860 size_t r = parse_number(suffix, out);
862 if (std::holds_alternative<int64_t>(out)) {
863 int64_t int_value = std::get<int64_t>(out);
864 values.push_back(std::meta::reflect_constant(int_value));
865 }
else if (std::holds_alternative<uint64_t>(out)) {
866 uint64_t uint_value = std::get<uint64_t>(out);
867 values.push_back(std::meta::reflect_constant(uint_value));
869 double float_value = std::get<double>(out);
870 values.push_back(std::meta::reflect_constant(float_value));
875 simdjson_consteval_error(
"Invalid character starting value");
878 if (cursor != end && *cursor ==
',') {
884 if (!expect_consume(
']')) {
885 simdjson_consteval_error(
"Expected ']'");
887 std::size_t count = values.size() - 1;
890 auto array_type = std::meta::substitute(
893 std::meta::type_of(values[1]), std::meta::reflect_constant(count)});
896 values[0] = array_type;
897 consumed = size_t(cursor - json.begin());
898 if (json[consumed - 1] !=
']') {
899 simdjson_consteval_error(
"Expected ']'");
901 return {std::meta::substitute(^^construct_from, values), consumed};
910consteval std::pair<std::meta::info, size_t>
911parse_json_object_impl(std::string_view json) {
913 auto cursor = json.begin();
914 auto end = json.end();
916 auto skip_whitespace = [&]() ->
void {
917 while (cursor != end && is_whitespace(*cursor))
921 auto expect_consume = [&] [[nodiscard]] (
char c) ->
bool {
923 if (cursor == end || *(cursor++) != c) {
929 if (!expect_consume(
'{')) {
930 simdjson_consteval_error(
"Expected '{'");
933 std::vector<std::meta::info> members;
934 std::vector<std::meta::info> values = {^^
void};
936 while (cursor != end && *cursor !=
'}') {
941 auto field = parse_string(std::string_view(cursor, end));
942 std::string field_name = field.first;
943 cursor += field.second;
944 if (!expect_consume(
':')) {
945 simdjson_consteval_error(
"Expected ':'");
949 simdjson_consteval_error(
"Expected value after colon");
954 std::string_view value(cursor, end);
955 auto [parsed, object_size] = parse_json_object_impl(value);
956 if (*(cursor + object_size - 1) !=
'}') {
957 simdjson_consteval_error(
"Expected '}'");
959 cursor += object_size;
960 auto dms = std::meta::data_member_spec(std::meta::type_of(parsed),
961 {.name = field_name});
962 members.push_back(std::meta::reflect_constant(dms));
963 values.push_back(parsed);
968 std::string_view value(cursor, end);
969 auto [parsed, array_size] = parse_json_array_impl(value);
970 auto dms = std::meta::data_member_spec(std::meta::type_of(parsed),
971 {.name = field_name});
972 members.push_back(std::meta::reflect_constant(dms));
973 values.push_back(parsed);
974 if (*(cursor + array_size - 1) !=
']') {
975 simdjson_consteval_error(
"Expected ']'");
977 cursor += array_size;
982 auto res = parse_string(std::string_view(cursor, end));
983 std::string_view value = res.first;
984 cursor += res.second;
985 for (
char ch : value) {
987 simdjson_consteval_error(
988 "Field string values cannot contain embedded nulls");
992 std::meta::data_member_spec(^^
const char *, {
993 .name = field_name});
994 members.push_back(std::meta::reflect_constant(dms));
995 values.push_back(std::meta::reflect_constant_string(value));
999 if (end - cursor < 4 || std::string_view(cursor, 4) !=
"true") {
1000 simdjson_consteval_error(
"Invalid value");
1004 auto dms = std::meta::data_member_spec(^^
bool, {
1005 .name = field_name});
1006 members.push_back(std::meta::reflect_constant(dms));
1007 values.push_back(std::meta::reflect_constant(
true));
1011 if (end - cursor < 5 || std::string_view(cursor, 5) !=
"false") {
1012 simdjson_consteval_error(
"Invalid value");
1016 auto dms = std::meta::data_member_spec(^^
bool, {
1017 .name = field_name});
1018 members.push_back(std::meta::reflect_constant(dms));
1019 values.push_back(std::meta::reflect_constant(
false));
1023 if (end - cursor < 4 || std::string_view(cursor, 4) !=
"null") {
1024 simdjson_consteval_error(
"Invalid value");
1028 auto dms = std::meta::data_member_spec(^^std::nullptr_t,
1030 .name = field_name});
1031 members.push_back(std::meta::reflect_constant(dms));
1032 values.push_back(std::meta::reflect_constant(
nullptr));
1047 std::string_view suffix = std::string_view(cursor, end);
1048 std::variant<int64_t, uint64_t, double> out;
1049 size_t r = parse_number(suffix, out);
1051 if (std::holds_alternative<int64_t>(out)) {
1052 int64_t int_value = std::get<int64_t>(out);
1054 std::meta::data_member_spec(^^int64_t, {
1055 .name = field_name});
1056 members.push_back(std::meta::reflect_constant(dms));
1057 values.push_back(std::meta::reflect_constant(int_value));
1058 }
else if (std::holds_alternative<uint64_t>(out)) {
1059 uint64_t uint_value = std::get<uint64_t>(out);
1061 std::meta::data_member_spec(^^uint64_t, {
1062 .name = field_name});
1063 members.push_back(std::meta::reflect_constant(dms));
1064 values.push_back(std::meta::reflect_constant(uint_value));
1066 double float_value = std::get<double>(out);
1068 std::meta::data_member_spec(^^
double, {
1069 .name = field_name});
1070 members.push_back(std::meta::reflect_constant(dms));
1071 values.push_back(std::meta::reflect_constant(float_value));
1076 simdjson_consteval_error(
"Invalid character starting value");
1079 if (cursor == end) {
1080 simdjson_consteval_error(
"Expected '}' or ','");
1082 if (*cursor ==
',') {
1085 }
else if (*cursor !=
'}') {
1086 simdjson_consteval_error(
"Expected '}'");
1090 if (!expect_consume(
'}')) {
1091 simdjson_consteval_error(
"Expected '}'");
1093 values[0] = std::meta::substitute(^^class_type, members);
1094 consumed = size_t(cursor - json.begin());
1095 if (json[consumed - 1] !=
'}') {
1096 simdjson_consteval_error(
"Expected '}'");
1098 return {std::meta::substitute(^^construct_from, values), consumed};
1107template <constevalutil::fixed_
string json_str>
consteval auto parse_json() {
1108 constexpr std::string_view json = trim_whitespace(json_str.view());
1109 static_assert(!json.empty(),
"JSON string cannot be empty");
1114 constexpr auto result = json.front() ==
'['
1115 ? parse_json_array_impl(json)
1116 : parse_json_object_impl(json);
1117 return [: result.first :];
Compile-time JSON parsing using C++26 reflection with std::meta::substitute()
The top level simdjson namespace, containing everything the library provides.