9455 using number_integer_t =
typename BasicJsonType::number_integer_t;
9456 using number_unsigned_t =
typename BasicJsonType::number_unsigned_t;
9457 using number_float_t =
typename BasicJsonType::number_float_t;
9458 using string_t =
typename BasicJsonType::string_t;
9459 using binary_t =
typename BasicJsonType::binary_t;
9460 using json_sax_t = SAX;
9461 using char_type =
typename InputAdapterType::char_type;
9470 explicit binary_reader(InputAdapterType&& adapter,
const input_format_t format = input_format_t::json) noexcept : ia(std::move(adapter)), input_format(format) {
9489 JSON_HEDLEY_NON_NULL(3)
9492 const
bool strict = true,
9495 bool result =
false;
9498 case input_format_t::bson:
9499 result = parse_bson_internal();
9502 case input_format_t::cbor:
9503 result = parse_cbor_internal(
true, tag_handler);
9506 case input_format_t::msgpack:
9507 result = parse_msgpack_internal();
9510 case input_format_t::ubjson:
9511 case input_format_t::bjdata:
9512 result = parse_ubjson_internal();
9515 case input_format_t::json:
9522 if (input_format == input_format_t::ubjson || input_format == input_format_t::bjdata) {
9530 return sax->parse_error(chars_read, get_token_string(),
parse_error::create(110, chars_read,
9531 exception_message(input_format, concat(
"expected end of input; last byte: 0x", get_token_string()),
"value"),
nullptr));
9547 bool parse_bson_internal() {
9548 std::int32_t document_size{};
9549 get_number<std::int32_t, true>(input_format_t::bson, document_size);
9551 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(detail::unknown_size()))) {
9555 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(
false))) {
9559 return sax->end_object();
9569 bool get_bson_cstr(string_t& result) {
9570 auto out = std::back_inserter(result);
9573 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson,
"cstring"))) {
9576 if (current == 0x00) {
9579 *out++ =
static_cast<typename string_t::value_type
>(current);
9594 template<
typename NumberType>
9595 bool get_bson_string(
const NumberType len, string_t& result) {
9596 if (JSON_HEDLEY_UNLIKELY(len < 1)) {
9597 auto last_token = get_token_string();
9598 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
9599 exception_message(input_format_t::bson, concat(
"string length must be at least 1, is ", std::to_string(len)),
"string"),
nullptr));
9602 return get_string(input_format_t::bson, len -
static_cast<NumberType
>(1), result) && get() != char_traits<char_type>::eof();
9614 template<
typename NumberType>
9615 bool get_bson_binary(
const NumberType len, binary_t& result) {
9616 if (JSON_HEDLEY_UNLIKELY(len < 0)) {
9617 auto last_token = get_token_string();
9618 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
9619 exception_message(input_format_t::bson, concat(
"byte array length cannot be negative, is ", std::to_string(len)),
"binary"),
nullptr));
9623 std::uint8_t subtype{};
9624 get_number<std::uint8_t>(input_format_t::bson, subtype);
9625 result.set_subtype(subtype);
9627 return get_binary(input_format_t::bson, len, result);
9640 bool parse_bson_element_internal(
const char_int_type element_type,
9641 const std::size_t element_type_parse_position) {
9642 switch (element_type) {
9646 return get_number<double, true>(input_format_t::bson, number) && sax->number_float(
static_cast<number_float_t
>(number),
"");
9653 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_string(len, value) && sax->string(value);
9658 return parse_bson_internal();
9663 return parse_bson_array();
9670 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_binary(len, value) && sax->binary(value);
9675 return sax->boolean(get() != 0);
9685 std::int32_t value{};
9686 return get_number<std::int32_t, true>(input_format_t::bson, value) && sax->number_integer(value);
9691 std::int64_t value{};
9692 return get_number<std::int64_t, true>(input_format_t::bson, value) && sax->number_integer(value);
9697 std::uint64_t value{};
9698 return get_number<std::uint64_t, true>(input_format_t::bson, value) && sax->number_unsigned(value);
9703 std::array<char, 3> cr{ {} };
9704 static_cast<void>((std::snprintf)(cr.data(), cr.size(),
"%.2hhX",
static_cast<unsigned char>(element_type)));
9705 const std::string cr_str{ cr.data() };
9706 return sax->parse_error(element_type_parse_position, cr_str,
9707 parse_error::create(114, element_type_parse_position, concat(
"Unsupported BSON record type 0x", cr_str),
nullptr));
9724 bool parse_bson_element_list(
const bool is_array) {
9727 while (
auto element_type = get()) {
9728 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson,
"element list"))) {
9732 const std::size_t element_type_parse_position = chars_read;
9733 if (JSON_HEDLEY_UNLIKELY(!get_bson_cstr(key))) {
9737 if (!is_array && !sax->key(key)) {
9741 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_internal(element_type, element_type_parse_position))) {
9756 bool parse_bson_array() {
9757 std::int32_t document_size{};
9758 get_number<std::int32_t, true>(input_format_t::bson, document_size);
9760 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(detail::unknown_size()))) {
9764 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(
true))) {
9768 return sax->end_array();
9784 template<
typename NumberType>
9785 bool get_cbor_negative_integer() {
9786 NumberType number{};
9787 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::cbor, number))) {
9790 const auto max_val =
static_cast<NumberType
>((std::numeric_limits<number_integer_t>::max)());
9791 if (number > max_val) {
9792 return sax->parse_error(chars_read, get_token_string(),
9793 parse_error::create(112, chars_read,
9794 exception_message(input_format_t::cbor,
"negative integer overflow",
"value"),
nullptr));
9796 return sax->number_integer(
static_cast<number_integer_t
>(-1) -
static_cast<number_integer_t
>(number));
9799 bool parse_cbor_internal(
const bool get_char,
9800 const cbor_tag_handler_t tag_handler) {
9801 switch (get_char ? get() : current) {
9803 case char_traits<char_type>::eof():
9831 return sax->number_unsigned(
static_cast<number_unsigned_t
>(current));
9835 std::uint8_t number{};
9836 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9841 std::uint16_t number{};
9842 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9847 std::uint32_t number{};
9848 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9853 std::uint64_t number{};
9854 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9882 return sax->number_integer(
static_cast<std::int8_t
>(0x20 - 1 - current));
9885 return get_cbor_negative_integer<std::uint8_t>();
9888 return get_cbor_negative_integer<std::uint16_t>();
9891 return get_cbor_negative_integer<std::uint32_t>();
9894 return get_cbor_negative_integer<std::uint64_t>();
9928 return get_cbor_binary(b) && sax->binary(b);
9963 return get_cbor_string(s) && sax->string(s);
9991 return get_cbor_array(
9992 conditional_static_cast<std::size_t>(
static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
9997 return get_number(input_format_t::cbor, len) && get_cbor_array(
static_cast<std::size_t
>(len), tag_handler);
10002 std::uint16_t len{};
10003 return get_number(input_format_t::cbor, len) && get_cbor_array(
static_cast<std::size_t
>(len), tag_handler);
10008 std::uint32_t len{};
10009 return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
10014 std::uint64_t len{};
10015 return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
10019 return get_cbor_array(detail::unknown_size(), tag_handler);
10046 return get_cbor_object(conditional_static_cast<std::size_t>(
static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
10050 std::uint8_t len{};
10051 return get_number(input_format_t::cbor, len) && get_cbor_object(
static_cast<std::size_t
>(len), tag_handler);
10056 std::uint16_t len{};
10057 return get_number(input_format_t::cbor, len) && get_cbor_object(
static_cast<std::size_t
>(len), tag_handler);
10062 std::uint32_t len{};
10063 return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
10068 std::uint64_t len{};
10069 return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
10073 return get_cbor_object(detail::unknown_size(), tag_handler);
10095 switch (tag_handler) {
10096 case cbor_tag_handler_t::error:
10098 auto last_token = get_token_string();
10099 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10100 exception_message(input_format_t::cbor, concat(
"invalid byte: 0x", last_token),
"value"),
nullptr));
10103 case cbor_tag_handler_t::ignore:
10109 std::uint8_t subtype_to_ignore{};
10110 get_number(input_format_t::cbor, subtype_to_ignore);
10115 std::uint16_t subtype_to_ignore{};
10116 get_number(input_format_t::cbor, subtype_to_ignore);
10121 std::uint32_t subtype_to_ignore{};
10122 get_number(input_format_t::cbor, subtype_to_ignore);
10127 std::uint64_t subtype_to_ignore{};
10128 get_number(input_format_t::cbor, subtype_to_ignore);
10134 return parse_cbor_internal(
true, tag_handler);
10137 case cbor_tag_handler_t::store:
10144 std::uint8_t subtype{};
10145 get_number(input_format_t::cbor, subtype);
10146 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
10151 std::uint16_t subtype{};
10152 get_number(input_format_t::cbor, subtype);
10153 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
10158 std::uint32_t subtype{};
10159 get_number(input_format_t::cbor, subtype);
10160 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
10165 std::uint64_t subtype{};
10166 get_number(input_format_t::cbor, subtype);
10167 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
10171 return parse_cbor_internal(
true, tag_handler);
10174 return get_cbor_binary(b) && sax->binary(b);
10178 JSON_ASSERT(
false);
10184 return sax->boolean(
false);
10187 return sax->boolean(
true);
10190 return sax->null();
10194 const auto byte1_raw = get();
10195 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor,
"number"))) {
10198 const auto byte2_raw = get();
10199 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor,
"number"))) {
10203 const auto byte1 =
static_cast<unsigned char>(byte1_raw);
10204 const auto byte2 =
static_cast<unsigned char>(byte2_raw);
10214 const auto half =
static_cast<unsigned int>((byte1 << 8u) + byte2);
10215 const double val = [&half] {
10216 const int exp = (half >> 10u) & 0x1Fu;
10217 const unsigned int mant = half & 0x3FFu;
10218 JSON_ASSERT(0 <= exp && exp <= 32);
10219 JSON_ASSERT(mant <= 1024);
10222 return std::ldexp(mant, -24);
10225 ? std::numeric_limits<double>::infinity()
10226 : std::numeric_limits<double>::quiet_NaN();
10228 return std::ldexp(mant + 1024, exp - 25);
10231 return sax->number_float((half & 0x8000u) != 0
10232 ?
static_cast<number_float_t
>(-val)
10233 :
static_cast<number_float_t
>(val),
"");
10239 return get_number(input_format_t::cbor, number) && sax->number_float(
static_cast<number_float_t
>(number),
"");
10245 return get_number(input_format_t::cbor, number) && sax->number_float(
static_cast<number_float_t
>(number),
"");
10250 auto last_token = get_token_string();
10251 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10252 exception_message(input_format_t::cbor, concat(
"invalid byte: 0x", last_token),
"value"),
nullptr));
10268 bool get_cbor_string(string_t& result) {
10269 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor,
"string"))) {
10300 return get_string(input_format_t::cbor,
static_cast<unsigned int>(current) & 0x1Fu, result);
10305 std::uint8_t len{};
10306 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10311 std::uint16_t len{};
10312 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10317 std::uint32_t len{};
10318 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10323 std::uint64_t len{};
10324 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10329 while (get() != 0xFF) {
10331 if (!get_cbor_string(chunk)) {
10334 result.append(chunk);
10341 auto last_token = get_token_string();
10342 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10343 exception_message(input_format_t::cbor, concat(
"expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x", last_token),
"string"),
nullptr));
10359 bool get_cbor_binary(binary_t& result) {
10360 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor,
"binary"))) {
10391 return get_binary(input_format_t::cbor,
static_cast<unsigned int>(current) & 0x1Fu, result);
10396 std::uint8_t len{};
10397 return get_number(input_format_t::cbor, len) &&
10398 get_binary(input_format_t::cbor, len, result);
10403 std::uint16_t len{};
10404 return get_number(input_format_t::cbor, len) &&
10405 get_binary(input_format_t::cbor, len, result);
10410 std::uint32_t len{};
10411 return get_number(input_format_t::cbor, len) &&
10412 get_binary(input_format_t::cbor, len, result);
10417 std::uint64_t len{};
10418 return get_number(input_format_t::cbor, len) &&
10419 get_binary(input_format_t::cbor, len, result);
10424 while (get() != 0xFF) {
10426 if (!get_cbor_binary(chunk)) {
10429 result.insert(result.end(), chunk.begin(), chunk.end());
10436 auto last_token = get_token_string();
10437 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10438 exception_message(input_format_t::cbor, concat(
"expected length specification (0x40-0x5B) or indefinite binary array type (0x5F); last byte: 0x", last_token),
"binary"),
nullptr));
10449 bool get_cbor_array(
const std::size_t len,
10450 const cbor_tag_handler_t tag_handler) {
10451 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len))) {
10455 if (len != detail::unknown_size()) {
10456 for (std::size_t i = 0; i < len; ++i) {
10457 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(
true, tag_handler))) {
10463 while (get() != 0xFF) {
10464 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(
false, tag_handler))) {
10470 return sax->end_array();
10479 bool get_cbor_object(
const std::size_t len,
10480 const cbor_tag_handler_t tag_handler) {
10481 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len))) {
10487 if (len != detail::unknown_size()) {
10488 for (std::size_t i = 0; i < len; ++i) {
10490 if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key))) {
10494 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(
true, tag_handler))) {
10501 while (get() != 0xFF) {
10502 if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key))) {
10506 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(
true, tag_handler))) {
10514 return sax->end_object();
10524 bool parse_msgpack_internal() {
10527 case char_traits<char_type>::eof():
10659 return sax->number_unsigned(
static_cast<number_unsigned_t
>(current));
10678 return get_msgpack_object(conditional_static_cast<std::size_t>(
static_cast<unsigned int>(current) & 0x0Fu));
10697 return get_msgpack_array(conditional_static_cast<std::size_t>(
static_cast<unsigned int>(current) & 0x0Fu));
10737 return get_msgpack_string(s) && sax->string(s);
10741 return sax->null();
10744 return sax->boolean(
false);
10747 return sax->boolean(
true);
10762 return get_msgpack_binary(b) && sax->binary(b);
10768 return get_number(input_format_t::msgpack, number) && sax->number_float(
static_cast<number_float_t
>(number),
"");
10774 return get_number(input_format_t::msgpack, number) && sax->number_float(
static_cast<number_float_t
>(number),
"");
10779 std::uint8_t number{};
10780 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10785 std::uint16_t number{};
10786 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10791 std::uint32_t number{};
10792 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10797 std::uint64_t number{};
10798 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10803 std::int8_t number{};
10804 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10809 std::int16_t number{};
10810 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10815 std::int32_t number{};
10816 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10821 std::int64_t number{};
10822 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10827 std::uint16_t len{};
10828 return get_number(input_format_t::msgpack, len) && get_msgpack_array(
static_cast<std::size_t
>(len));
10833 std::uint32_t len{};
10834 return get_number(input_format_t::msgpack, len) && get_msgpack_array(conditional_static_cast<std::size_t>(len));
10839 std::uint16_t len{};
10840 return get_number(input_format_t::msgpack, len) && get_msgpack_object(
static_cast<std::size_t
>(len));
10845 std::uint32_t len{};
10846 return get_number(input_format_t::msgpack, len) && get_msgpack_object(conditional_static_cast<std::size_t>(len));
10882 return sax->number_integer(
static_cast<std::int8_t
>(current));
10886 auto last_token = get_token_string();
10887 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10888 exception_message(input_format_t::msgpack, concat(
"invalid byte: 0x", last_token),
"value"),
nullptr));
10903 bool get_msgpack_string(string_t& result) {
10904 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::msgpack,
"string"))) {
10943 return get_string(input_format_t::msgpack,
static_cast<unsigned int>(current) & 0x1Fu, result);
10948 std::uint8_t len{};
10949 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
10954 std::uint16_t len{};
10955 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
10960 std::uint32_t len{};
10961 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
10966 auto last_token = get_token_string();
10967 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10968 exception_message(input_format_t::msgpack, concat(
"expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x", last_token),
"string"),
nullptr));
10983 bool get_msgpack_binary(binary_t& result) {
10985 auto assign_and_return_true = [&result](std::int8_t subtype) {
10986 result.set_subtype(
static_cast<std::uint8_t
>(subtype));
10993 std::uint8_t len{};
10994 return get_number(input_format_t::msgpack, len) &&
10995 get_binary(input_format_t::msgpack, len, result);
11000 std::uint16_t len{};
11001 return get_number(input_format_t::msgpack, len) &&
11002 get_binary(input_format_t::msgpack, len, result);
11007 std::uint32_t len{};
11008 return get_number(input_format_t::msgpack, len) &&
11009 get_binary(input_format_t::msgpack, len, result);
11014 std::uint8_t len{};
11015 std::int8_t subtype{};
11016 return get_number(input_format_t::msgpack, len) &&
11017 get_number(input_format_t::msgpack, subtype) &&
11018 get_binary(input_format_t::msgpack, len, result) &&
11019 assign_and_return_true(subtype);
11024 std::uint16_t len{};
11025 std::int8_t subtype{};
11026 return get_number(input_format_t::msgpack, len) &&
11027 get_number(input_format_t::msgpack, subtype) &&
11028 get_binary(input_format_t::msgpack, len, result) &&
11029 assign_and_return_true(subtype);
11034 std::uint32_t len{};
11035 std::int8_t subtype{};
11036 return get_number(input_format_t::msgpack, len) &&
11037 get_number(input_format_t::msgpack, subtype) &&
11038 get_binary(input_format_t::msgpack, len, result) &&
11039 assign_and_return_true(subtype);
11044 std::int8_t subtype{};
11045 return get_number(input_format_t::msgpack, subtype) &&
11046 get_binary(input_format_t::msgpack, 1, result) &&
11047 assign_and_return_true(subtype);
11052 std::int8_t subtype{};
11053 return get_number(input_format_t::msgpack, subtype) &&
11054 get_binary(input_format_t::msgpack, 2, result) &&
11055 assign_and_return_true(subtype);
11060 std::int8_t subtype{};
11061 return get_number(input_format_t::msgpack, subtype) &&
11062 get_binary(input_format_t::msgpack, 4, result) &&
11063 assign_and_return_true(subtype);
11068 std::int8_t subtype{};
11069 return get_number(input_format_t::msgpack, subtype) &&
11070 get_binary(input_format_t::msgpack, 8, result) &&
11071 assign_and_return_true(subtype);
11076 std::int8_t subtype{};
11077 return get_number(input_format_t::msgpack, subtype) &&
11078 get_binary(input_format_t::msgpack, 16, result) &&
11079 assign_and_return_true(subtype);
11091 bool get_msgpack_array(
const std::size_t len) {
11092 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len))) {
11096 for (std::size_t i = 0; i < len; ++i) {
11097 if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal())) {
11102 return sax->end_array();
11109 bool get_msgpack_object(
const std::size_t len) {
11110 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len))) {
11115 for (std::size_t i = 0; i < len; ++i) {
11117 if (JSON_HEDLEY_UNLIKELY(!get_msgpack_string(key) || !sax->key(key))) {
11121 if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal())) {
11127 return sax->end_object();
11141 bool parse_ubjson_internal(
const bool get_char =
true) {
11142 return get_ubjson_value(get_char ? get_ignore_noop() : current);
11159 bool get_ubjson_string(string_t& result,
const bool get_char =
true) {
11164 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format,
"value"))) {
11171 std::uint8_t len{};
11172 return get_number(input_format, len) && get_string(input_format, len, result);
11178 return get_number(input_format, len) && get_string(input_format, len, result);
11183 std::int16_t len{};
11184 return get_number(input_format, len) && get_string(input_format, len, result);
11189 std::int32_t len{};
11190 return get_number(input_format, len) && get_string(input_format, len, result);
11195 std::int64_t len{};
11196 return get_number(input_format, len) && get_string(input_format, len, result);
11201 if (input_format != input_format_t::bjdata) {
11204 std::uint16_t len{};
11205 return get_number(input_format, len) && get_string(input_format, len, result);
11210 if (input_format != input_format_t::bjdata) {
11213 std::uint32_t len{};
11214 return get_number(input_format, len) && get_string(input_format, len, result);
11219 if (input_format != input_format_t::bjdata) {
11222 std::uint64_t len{};
11223 return get_number(input_format, len) && get_string(input_format, len, result);
11229 auto last_token = get_token_string();
11230 std::string message;
11232 if (input_format != input_format_t::bjdata) {
11233 message =
"expected length type specification (U, i, I, l, L); last byte: 0x" + last_token;
11236 message =
"expected length type specification (U, i, u, I, m, l, M, L); last byte: 0x" + last_token;
11238 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message,
"string"),
nullptr));
11245 bool get_ubjson_ndarray_size(std::vector<size_t>& dim) {
11246 std::pair<std::size_t, char_int_type> size_and_type;
11248 bool no_ndarray =
true;
11250 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type, no_ndarray))) {
11254 if (size_and_type.first != npos) {
11255 if (size_and_type.second != 0) {
11256 if (size_and_type.second !=
'N') {
11257 for (std::size_t i = 0; i < size_and_type.first; ++i) {
11258 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, size_and_type.second))) {
11261 dim.push_back(dimlen);
11266 for (std::size_t i = 0; i < size_and_type.first; ++i) {
11267 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray))) {
11270 dim.push_back(dimlen);
11275 while (current !=
']') {
11276 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, current))) {
11279 dim.push_back(dimlen);
11297 bool get_ubjson_size_value(std::size_t& result,
bool& is_ndarray, char_int_type prefix = 0) {
11299 prefix = get_ignore_noop();
11305 std::uint8_t number{};
11306 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) {
11309 result =
static_cast<std::size_t
>(number);
11315 std::int8_t number{};
11316 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) {
11320 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11321 exception_message(input_format,
"count in an optimized container must be positive",
"size"),
nullptr));
11323 result =
static_cast<std::size_t
>(number);
11329 std::int16_t number{};
11330 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) {
11334 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11335 exception_message(input_format,
"count in an optimized container must be positive",
"size"),
nullptr));
11337 result =
static_cast<std::size_t
>(number);
11343 std::int32_t number{};
11344 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) {
11348 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11349 exception_message(input_format,
"count in an optimized container must be positive",
"size"),
nullptr));
11351 result =
static_cast<std::size_t
>(number);
11357 std::int64_t number{};
11358 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) {
11362 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11363 exception_message(input_format,
"count in an optimized container must be positive",
"size"),
nullptr));
11365 if (!value_in_range_of<std::size_t>(number)) {
11366 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
11367 exception_message(input_format,
"integer value overflow",
"size"),
nullptr));
11369 result =
static_cast<std::size_t
>(number);
11375 if (input_format != input_format_t::bjdata) {
11378 std::uint16_t number{};
11379 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) {
11382 result =
static_cast<std::size_t
>(number);
11388 if (input_format != input_format_t::bjdata) {
11391 std::uint32_t number{};
11392 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) {
11395 result = conditional_static_cast<std::size_t>(number);
11401 if (input_format != input_format_t::bjdata) {
11404 std::uint64_t number{};
11405 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number))) {
11408 if (!value_in_range_of<std::size_t>(number)) {
11409 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
11410 exception_message(input_format,
"integer value overflow",
"size"),
nullptr));
11412 result = detail::conditional_static_cast<std::size_t>(number);
11418 if (input_format != input_format_t::bjdata) {
11423 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read, exception_message(input_format,
"ndarray dimensional vector is not allowed",
"size"),
nullptr));
11425 std::vector<size_t> dim;
11426 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_ndarray_size(dim))) {
11429 if (dim.size() == 1 || (dim.size() == 2 && dim.at(0) == 1))
11431 result = dim.at(dim.size() - 1);
11444 string_t key =
"_ArraySize_";
11445 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(3) || !sax->key(key) || !sax->start_array(dim.size()))) {
11449 for (
auto i : dim) {
11453 if (JSON_HEDLEY_UNLIKELY(i > 0 && result > (std::numeric_limits<std::size_t>::max)() / i)) {
11454 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408, exception_message(input_format,
"excessive ndarray size caused overflow",
"size"),
nullptr));
11458 if (result == 0 || result == npos) {
11459 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408, exception_message(input_format,
"excessive ndarray size caused overflow",
"size"),
nullptr));
11461 if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(
static_cast<number_unsigned_t
>(i)))) {
11466 return sax->end_array();
11475 auto last_token = get_token_string();
11476 std::string message;
11478 if (input_format != input_format_t::bjdata) {
11479 message =
"expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token;
11482 message =
"expected length type specification (U, i, u, I, m, l, M, L) after '#'; last byte: 0x" + last_token;
11484 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message,
"size"),
nullptr));
11498 bool get_ubjson_size_type(std::pair<std::size_t, char_int_type>& result,
bool inside_ndarray =
false) {
11499 result.first = npos;
11501 bool is_ndarray =
false;
11505 if (current ==
'$') {
11506 result.second = get();
11507 if (input_format == input_format_t::bjdata
11508 && JSON_HEDLEY_UNLIKELY(std::binary_search(bjd_optimized_type_markers.begin(), bjd_optimized_type_markers.end(), result.second))) {
11509 auto last_token = get_token_string();
11510 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11511 exception_message(input_format, concat(
"marker 0x", last_token,
" is not a permitted optimized array type"),
"type"),
nullptr));
11514 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format,
"type"))) {
11519 if (JSON_HEDLEY_UNLIKELY(current !=
'#')) {
11520 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format,
"value"))) {
11523 auto last_token = get_token_string();
11524 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11525 exception_message(input_format, concat(
"expected '#' after type information; last byte: 0x", last_token),
"size"),
nullptr));
11528 const bool is_error = get_ubjson_size_value(result.first, is_ndarray);
11529 if (input_format == input_format_t::bjdata && is_ndarray) {
11530 if (inside_ndarray) {
11531 return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
11532 exception_message(input_format,
"ndarray can not be recursive",
"size"),
nullptr));
11534 result.second |= (1 << 8);
11539 if (current ==
'#') {
11540 const bool is_error = get_ubjson_size_value(result.first, is_ndarray);
11541 if (input_format == input_format_t::bjdata && is_ndarray) {
11542 return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
11543 exception_message(input_format,
"ndarray requires both type and size",
"size"),
nullptr));
11555 bool get_ubjson_value(
const char_int_type prefix) {
11557 case char_traits<char_type>::eof():
11558 return unexpect_eof(input_format,
"value");
11561 return sax->boolean(
true);
11563 return sax->boolean(
false);
11566 return sax->null();
11570 if (input_format != input_format_t::bjdata) {
11573 std::uint8_t number{};
11574 return get_number(input_format, number) && sax->number_unsigned(number);
11579 std::uint8_t number{};
11580 return get_number(input_format, number) && sax->number_unsigned(number);
11585 std::int8_t number{};
11586 return get_number(input_format, number) && sax->number_integer(number);
11591 std::int16_t number{};
11592 return get_number(input_format, number) && sax->number_integer(number);
11597 std::int32_t number{};
11598 return get_number(input_format, number) && sax->number_integer(number);
11603 std::int64_t number{};
11604 return get_number(input_format, number) && sax->number_integer(number);
11609 if (input_format != input_format_t::bjdata) {
11612 std::uint16_t number{};
11613 return get_number(input_format, number) && sax->number_unsigned(number);
11618 if (input_format != input_format_t::bjdata) {
11621 std::uint32_t number{};
11622 return get_number(input_format, number) && sax->number_unsigned(number);
11627 if (input_format != input_format_t::bjdata) {
11630 std::uint64_t number{};
11631 return get_number(input_format, number) && sax->number_unsigned(number);
11636 if (input_format != input_format_t::bjdata) {
11639 const auto byte1_raw = get();
11640 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format,
"number"))) {
11643 const auto byte2_raw = get();
11644 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format,
"number"))) {
11648 const auto byte1 =
static_cast<unsigned char>(byte1_raw);
11649 const auto byte2 =
static_cast<unsigned char>(byte2_raw);
11659 const auto half =
static_cast<unsigned int>((byte2 << 8u) + byte1);
11660 const double val = [&half] {
11661 const int exp = (half >> 10u) & 0x1Fu;
11662 const unsigned int mant = half & 0x3FFu;
11663 JSON_ASSERT(0 <= exp && exp <= 32);
11664 JSON_ASSERT(mant <= 1024);
11667 return std::ldexp(mant, -24);
11670 ? std::numeric_limits<double>::infinity()
11671 : std::numeric_limits<double>::quiet_NaN();
11673 return std::ldexp(mant + 1024, exp - 25);
11676 return sax->number_float((half & 0x8000u) != 0
11677 ?
static_cast<number_float_t
>(-val)
11678 :
static_cast<number_float_t
>(val),
"");
11684 return get_number(input_format, number) && sax->number_float(
static_cast<number_float_t
>(number),
"");
11690 return get_number(input_format, number) && sax->number_float(
static_cast<number_float_t
>(number),
"");
11695 return get_ubjson_high_precision_number();
11701 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format,
"char"))) {
11704 if (JSON_HEDLEY_UNLIKELY(current > 127)) {
11705 auto last_token = get_token_string();
11706 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
11707 exception_message(input_format, concat(
"byte after 'C' must be in range 0x00..0x7F; last byte: 0x", last_token),
"char"),
nullptr));
11709 string_t s(1,
static_cast<typename string_t::value_type
>(current));
11710 return sax->string(s);
11716 return get_ubjson_string(s) && sax->string(s);
11720 return get_ubjson_array();
11723 return get_ubjson_object();
11728 auto last_token = get_token_string();
11729 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format,
"invalid byte: 0x" + last_token,
"value"),
nullptr));
11735 bool get_ubjson_array() {
11736 std::pair<std::size_t, char_int_type> size_and_type;
11737 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type))) {
11744 if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0) {
11745 size_and_type.second &= ~(
static_cast<char_int_type
>(1) << 8);
11746 auto it = std::lower_bound(bjd_types_map.begin(), bjd_types_map.end(), size_and_type.second, [](
const bjd_type& p, char_int_type t) {
11747 return p.first < t;
11749 string_t key =
"_ArrayType_";
11750 if (JSON_HEDLEY_UNLIKELY(it == bjd_types_map.end() || it->first != size_and_type.second)) {
11751 auto last_token = get_token_string();
11752 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11753 exception_message(input_format,
"invalid byte: 0x" + last_token,
"type"),
nullptr));
11756 string_t type = it->second;
11757 if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->string(type))) {
11761 if (size_and_type.second ==
'C' || size_and_type.second ==
'B') {
11762 size_and_type.second =
'U';
11765 key =
"_ArrayData_";
11766 if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->start_array(size_and_type.first))) {
11770 for (std::size_t i = 0; i < size_and_type.first; ++i) {
11771 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second))) {
11776 return (sax->end_array() && sax->end_object());
11780 if (input_format == input_format_t::bjdata && size_and_type.first != npos && size_and_type.second ==
'B') {
11782 return get_binary(input_format, size_and_type.first, result) && sax->binary(result);
11785 if (size_and_type.first != npos) {
11786 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first))) {
11790 if (size_and_type.second != 0) {
11791 if (size_and_type.second !=
'N') {
11792 for (std::size_t i = 0; i < size_and_type.first; ++i) {
11793 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second))) {
11800 for (std::size_t i = 0; i < size_and_type.first; ++i) {
11801 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal())) {
11808 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(detail::unknown_size()))) {
11812 while (current !=
']') {
11813 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal(
false))) {
11820 return sax->end_array();
11826 bool get_ubjson_object() {
11827 std::pair<std::size_t, char_int_type> size_and_type;
11828 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type))) {
11833 if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0) {
11834 auto last_token = get_token_string();
11835 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11836 exception_message(input_format,
"BJData object does not support ND-array size in optimized format",
"object"),
nullptr));
11840 if (size_and_type.first != npos) {
11841 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(size_and_type.first))) {
11845 if (size_and_type.second != 0) {
11846 for (std::size_t i = 0; i < size_and_type.first; ++i) {
11847 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key))) {
11850 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second))) {
11857 for (std::size_t i = 0; i < size_and_type.first; ++i) {
11858 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key))) {
11861 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal())) {
11869 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(detail::unknown_size()))) {
11873 while (current !=
'}') {
11874 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key,
false) || !sax->key(key))) {
11877 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal())) {
11885 return sax->end_object();
11891 bool get_ubjson_high_precision_number() {
11893 std::size_t size{};
11894 bool no_ndarray =
true;
11895 auto res = get_ubjson_size_value(size, no_ndarray);
11896 if (JSON_HEDLEY_UNLIKELY(!res)) {
11901 std::vector<char> number_vector;
11902 for (std::size_t i = 0; i < size; ++i) {
11904 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format,
"number"))) {
11907 number_vector.push_back(
static_cast<char>(current));
11911 using ia_type =
decltype(detail::input_adapter(number_vector));
11912 auto number_lexer = detail::lexer<BasicJsonType, ia_type>(detail::input_adapter(number_vector),
false);
11913 const auto result_number = number_lexer.scan();
11914 const auto number_string = number_lexer.get_token_string();
11915 const auto result_remainder = number_lexer.scan();
11919 if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input)) {
11920 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
11921 exception_message(input_format, concat(
"invalid number text: ", number_lexer.get_token_string()),
"high-precision number"),
nullptr));
11924 switch (result_number) {
11925 case token_type::value_integer:
11926 return sax->number_integer(number_lexer.get_number_integer());
11927 case token_type::value_unsigned:
11928 return sax->number_unsigned(number_lexer.get_number_unsigned());
11929 case token_type::value_float:
11930 return sax->number_float(number_lexer.get_number_float(), std::move(number_string));
11931 case token_type::uninitialized:
11932 case token_type::literal_true:
11933 case token_type::literal_false:
11934 case token_type::literal_null:
11935 case token_type::value_string:
11936 case token_type::begin_array:
11937 case token_type::begin_object:
11938 case token_type::end_array:
11939 case token_type::end_object:
11940 case token_type::name_separator:
11941 case token_type::value_separator:
11942 case token_type::parse_error:
11943 case token_type::end_of_input:
11944 case token_type::literal_or_value:
11946 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
11947 exception_message(input_format, concat(
"invalid number text: ", number_lexer.get_token_string()),
"high-precision number"),
nullptr));
11964 char_int_type get() {
11966 return current = ia.get_character();
11978 bool get_to(T& dest,
const input_format_t format,
const char* context) {
11979 auto new_chars_read = ia.get_elements(&dest);
11980 chars_read += new_chars_read;
11981 if (JSON_HEDLEY_UNLIKELY(new_chars_read <
sizeof(T))) {
11984 sax->parse_error(chars_read,
"<end of file>", parse_error::create(110, chars_read, exception_message(format,
"unexpected end of input", context),
nullptr));
11993 char_int_type get_ignore_noop() {
11996 }
while (current ==
'N');
12001 template<
class NumberType>
12002 static void byte_swap(NumberType& number) {
12003 constexpr std::size_t sz =
sizeof(number);
12004#ifdef __cpp_lib_byteswap
12005 if constexpr (sz == 1) {
12008 else if constexpr (std::is_integral_v<NumberType>) {
12009 number = std::byteswap(number);
12014 auto* ptr =
reinterpret_cast<std::uint8_t*
>(&number);
12015 for (std::size_t i = 0; i < sz / 2; ++i) {
12016 std::swap(ptr[i], ptr[sz - i - 1]);
12018#ifdef __cpp_lib_byteswap
12038 template<
typename NumberType,
bool InputIsLittleEndian = false>
12039 bool get_number(
const input_format_t format, NumberType& result) {
12042 if (JSON_HEDLEY_UNLIKELY(!get_to(result, format,
"number"))) {
12045 if (is_little_endian != (InputIsLittleEndian || format == input_format_t::bjdata)) {
12065 template<
typename NumberType>
12066 bool get_string(
const input_format_t format,
12067 const NumberType len,
12068 string_t& result) {
12069 bool success =
true;
12070 for (NumberType i = 0; i < len; i++) {
12072 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format,
"string"))) {
12076 result.push_back(
static_cast<typename string_t::value_type
>(current));
12095 template<
typename NumberType>
12096 bool get_binary(
const input_format_t format,
12097 const NumberType len,
12098 binary_t& result) {
12099 bool success =
true;
12100 for (NumberType i = 0; i < len; i++) {
12102 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format,
"binary"))) {
12106 result.push_back(
static_cast<typename binary_t::value_type
>(current));
12116 JSON_HEDLEY_NON_NULL(3)
12117 bool unexpect_eof(const input_format_t format, const
char* context)
const {
12118 if (JSON_HEDLEY_UNLIKELY(current == char_traits<char_type>::eof())) {
12119 return sax->parse_error(chars_read,
"<end of file>",
12120 parse_error::create(110, chars_read, exception_message(format,
"unexpected end of input", context),
nullptr));
12128 std::string get_token_string()
const {
12129 std::array<char, 3> cr{ {} };
12130 static_cast<void>((std::snprintf)(cr.data(), cr.size(),
"%.2hhX",
static_cast<unsigned char>(current)));
12131 return std::string{ cr.data() };
12140 std::string exception_message(
const input_format_t format,
12141 const std::string& detail,
12142 const std::string& context)
const {
12143 std::string error_msg =
"syntax error while parsing ";
12146 case input_format_t::cbor:
12147 error_msg +=
"CBOR";
12150 case input_format_t::msgpack:
12151 error_msg +=
"MessagePack";
12154 case input_format_t::ubjson:
12155 error_msg +=
"UBJSON";
12158 case input_format_t::bson:
12159 error_msg +=
"BSON";
12162 case input_format_t::bjdata:
12163 error_msg +=
"BJData";
12166 case input_format_t::json:
12168 JSON_ASSERT(
false);
12171 return concat(error_msg,
' ', context,
": ", detail);
12175 static JSON_INLINE_VARIABLE
constexpr std::size_t npos = detail::unknown_size();
12178 InputAdapterType ia;
12181 char_int_type current = char_traits<char_type>::eof();
12184 std::size_t chars_read = 0;
12193 json_sax_t* sax =
nullptr;
12196#define JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_ \
12197 make_array<char_int_type>('F', 'H', 'N', 'S', 'T', 'Z', '[', '{')
12199#define JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_ \
12200 make_array<bjd_type>( \
12201 bjd_type{'B', "byte"}, \
12202 bjd_type{'C', "char"}, \
12203 bjd_type{'D', "double"}, \
12204 bjd_type{'I', "int16"}, \
12205 bjd_type{'L', "int64"}, \
12206 bjd_type{'M', "uint64"}, \
12207 bjd_type{'U', "uint8"}, \
12208 bjd_type{'d', "single"}, \
12209 bjd_type{'i', "int8"}, \
12210 bjd_type{'l', "int32"}, \
12211 bjd_type{'m', "uint32"}, \
12212 bjd_type{'u', "uint16"})
12214 JSON_PRIVATE_UNLESS_TESTED:
12217 const decltype(JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_) bjd_optimized_type_markers =
12218 JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_;
12220 using bjd_type = std::pair<char_int_type, string_t>;
12222 const decltype(JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_) bjd_types_map =
12223 JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_;
12225#undef JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_
12226#undef JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_
17650 using string_t =
typename BasicJsonType::string_t;
17651 using number_float_t =
typename BasicJsonType::number_float_t;
17652 using number_integer_t =
typename BasicJsonType::number_integer_t;
17653 using number_unsigned_t =
typename BasicJsonType::number_unsigned_t;
17654 using binary_char_t =
typename BasicJsonType::binary_t::value_type;
17655 static constexpr std::uint8_t UTF8_ACCEPT = 0;
17656 static constexpr std::uint8_t UTF8_REJECT = 1;
17667 , loc(std::localeconv())
17668 , thousands_sep(loc->thousands_sep == nullptr ?
'\0' : std::
char_traits<char>::to_char_type(*(loc->thousands_sep)))
17669 , decimal_point(loc->decimal_point == nullptr ?
'\0' : std::
char_traits<char>::to_char_type(*(loc->decimal_point)))
17670 , indent_char(ichar)
17671 , indent_string(512, indent_char)
17672 , error_handler(error_handler_) {}
17704 const bool pretty_print,
17705 const bool ensure_ascii,
17706 const unsigned int indent_step,
17707 const unsigned int current_indent = 0) {
17708 switch (val.m_data.m_type) {
17711 if (val.m_data.m_value.object->empty()) {
17712 o->write_characters(
"{}", 2);
17716 if (pretty_print) {
17717 o->write_characters(
"{\n", 2);
17720 const auto new_indent = current_indent + indent_step;
17721 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent)) {
17722 indent_string.resize(indent_string.size() * 2,
' ');
17726 auto i = val.m_data.m_value.object->cbegin();
17727 for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i) {
17728 o->write_characters(indent_string.c_str(), new_indent);
17729 o->write_character(
'\"');
17730 dump_escaped(i->first, ensure_ascii);
17731 o->write_characters(
"\": ", 3);
17732 dump(i->second,
true, ensure_ascii, indent_step, new_indent);
17733 o->write_characters(
",\n", 2);
17737 JSON_ASSERT(i != val.m_data.m_value.object->cend());
17738 JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend());
17739 o->write_characters(indent_string.c_str(), new_indent);
17740 o->write_character(
'\"');
17741 dump_escaped(i->first, ensure_ascii);
17742 o->write_characters(
"\": ", 3);
17743 dump(i->second,
true, ensure_ascii, indent_step, new_indent);
17745 o->write_character(
'\n');
17746 o->write_characters(indent_string.c_str(), current_indent);
17747 o->write_character(
'}');
17750 o->write_character(
'{');
17753 auto i = val.m_data.m_value.object->cbegin();
17754 for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i) {
17755 o->write_character(
'\"');
17756 dump_escaped(i->first, ensure_ascii);
17757 o->write_characters(
"\":", 2);
17758 dump(i->second,
false, ensure_ascii, indent_step, current_indent);
17759 o->write_character(
',');
17763 JSON_ASSERT(i != val.m_data.m_value.object->cend());
17764 JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend());
17765 o->write_character(
'\"');
17766 dump_escaped(i->first, ensure_ascii);
17767 o->write_characters(
"\":", 2);
17768 dump(i->second,
false, ensure_ascii, indent_step, current_indent);
17770 o->write_character(
'}');
17778 if (val.m_data.m_value.array->empty()) {
17779 o->write_characters(
"[]", 2);
17783 if (pretty_print) {
17784 o->write_characters(
"[\n", 2);
17787 const auto new_indent = current_indent + indent_step;
17788 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent)) {
17789 indent_string.resize(indent_string.size() * 2,
' ');
17793 for (
auto i = val.m_data.m_value.array->cbegin();
17794 i != val.m_data.m_value.array->cend() - 1; ++i) {
17795 o->write_characters(indent_string.c_str(), new_indent);
17796 dump(*i,
true, ensure_ascii, indent_step, new_indent);
17797 o->write_characters(
",\n", 2);
17801 JSON_ASSERT(!val.m_data.m_value.array->empty());
17802 o->write_characters(indent_string.c_str(), new_indent);
17803 dump(val.m_data.m_value.array->back(),
true, ensure_ascii, indent_step, new_indent);
17805 o->write_character(
'\n');
17806 o->write_characters(indent_string.c_str(), current_indent);
17807 o->write_character(
']');
17810 o->write_character(
'[');
17813 for (
auto i = val.m_data.m_value.array->cbegin();
17814 i != val.m_data.m_value.array->cend() - 1; ++i) {
17815 dump(*i,
false, ensure_ascii, indent_step, current_indent);
17816 o->write_character(
',');
17820 JSON_ASSERT(!val.m_data.m_value.array->empty());
17821 dump(val.m_data.m_value.array->back(),
false, ensure_ascii, indent_step, current_indent);
17823 o->write_character(
']');
17831 o->write_character(
'\"');
17832 dump_escaped(*val.m_data.m_value.string, ensure_ascii);
17833 o->write_character(
'\"');
17839 if (pretty_print) {
17840 o->write_characters(
"{\n", 2);
17843 const auto new_indent = current_indent + indent_step;
17844 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent)) {
17845 indent_string.resize(indent_string.size() * 2,
' ');
17848 o->write_characters(indent_string.c_str(), new_indent);
17850 o->write_characters(
"\"bytes\": [", 10);
17852 if (!val.m_data.m_value.binary->empty()) {
17853 for (
auto i = val.m_data.m_value.binary->cbegin();
17854 i != val.m_data.m_value.binary->cend() - 1; ++i) {
17856 o->write_characters(
", ", 2);
17858 dump_integer(val.m_data.m_value.binary->back());
17861 o->write_characters(
"],\n", 3);
17862 o->write_characters(indent_string.c_str(), new_indent);
17864 o->write_characters(
"\"subtype\": ", 11);
17865 if (val.m_data.m_value.binary->has_subtype()) {
17866 dump_integer(val.m_data.m_value.binary->subtype());
17869 o->write_characters(
"null", 4);
17871 o->write_character(
'\n');
17872 o->write_characters(indent_string.c_str(), current_indent);
17873 o->write_character(
'}');
17876 o->write_characters(
"{\"bytes\":[", 10);
17878 if (!val.m_data.m_value.binary->empty()) {
17879 for (
auto i = val.m_data.m_value.binary->cbegin();
17880 i != val.m_data.m_value.binary->cend() - 1; ++i) {
17882 o->write_character(
',');
17884 dump_integer(val.m_data.m_value.binary->back());
17887 o->write_characters(
"],\"subtype\":", 12);
17888 if (val.m_data.m_value.binary->has_subtype()) {
17889 dump_integer(val.m_data.m_value.binary->subtype());
17890 o->write_character(
'}');
17893 o->write_characters(
"null}", 5);
17901 if (val.m_data.m_value.boolean) {
17902 o->write_characters(
"true", 4);
17905 o->write_characters(
"false", 5);
17912 dump_integer(val.m_data.m_value.number_integer);
17918 dump_integer(val.m_data.m_value.number_unsigned);
17924 dump_float(val.m_data.m_value.number_float);
17930 o->write_characters(
"<discarded>", 11);
17936 o->write_characters(
"null", 4);
17941 JSON_ASSERT(
false);
17945 JSON_PRIVATE_UNLESS_TESTED:
17960 void dump_escaped(
const string_t& s,
const bool ensure_ascii) {
17961 std::uint32_t codepoint{};
17962 std::uint8_t state = UTF8_ACCEPT;
17963 std::size_t bytes = 0;
17966 std::size_t bytes_after_last_accept = 0;
17967 std::size_t undumped_chars = 0;
17969 for (std::size_t i = 0; i < s.size(); ++i) {
17970 const auto byte =
static_cast<std::uint8_t
>(s[i]);
17972 switch (decode(state, codepoint,
byte)) {
17975 switch (codepoint) {
17978 string_buffer[bytes++] =
'\\';
17979 string_buffer[bytes++] =
'b';
17985 string_buffer[bytes++] =
'\\';
17986 string_buffer[bytes++] =
't';
17992 string_buffer[bytes++] =
'\\';
17993 string_buffer[bytes++] =
'n';
17999 string_buffer[bytes++] =
'\\';
18000 string_buffer[bytes++] =
'f';
18006 string_buffer[bytes++] =
'\\';
18007 string_buffer[bytes++] =
'r';
18013 string_buffer[bytes++] =
'\\';
18014 string_buffer[bytes++] =
'\"';
18020 string_buffer[bytes++] =
'\\';
18021 string_buffer[bytes++] =
'\\';
18029 if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F))) {
18030 if (codepoint <= 0xFFFF) {
18032 static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 7,
"\\u%04x",
18033 static_cast<std::uint16_t
>(codepoint)));
18038 static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 13,
"\\u%04x\\u%04x",
18039 static_cast<std::uint16_t
>(0xD7C0u + (codepoint >> 10u)),
18040 static_cast<std::uint16_t
>(0xDC00u + (codepoint & 0x3FFu))));
18047 string_buffer[bytes++] = s[i];
18056 if (string_buffer.size() - bytes < 13) {
18057 o->write_characters(string_buffer.data(), bytes);
18062 bytes_after_last_accept = bytes;
18063 undumped_chars = 0;
18069 switch (error_handler) {
18070 case error_handler_t::strict:
18072 JSON_THROW(type_error::create(316, concat(
"invalid UTF-8 byte at index ", std::to_string(i),
": 0x", hex_bytes(
byte | 0)),
nullptr));
18075 case error_handler_t::ignore:
18076 case error_handler_t::replace:
18082 if (undumped_chars > 0) {
18088 bytes = bytes_after_last_accept;
18090 if (error_handler == error_handler_t::replace) {
18092 if (ensure_ascii) {
18093 string_buffer[bytes++] =
'\\';
18094 string_buffer[bytes++] =
'u';
18095 string_buffer[bytes++] =
'f';
18096 string_buffer[bytes++] =
'f';
18097 string_buffer[bytes++] =
'f';
18098 string_buffer[bytes++] =
'd';
18101 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type(
'\xEF');
18102 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type(
'\xBF');
18103 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type(
'\xBD');
18109 if (string_buffer.size() - bytes < 13) {
18110 o->write_characters(string_buffer.data(), bytes);
18114 bytes_after_last_accept = bytes;
18117 undumped_chars = 0;
18120 state = UTF8_ACCEPT;
18125 JSON_ASSERT(
false);
18132 if (!ensure_ascii) {
18134 string_buffer[bytes++] = s[i];
18143 if (JSON_HEDLEY_LIKELY(state == UTF8_ACCEPT)) {
18146 o->write_characters(string_buffer.data(), bytes);
18151 switch (error_handler) {
18152 case error_handler_t::strict:
18154 JSON_THROW(type_error::create(316, concat(
"incomplete UTF-8 string; last byte: 0x", hex_bytes(
static_cast<std::uint8_t
>(s.back() | 0))),
nullptr));
18157 case error_handler_t::ignore:
18160 o->write_characters(string_buffer.data(), bytes_after_last_accept);
18164 case error_handler_t::replace:
18167 o->write_characters(string_buffer.data(), bytes_after_last_accept);
18169 if (ensure_ascii) {
18170 o->write_characters(
"\\ufffd", 6);
18173 o->write_characters(
"\xEF\xBF\xBD", 3);
18179 JSON_ASSERT(
false);
18193 unsigned int count_digits(number_unsigned_t x)
noexcept {
18194 unsigned int n_digits = 1;
18200 return n_digits + 1;
18203 return n_digits + 2;
18206 return n_digits + 3;
18218 static std::string hex_bytes(std::uint8_t
byte) {
18219 std::string result =
"FF";
18220 constexpr const char* nibble_to_hex =
"0123456789ABCDEF";
18221 result[0] = nibble_to_hex[
byte / 16];
18222 result[1] = nibble_to_hex[
byte % 16];
18227 template <typename NumberType, enable_if_t<std::is_signed<NumberType>::value,
int> = 0>
18228 bool is_negative_number(NumberType x) {
18232 template < typename NumberType, enable_if_t <std::is_unsigned<NumberType>::value,
int > = 0 >
18233 bool is_negative_number(NumberType ) {
18246 template <
typename NumberType, detail::enable_if_t <
18247 std::is_integral<NumberType>::value ||
18248 std::is_same<NumberType, number_unsigned_t>::value ||
18249 std::is_same<NumberType, number_integer_t>::value ||
18250 std::is_same<NumberType, binary_char_t>::value,
18252 void dump_integer(NumberType x) {
18253 static constexpr std::array<std::array<char, 2>, 100> digits_to_99
18256 {{
'0',
'0'}}, {{
'0',
'1'}}, {{
'0',
'2'}}, {{
'0',
'3'}}, {{
'0',
'4'}}, {{
'0',
'5'}}, {{
'0',
'6'}}, {{
'0',
'7'}}, {{
'0',
'8'}}, {{
'0',
'9'}},
18257 {{
'1',
'0'}}, {{
'1',
'1'}}, {{
'1',
'2'}}, {{
'1',
'3'}}, {{
'1',
'4'}}, {{
'1',
'5'}}, {{
'1',
'6'}}, {{
'1',
'7'}}, {{
'1',
'8'}}, {{
'1',
'9'}},
18258 {{
'2',
'0'}}, {{
'2',
'1'}}, {{
'2',
'2'}}, {{
'2',
'3'}}, {{
'2',
'4'}}, {{
'2',
'5'}}, {{
'2',
'6'}}, {{
'2',
'7'}}, {{
'2',
'8'}}, {{
'2',
'9'}},
18259 {{
'3',
'0'}}, {{
'3',
'1'}}, {{
'3',
'2'}}, {{
'3',
'3'}}, {{
'3',
'4'}}, {{
'3',
'5'}}, {{
'3',
'6'}}, {{
'3',
'7'}}, {{
'3',
'8'}}, {{
'3',
'9'}},
18260 {{
'4',
'0'}}, {{
'4',
'1'}}, {{
'4',
'2'}}, {{
'4',
'3'}}, {{
'4',
'4'}}, {{
'4',
'5'}}, {{
'4',
'6'}}, {{
'4',
'7'}}, {{
'4',
'8'}}, {{
'4',
'9'}},
18261 {{
'5',
'0'}}, {{
'5',
'1'}}, {{
'5',
'2'}}, {{
'5',
'3'}}, {{
'5',
'4'}}, {{
'5',
'5'}}, {{
'5',
'6'}}, {{
'5',
'7'}}, {{
'5',
'8'}}, {{
'5',
'9'}},
18262 {{
'6',
'0'}}, {{
'6',
'1'}}, {{
'6',
'2'}}, {{
'6',
'3'}}, {{
'6',
'4'}}, {{
'6',
'5'}}, {{
'6',
'6'}}, {{
'6',
'7'}}, {{
'6',
'8'}}, {{
'6',
'9'}},
18263 {{
'7',
'0'}}, {{
'7',
'1'}}, {{
'7',
'2'}}, {{
'7',
'3'}}, {{
'7',
'4'}}, {{
'7',
'5'}}, {{
'7',
'6'}}, {{
'7',
'7'}}, {{
'7',
'8'}}, {{
'7',
'9'}},
18264 {{
'8',
'0'}}, {{
'8',
'1'}}, {{
'8',
'2'}}, {{
'8',
'3'}}, {{
'8',
'4'}}, {{
'8',
'5'}}, {{
'8',
'6'}}, {{
'8',
'7'}}, {{
'8',
'8'}}, {{
'8',
'9'}},
18265 {{
'9',
'0'}}, {{
'9',
'1'}}, {{
'9',
'2'}}, {{
'9',
'3'}}, {{
'9',
'4'}}, {{
'9',
'5'}}, {{
'9',
'6'}}, {{
'9',
'7'}}, {{
'9',
'8'}}, {{
'9',
'9'}},
18271 o->write_character(
'0');
18276 auto buffer_ptr = number_buffer.begin();
18278 number_unsigned_t abs_value;
18280 unsigned int n_chars{};
18282 if (is_negative_number(x)) {
18284 abs_value = remove_sign(
static_cast<number_integer_t
>(x));
18287 n_chars = 1 + count_digits(abs_value);
18290 abs_value =
static_cast<number_unsigned_t
>(x);
18291 n_chars = count_digits(abs_value);
18295 JSON_ASSERT(n_chars < number_buffer.size() - 1);
18299 buffer_ptr +=
static_cast<typename decltype(number_buffer)::difference_type
>(n_chars);
18303 while (abs_value >= 100) {
18304 const auto digits_index =
static_cast<unsigned>((abs_value % 100));
18306 *(--buffer_ptr) = digits_to_99[digits_index][1];
18307 *(--buffer_ptr) = digits_to_99[digits_index][0];
18310 if (abs_value >= 10) {
18311 const auto digits_index =
static_cast<unsigned>(abs_value);
18312 *(--buffer_ptr) = digits_to_99[digits_index][1];
18313 *(--buffer_ptr) = digits_to_99[digits_index][0];
18316 *(--buffer_ptr) =
static_cast<char>(
'0' + abs_value);
18319 o->write_characters(number_buffer.data(), n_chars);
18330 void dump_float(number_float_t x) {
18332 if (!std::isfinite(x)) {
18333 o->write_characters(
"null", 4);
18342 static constexpr bool is_ieee_single_or_double
18343 = (std::numeric_limits<number_float_t>::is_iec559 && std::numeric_limits<number_float_t>::digits == 24 && std::numeric_limits<number_float_t>::max_exponent == 128) ||
18344 (std::numeric_limits<number_float_t>::is_iec559 && std::numeric_limits<number_float_t>::digits == 53 && std::numeric_limits<number_float_t>::max_exponent == 1024);
18346 dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
18349 void dump_float(number_float_t x, std::true_type ) {
18350 auto* begin = number_buffer.data();
18351 auto* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x);
18353 o->write_characters(begin,
static_cast<size_t>(end - begin));
18356 void dump_float(number_float_t x, std::false_type ) {
18358 static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10;
18362 std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(),
"%.*g", d, x);
18365 JSON_ASSERT(len > 0);
18367 JSON_ASSERT(
static_cast<std::size_t
>(len) < number_buffer.size());
18370 if (thousands_sep !=
'\0') {
18372 const auto end = std::remove(number_buffer.begin(), number_buffer.begin() + len, thousands_sep);
18373 std::fill(end, number_buffer.end(),
'\0');
18374 JSON_ASSERT((end - number_buffer.begin()) <= len);
18375 len = (end - number_buffer.begin());
18379 if (decimal_point !=
'\0' && decimal_point !=
'.') {
18381 const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
18382 if (dec_pos != number_buffer.end()) {
18387 o->write_characters(number_buffer.data(),
static_cast<std::size_t
>(len));
18390 const bool value_is_int_like =
18391 std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
18393 return c ==
'.' || c ==
'e';
18396 if (value_is_int_like) {
18397 o->write_characters(
".0", 2);
18422 static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep,
const std::uint8_t
byte)
noexcept {
18423 static const std::array<std::uint8_t, 400> utf8d =
18426 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
18427 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
18428 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
18429 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
18430 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
18431 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
18432 8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
18433 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3,
18434 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8,
18435 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1,
18436 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1,
18437 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1,
18438 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1,
18439 1, 3, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
18443 JSON_ASSERT(
static_cast<std::size_t
>(
byte) < utf8d.size());
18444 const std::uint8_t type = utf8d[byte];
18446 codep = (state != UTF8_ACCEPT)
18447 ? (
byte & 0x3fu) | (codep << 6u)
18448 : (0xFFu >> type) & (byte);
18450 const std::size_t index = 256u + (
static_cast<size_t>(state) * 16u) +
static_cast<size_t>(type);
18451 JSON_ASSERT(index < utf8d.size());
18452 state = utf8d[index];
18461 number_unsigned_t remove_sign(number_unsigned_t x) {
18462 JSON_ASSERT(
false);
18475 number_unsigned_t remove_sign(number_integer_t x)
noexcept {
18476 JSON_ASSERT(x < 0 && x < (std::numeric_limits<number_integer_t>::max)());
18477 return static_cast<number_unsigned_t
>(-(x + 1)) + 1;
18482 output_adapter_t<char> o =
nullptr;
18485 std::array<char, 64> number_buffer{ {} };
18488 const std::lconv* loc =
nullptr;
18490 const char thousands_sep =
'\0';
18492 const char decimal_point =
'\0';
18495 std::array<char, 512> string_buffer{ {} };
18498 const char indent_char;
18500 string_t indent_string;
18860 :
public ::nlohmann::detail::json_base_class<CustomBaseClass> {
18865 friend class ::nlohmann::json_pointer;
18869 template<
typename BasicJsonType,
typename InputType>
18870 friend class ::nlohmann::detail::parser;
18871 friend ::nlohmann::detail::serializer<basic_json>;
18872 template<
typename BasicJsonType>
18873 friend class ::nlohmann::detail::iter_impl;
18874 template<
typename BasicJsonType,
typename CharType>
18875 friend class ::nlohmann::detail::binary_writer;
18876 template<
typename BasicJsonType,
typename InputType,
typename SAX>
18877 friend class ::nlohmann::detail::binary_reader;
18878 template<
typename BasicJsonType,
typename InputAdapterType>
18879 friend class ::nlohmann::detail::json_sax_dom_parser;
18880 template<
typename BasicJsonType,
typename InputAdapterType>
18881 friend class ::nlohmann::detail::json_sax_dom_callback_parser;
18882 friend class ::nlohmann::detail::exception;
18885 using basic_json_t = NLOHMANN_BASIC_JSON_TPL;
18886 using json_base_class_t = ::nlohmann::detail::json_base_class<CustomBaseClass>;
18888JSON_PRIVATE_UNLESS_TESTED:
18890 using lexer = ::nlohmann::detail::lexer_base<basic_json>;
18892 template<
typename InputAdapterType>
18893 static ::nlohmann::detail::parser<basic_json, InputAdapterType> parser(
18894 InputAdapterType adapter,
18895 detail::parser_callback_t<basic_json>cb =
nullptr,
18896 const bool allow_exceptions =
true,
18897 const bool ignore_comments =
false,
18898 const bool ignore_trailing_commas =
false
18900 return ::nlohmann::detail::parser<basic_json, InputAdapterType>(std::move(adapter),
18901 std::move(cb), allow_exceptions, ignore_comments, ignore_trailing_commas);
18905 using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t;
18906 template<
typename BasicJsonType>
18907 using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>;
18908 template<
typename BasicJsonType>
18909 using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>;
18910 template<
typename Iterator>
18911 using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>;
18912 template<
typename Base>
using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>;
18914 template<
typename CharType>
18915 using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;
18917 template<
typename InputType>
18918 using binary_reader = ::nlohmann::detail::binary_reader<basic_json, InputType>;
18919 template<
typename CharType>
using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>;
18921JSON_PRIVATE_UNLESS_TESTED:
18922 using serializer = ::nlohmann::detail::serializer<basic_json>;
18927 using json_pointer = ::nlohmann::json_pointer<StringType>;
18928 template<
typename T,
typename SFINAE>
18929 using json_serializer = JSONSerializer<T, SFINAE>;
18935 using bjdata_version_t = detail::bjdata_version_t;
18937 using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
18970 using value_type = basic_json;
18973 using reference = value_type&;
18975 using const_reference =
const value_type&;
18978 using difference_type = std::ptrdiff_t;
18980 using size_type = std::size_t;
18983 using allocator_type = AllocatorType<basic_json>;
18986 using pointer =
typename std::allocator_traits<allocator_type>::pointer;
18988 using const_pointer =
typename std::allocator_traits<allocator_type>::const_pointer;
18991 using iterator = iter_impl<basic_json>;
18993 using const_iterator = iter_impl<const basic_json>;
18995 using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;
18997 using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>;
19003 static allocator_type get_allocator() {
19004 return allocator_type();
19009 JSON_HEDLEY_WARN_UNUSED_RESULT
19010 static basic_json meta() {
19013 result[
"copyright"] =
"(C) 2013-2026 Niels Lohmann";
19014 result[
"name"] =
"JSON for Modern C++";
19015 result[
"url"] =
"https://github.com/nlohmann/json";
19016 result[
"version"][
"string"] =
19017 detail::concat(std::to_string(NLOHMANN_JSON_VERSION_MAJOR),
'.',
19018 std::to_string(NLOHMANN_JSON_VERSION_MINOR),
'.',
19019 std::to_string(NLOHMANN_JSON_VERSION_PATCH));
19020 result[
"version"][
"major"] = NLOHMANN_JSON_VERSION_MAJOR;
19021 result[
"version"][
"minor"] = NLOHMANN_JSON_VERSION_MINOR;
19022 result[
"version"][
"patch"] = NLOHMANN_JSON_VERSION_PATCH;
19025 result[
"platform"] =
"win32";
19026#elif defined __linux__
19027 result[
"platform"] =
"linux";
19028#elif defined __APPLE__
19029 result[
"platform"] =
"apple";
19030#elif defined __unix__
19031 result[
"platform"] =
"unix";
19033 result[
"platform"] =
"unknown";
19036#if defined(__ICC) || defined(__INTEL_COMPILER)
19037 result[
"compiler"] = { {
"family",
"icc"}, {
"version", __INTEL_COMPILER} };
19038#elif defined(__clang__)
19039 result[
"compiler"] = { {
"family",
"clang"}, {
"version", __clang_version__} };
19040#elif defined(__GNUC__) || defined(__GNUG__)
19041 result[
"compiler"] = { {
"family",
"gcc"}, {
"version", detail::concat(
19042 std::to_string(__GNUC__),
'.',
19043 std::to_string(__GNUC_MINOR__),
'.',
19044 std::to_string(__GNUC_PATCHLEVEL__))
19047#elif defined(__HP_cc) || defined(__HP_aCC)
19048 result[
"compiler"] =
"hp"
19049#elif defined(__IBMCPP__)
19050 result[
"compiler"] = { {
"family",
"ilecpp"}, {
"version", __IBMCPP__} };
19051#elif defined(_MSC_VER)
19052 result[
"compiler"] = { {
"family",
"msvc"}, {
"version", _MSC_VER} };
19053#elif defined(__PGI)
19054 result[
"compiler"] = { {
"family",
"pgcpp"}, {
"version", __PGI} };
19055#elif defined(__SUNPRO_CC)
19056 result[
"compiler"] = { {
"family",
"sunpro"}, {
"version", __SUNPRO_CC} };
19058 result[
"compiler"] = { {
"family",
"unknown"}, {
"version",
"unknown"} };
19061#if defined(_MSVC_LANG)
19062 result[
"compiler"][
"c++"] = std::to_string(_MSVC_LANG);
19063#elif defined(__cplusplus)
19064 result[
"compiler"][
"c++"] = std::to_string(__cplusplus);
19066 result[
"compiler"][
"c++"] =
"unknown";
19084#if defined(JSON_HAS_CPP_14)
19087 using default_object_comparator_t = std::less<>;
19089 using default_object_comparator_t = std::less<StringType>;
19094 using object_t = ObjectType<StringType,
19096 default_object_comparator_t,
19097 AllocatorType<std::pair<
const StringType,
19102 using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
19106 using string_t = StringType;
19110 using boolean_t = BooleanType;
19114 using number_integer_t = NumberIntegerType;
19118 using number_unsigned_t = NumberUnsignedType;
19122 using number_float_t = NumberFloatType;
19126 using binary_t = nlohmann::byte_container_with_subtype<BinaryType>;
19130 using object_comparator_t = detail::actual_object_comparator_t<basic_json>;
19137 template<
typename T,
typename... Args>
19138 JSON_HEDLEY_RETURNS_NON_NULL
19139 static T* create(Args&& ... args) {
19140 AllocatorType<T> alloc;
19141 using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
19143 auto deleter = [&](T* obj) {
19144 AllocatorTraits::deallocate(alloc, obj, 1);
19146 std::unique_ptr<T,
decltype(deleter)> obj(AllocatorTraits::allocate(alloc, 1), deleter);
19147 AllocatorTraits::construct(alloc, obj.get(), std::forward<Args>(args)...);
19148 JSON_ASSERT(obj !=
nullptr);
19149 return obj.release();
19156JSON_PRIVATE_UNLESS_TESTED:
19194 number_integer_t number_integer;
19196 number_unsigned_t number_unsigned;
19198 number_float_t number_float;
19201 json_value() =
default;
19203 json_value(boolean_t v) noexcept : boolean(v) {}
19205 json_value(number_integer_t v) noexcept : number_integer(v) {}
19207 json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
19209 json_value(number_float_t v) noexcept : number_float(v) {}
19211 json_value(value_t t) {
19213 case value_t::object:
19215 object = create<object_t>();
19219 case value_t::array:
19221 array = create<array_t>();
19225 case value_t::string:
19227 string = create<string_t>(
"");
19231 case value_t::binary:
19233 binary = create<binary_t>();
19237 case value_t::boolean:
19239 boolean =
static_cast<boolean_t
>(
false);
19243 case value_t::number_integer:
19245 number_integer =
static_cast<number_integer_t
>(0);
19249 case value_t::number_unsigned:
19251 number_unsigned =
static_cast<number_unsigned_t
>(0);
19255 case value_t::number_float:
19257 number_float =
static_cast<number_float_t
>(0.0);
19261 case value_t::null:
19267 case value_t::discarded:
19271 if (JSON_HEDLEY_UNLIKELY(t == value_t::null)) {
19272 JSON_THROW(other_error::create(500,
"961c151d2e87f2686a955a9be24d316f1362bf21 3.12.0",
nullptr));
19280 json_value(
const string_t& value) : string(create<string_t>(value)) {}
19283 json_value(string_t&& value) : string(create<string_t>(std::move(value))) {}
19286 json_value(
const object_t& value) : object(create<object_t>(value)) {}
19289 json_value(object_t&& value) : object(create<object_t>(std::move(value))) {}
19292 json_value(
const array_t& value) : array(create<array_t>(value)) {}
19295 json_value(array_t&& value) : array(create<array_t>(std::move(value))) {}
19298 json_value(
const typename binary_t::container_type& value) : binary(create<binary_t>(value)) {}
19301 json_value(
typename binary_t::container_type&& value) : binary(create<binary_t>(std::move(value))) {}
19304 json_value(
const binary_t& value) : binary(create<binary_t>(value)) {}
19307 json_value(binary_t&& value) : binary(create<binary_t>(std::move(value))) {}
19309 void destroy(value_t t) {
19311 (t == value_t::object &&
object ==
nullptr) ||
19312 (t == value_t::array && array ==
nullptr) ||
19313 (t == value_t::string &&
string ==
nullptr) ||
19314 (t == value_t::binary && binary ==
nullptr)
19319 if (t == value_t::array || t == value_t::object) {
19321 std::vector<basic_json> stack;
19324 if (t == value_t::array) {
19325 stack.reserve(array->size());
19326 std::move(array->begin(), array->end(), std::back_inserter(stack));
19329 stack.reserve(object->size());
19330 for (
auto&& it : *
object) {
19331 stack.push_back(std::move(it.second));
19335 while (!stack.empty()) {
19337 basic_json current_item(std::move(stack.back()));
19342 if (current_item.is_array()) {
19343 std::move(current_item.m_data.m_value.array->begin(), current_item.m_data.m_value.array->end(), std::back_inserter(stack));
19345 current_item.m_data.m_value.array->clear();
19347 else if (current_item.is_object()) {
19348 for (
auto&& it : *current_item.m_data.m_value.object) {
19349 stack.push_back(std::move(it.second));
19352 current_item.m_data.m_value.object->clear();
19361 case value_t::object:
19363 AllocatorType<object_t> alloc;
19364 std::allocator_traits<
decltype(alloc)>::destroy(alloc,
object);
19365 std::allocator_traits<
decltype(alloc)>::deallocate(alloc,
object, 1);
19369 case value_t::array:
19371 AllocatorType<array_t> alloc;
19372 std::allocator_traits<
decltype(alloc)>::destroy(alloc, array);
19373 std::allocator_traits<
decltype(alloc)>::deallocate(alloc, array, 1);
19377 case value_t::string:
19379 AllocatorType<string_t> alloc;
19380 std::allocator_traits<
decltype(alloc)>::destroy(alloc,
string);
19381 std::allocator_traits<
decltype(alloc)>::deallocate(alloc,
string, 1);
19385 case value_t::binary:
19387 AllocatorType<binary_t> alloc;
19388 std::allocator_traits<
decltype(alloc)>::destroy(alloc, binary);
19389 std::allocator_traits<
decltype(alloc)>::deallocate(alloc, binary, 1);
19393 case value_t::null:
19394 case value_t::boolean:
19395 case value_t::number_integer:
19396 case value_t::number_unsigned:
19397 case value_t::number_float:
19398 case value_t::discarded:
19426 void assert_invariant(
bool check_parents =
true)
const noexcept {
19427 JSON_ASSERT(m_data.m_type != value_t::object || m_data.m_value.object !=
nullptr);
19428 JSON_ASSERT(m_data.m_type != value_t::array || m_data.m_value.array !=
nullptr);
19429 JSON_ASSERT(m_data.m_type != value_t::string || m_data.m_value.string !=
nullptr);
19430 JSON_ASSERT(m_data.m_type != value_t::binary || m_data.m_value.binary !=
nullptr);
19432#if JSON_DIAGNOSTICS
19436 JSON_ASSERT(!check_parents || !is_structured() || std::all_of(begin(), end(), [
this](
const basic_json& j) {
19437 return j.m_parent ==
this;
19442 static_cast<void>(check_parents);
19445 void set_parents() {
19446#if JSON_DIAGNOSTICS
19447 switch (m_data.m_type) {
19448 case value_t::array:
19450 for (
auto& element : *m_data.m_value.array) {
19451 element.m_parent =
this;
19456 case value_t::object:
19458 for (
auto& element : *m_data.m_value.object) {
19459 element.second.m_parent =
this;
19464 case value_t::null:
19465 case value_t::string:
19466 case value_t::boolean:
19467 case value_t::number_integer:
19468 case value_t::number_unsigned:
19469 case value_t::number_float:
19470 case value_t::binary:
19471 case value_t::discarded:
19478 iterator set_parents(iterator it,
typename iterator::difference_type count_set_parents) {
19479#if JSON_DIAGNOSTICS
19480 for (
typename iterator::difference_type i = 0; i < count_set_parents; ++i) {
19481 (it + i)->m_parent =
this;
19484 static_cast<void>(count_set_parents);
19489 reference set_parent(reference j, std::size_t old_capacity = detail::unknown_size()) {
19490#if JSON_DIAGNOSTICS
19491 if (old_capacity != detail::unknown_size()) {
19493 JSON_ASSERT(type() == value_t::array);
19494 if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity)) {
19503#ifdef JSON_HEDLEY_MSVC_VERSION
19504#pragma warning(push )
19505#pragma warning(disable : 4127)
19507 if (detail::is_ordered_map<object_t>::value) {
19511#ifdef JSON_HEDLEY_MSVC_VERSION
19512#pragma warning( pop )
19517 static_cast<void>(j);
19518 static_cast<void>(old_capacity);
19530 using parse_event_t = detail::parse_event_t;
19534 using parser_callback_t = detail::parser_callback_t<basic_json>;
19547 basic_json(
const value_t v)
19549 assert_invariant();
19554 basic_json(std::nullptr_t =
nullptr)
noexcept
19555 : basic_json(value_t::null) {
19556 assert_invariant();
19561 template <
typename CompatibleType,
19562 typename U = detail::uncvref_t<CompatibleType>,
19563 detail::enable_if_t <
19565 basic_json(CompatibleType&& val)
noexcept(
noexcept(
19566 JSONSerializer<U>::to_json(std::declval<basic_json_t&>(),
19567 std::forward<CompatibleType>(val)))) {
19568 JSONSerializer<U>::to_json(*
this, std::forward<CompatibleType>(val));
19570 assert_invariant();
19575 template <
typename BasicJsonType,
19576 detail::enable_if_t <
19578 basic_json(
const BasicJsonType& val)
19579#if JSON_DIAGNOSTIC_POSITIONS
19580 : start_position(val.start_pos()),
19581 end_position(val.end_pos())
19584 using other_boolean_t =
typename BasicJsonType::boolean_t;
19585 using other_number_float_t =
typename BasicJsonType::number_float_t;
19586 using other_number_integer_t =
typename BasicJsonType::number_integer_t;
19587 using other_number_unsigned_t =
typename BasicJsonType::number_unsigned_t;
19588 using other_string_t =
typename BasicJsonType::string_t;
19589 using other_object_t =
typename BasicJsonType::object_t;
19590 using other_array_t =
typename BasicJsonType::array_t;
19591 using other_binary_t =
typename BasicJsonType::binary_t;
19593 switch (val.type()) {
19594 case value_t::boolean:
19595 JSONSerializer<other_boolean_t>::to_json(*
this, val.template get<other_boolean_t>());
19597 case value_t::number_float:
19598 JSONSerializer<other_number_float_t>::to_json(*
this, val.template get<other_number_float_t>());
19600 case value_t::number_integer:
19601 JSONSerializer<other_number_integer_t>::to_json(*
this, val.template get<other_number_integer_t>());
19603 case value_t::number_unsigned:
19604 JSONSerializer<other_number_unsigned_t>::to_json(*
this, val.template get<other_number_unsigned_t>());
19606 case value_t::string:
19607 JSONSerializer<other_string_t>::to_json(*
this, val.template get_ref<const other_string_t&>());
19609 case value_t::object:
19610 JSONSerializer<other_object_t>::to_json(*
this, val.template get_ref<const other_object_t&>());
19612 case value_t::array:
19613 JSONSerializer<other_array_t>::to_json(*
this, val.template get_ref<const other_array_t&>());
19615 case value_t::binary:
19616 JSONSerializer<other_binary_t>::to_json(*
this, val.template get_ref<const other_binary_t&>());
19618 case value_t::null:
19621 case value_t::discarded:
19622 m_data.m_type = value_t::discarded;
19625 JSON_ASSERT(
false);
19627 JSON_ASSERT(m_data.m_type == val.type());
19630 assert_invariant();
19635 basic_json(initializer_list_t init,
19636 bool type_deduction =
true,
19637 value_t manual_type = value_t::array) {
19640 bool is_an_object = std::all_of(init.begin(), init.end(),
19645 return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[static_cast<size_type>(0)].is_string();
19649 if (!type_deduction) {
19651 if (manual_type == value_t::array) {
19652 is_an_object =
false;
19656 if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object)) {
19657 JSON_THROW(type_error::create(301,
"cannot create object from initializer list",
nullptr));
19661 if (is_an_object) {
19663 m_data.m_type = value_t::object;
19664 m_data.m_value = value_t::object;
19666 for (
auto& element_ref : init) {
19667 auto element = element_ref.moved_or_copied();
19668 m_data.m_value.object->emplace(
19669 std::move(*((*element.m_data.m_value.array)[0].m_data.m_value.string)),
19670 std::move((*element.m_data.m_value.array)[1]));
19675 m_data.m_type = value_t::array;
19676 m_data.m_value.array = create<array_t>(init.begin(), init.end());
19680 assert_invariant();
19685 JSON_HEDLEY_WARN_UNUSED_RESULT
19686 static basic_json binary(
const typename binary_t::container_type& init) {
19687 auto res = basic_json();
19688 res.m_data.m_type = value_t::binary;
19689 res.m_data.m_value = init;
19695 JSON_HEDLEY_WARN_UNUSED_RESULT
19696 static basic_json binary(
const typename binary_t::container_type& init,
typename binary_t::subtype_type subtype) {
19697 auto res = basic_json();
19698 res.m_data.m_type = value_t::binary;
19699 res.m_data.m_value = binary_t(init, subtype);
19705 JSON_HEDLEY_WARN_UNUSED_RESULT
19706 static basic_json binary(
typename binary_t::container_type&& init) {
19707 auto res = basic_json();
19708 res.m_data.m_type = value_t::binary;
19709 res.m_data.m_value = std::move(init);
19715 JSON_HEDLEY_WARN_UNUSED_RESULT
19716 static basic_json binary(
typename binary_t::container_type&& init,
typename binary_t::subtype_type subtype) {
19717 auto res = basic_json();
19718 res.m_data.m_type = value_t::binary;
19719 res.m_data.m_value = binary_t(std::move(init), subtype);
19725 JSON_HEDLEY_WARN_UNUSED_RESULT
19726 static basic_json array(initializer_list_t init = {}) {
19727 return basic_json(init,
false, value_t::array);
19732 JSON_HEDLEY_WARN_UNUSED_RESULT
19733 static basic_json object(initializer_list_t init = {}) {
19734 return basic_json(init,
false, value_t::object);
19739 basic_json(size_type cnt,
const basic_json& val) :
19740 m_data{ cnt, val } {
19742 assert_invariant();
19747 template <
class InputIT,
typename std::enable_if <
19748 std::is_same<InputIT, typename basic_json_t::iterator>::value ||
19749 std::is_same<InputIT, typename basic_json_t::const_iterator>::value,
int >::type = 0 >
19750 basic_json(InputIT first, InputIT last)
19752 JSON_ASSERT(first.m_object !=
nullptr);
19753 JSON_ASSERT(last.m_object !=
nullptr);
19756 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) {
19757 JSON_THROW(invalid_iterator::create(201,
"iterators are not compatible",
nullptr));
19761 m_data.m_type = first.m_object->m_data.m_type;
19764 switch (m_data.m_type) {
19765 case value_t::boolean:
19766 case value_t::number_float:
19767 case value_t::number_integer:
19768 case value_t::number_unsigned:
19769 case value_t::string:
19771 if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin()
19772 || !last.m_it.primitive_iterator.is_end())) {
19773 JSON_THROW(invalid_iterator::create(204,
"iterators out of range", first.m_object));
19778 case value_t::null:
19779 case value_t::object:
19780 case value_t::array:
19781 case value_t::binary:
19782 case value_t::discarded:
19787 switch (m_data.m_type) {
19788 case value_t::number_integer:
19790 m_data.m_value.number_integer = first.m_object->m_data.m_value.number_integer;
19794 case value_t::number_unsigned:
19796 m_data.m_value.number_unsigned = first.m_object->m_data.m_value.number_unsigned;
19800 case value_t::number_float:
19802 m_data.m_value.number_float = first.m_object->m_data.m_value.number_float;
19806 case value_t::boolean:
19808 m_data.m_value.boolean = first.m_object->m_data.m_value.boolean;
19812 case value_t::string:
19814 m_data.m_value = *first.m_object->m_data.m_value.string;
19818 case value_t::object:
19820 m_data.m_value.object = create<object_t>(first.m_it.object_iterator,
19821 last.m_it.object_iterator);
19825 case value_t::array:
19827 m_data.m_value.array = create<array_t>(first.m_it.array_iterator,
19828 last.m_it.array_iterator);
19832 case value_t::binary:
19834 m_data.m_value = *first.m_object->m_data.m_value.binary;
19838 case value_t::null:
19839 case value_t::discarded:
19841 JSON_THROW(invalid_iterator::create(206, detail::concat(
"cannot construct with iterators from ", first.m_object->type_name()), first.m_object));
19845 assert_invariant();
19852 template<
typename JsonRef,
19853 detail::enable_if_t<detail::conjunction<detail::is_json_ref<JsonRef>,
19854 std::is_same<typename JsonRef::value_type, basic_json>>::value,
int> = 0 >
19855 basic_json(
const JsonRef& ref) : basic_json(ref.moved_or_copied()) {}
19859 basic_json(
const basic_json& other)
19860 : json_base_class_t(other)
19861#if JSON_DIAGNOSTIC_POSITIONS
19862 , start_position(other.start_position)
19863 , end_position(other.end_position)
19866 m_data.m_type = other.m_data.m_type;
19868 other.assert_invariant();
19870 switch (m_data.m_type) {
19871 case value_t::object:
19873 m_data.m_value = *other.m_data.m_value.object;
19877 case value_t::array:
19879 m_data.m_value = *other.m_data.m_value.array;
19883 case value_t::string:
19885 m_data.m_value = *other.m_data.m_value.string;
19889 case value_t::boolean:
19891 m_data.m_value = other.m_data.m_value.boolean;
19895 case value_t::number_integer:
19897 m_data.m_value = other.m_data.m_value.number_integer;
19901 case value_t::number_unsigned:
19903 m_data.m_value = other.m_data.m_value.number_unsigned;
19907 case value_t::number_float:
19909 m_data.m_value = other.m_data.m_value.number_float;
19913 case value_t::binary:
19915 m_data.m_value = *other.m_data.m_value.binary;
19919 case value_t::null:
19920 case value_t::discarded:
19926 assert_invariant();
19931 basic_json(basic_json&& other) noexcept
19932 : json_base_class_t(std::forward<json_base_class_t>(other)),
19933 m_data(std::move(other.m_data))
19934#if JSON_DIAGNOSTIC_POSITIONS
19935 , start_position(other.start_position)
19936 , end_position(other.end_position)
19940 other.assert_invariant(
false);
19943 other.m_data.m_type = value_t::null;
19944 other.m_data.m_value = {};
19946#if JSON_DIAGNOSTIC_POSITIONS
19947 other.start_position = std::string::npos;
19948 other.end_position = std::string::npos;
19952 assert_invariant();
19957 basic_json& operator=(basic_json other)
noexcept (
19958 std::is_nothrow_move_constructible<value_t>::value&&
19959 std::is_nothrow_move_assignable<value_t>::value&&
19960 std::is_nothrow_move_constructible<json_value>::value&&
19961 std::is_nothrow_move_assignable<json_value>::value&&
19962 std::is_nothrow_move_assignable<json_base_class_t>::value
19965 other.assert_invariant();
19968 swap(m_data.m_type, other.m_data.m_type);
19969 swap(m_data.m_value, other.m_data.m_value);
19971#if JSON_DIAGNOSTIC_POSITIONS
19972 swap(start_position, other.start_position);
19973 swap(end_position, other.end_position);
19976 json_base_class_t::operator=(std::move(other));
19979 assert_invariant();
19985 ~basic_json()
noexcept {
19986 assert_invariant(
false);
20002 string_t dump(
const int indent = -1,
20003 const char indent_char =
' ',
20004 const bool ensure_ascii =
false,
20005 const error_handler_t error_handler = error_handler_t::strict)
const {
20010 s.dump(*
this,
true, ensure_ascii,
static_cast<unsigned int>(indent));
20013 s.dump(*
this,
false, ensure_ascii, 0);
20021 constexpr value_t type()
const noexcept {
20022 return m_data.m_type;
20027 constexpr bool is_primitive()
const noexcept {
20028 return is_null() || is_string() || is_boolean() || is_number() || is_binary();
20033 constexpr bool is_structured()
const noexcept {
20034 return is_array() || is_object();
20039 constexpr bool is_null()
const noexcept {
20040 return m_data.m_type == value_t::null;
20045 constexpr bool is_boolean()
const noexcept {
20046 return m_data.m_type == value_t::boolean;
20051 constexpr bool is_number()
const noexcept {
20052 return is_number_integer() || is_number_float();
20057 constexpr bool is_number_integer()
const noexcept {
20058 return m_data.m_type == value_t::number_integer || m_data.m_type == value_t::number_unsigned;
20063 constexpr bool is_number_unsigned()
const noexcept {
20064 return m_data.m_type == value_t::number_unsigned;
20069 constexpr bool is_number_float()
const noexcept {
20070 return m_data.m_type == value_t::number_float;
20075 constexpr bool is_object()
const noexcept {
20076 return m_data.m_type == value_t::object;
20081 constexpr bool is_array()
const noexcept {
20082 return m_data.m_type == value_t::array;
20087 constexpr bool is_string()
const noexcept {
20088 return m_data.m_type == value_t::string;
20093 constexpr bool is_binary()
const noexcept {
20094 return m_data.m_type == value_t::binary;
20099 constexpr bool is_discarded()
const noexcept {
20100 return m_data.m_type == value_t::discarded;
20105 constexpr operator value_t()
const noexcept {
20106 return m_data.m_type;
20117 boolean_t get_impl(boolean_t* )
const {
20118 if (JSON_HEDLEY_LIKELY(is_boolean())) {
20119 return m_data.m_value.boolean;
20122 JSON_THROW(type_error::create(302, detail::concat(
"type must be boolean, but is ", type_name()),
this));
20126 object_t* get_impl_ptr(object_t* )
noexcept {
20127 return is_object() ? m_data.m_value.object :
nullptr;
20131 constexpr const object_t* get_impl_ptr(
const object_t* )
const noexcept {
20132 return is_object() ? m_data.m_value.object :
nullptr;
20136 array_t* get_impl_ptr(array_t* )
noexcept {
20137 return is_array() ? m_data.m_value.array :
nullptr;
20141 constexpr const array_t* get_impl_ptr(
const array_t* )
const noexcept {
20142 return is_array() ? m_data.m_value.array :
nullptr;
20146 string_t* get_impl_ptr(string_t* )
noexcept {
20147 return is_string() ? m_data.m_value.string :
nullptr;
20151 constexpr const string_t* get_impl_ptr(
const string_t* )
const noexcept {
20152 return is_string() ? m_data.m_value.string :
nullptr;
20156 boolean_t* get_impl_ptr(boolean_t* )
noexcept {
20157 return is_boolean() ? &m_data.m_value.boolean :
nullptr;
20161 constexpr const boolean_t* get_impl_ptr(
const boolean_t* )
const noexcept {
20162 return is_boolean() ? &m_data.m_value.boolean :
nullptr;
20166 number_integer_t* get_impl_ptr(number_integer_t* )
noexcept {
20167 return m_data.m_type == value_t::number_integer ? &m_data.m_value.number_integer :
nullptr;
20171 constexpr const number_integer_t* get_impl_ptr(
const number_integer_t* )
const noexcept {
20172 return m_data.m_type == value_t::number_integer ? &m_data.m_value.number_integer :
nullptr;
20176 number_unsigned_t* get_impl_ptr(number_unsigned_t* )
noexcept {
20177 return is_number_unsigned() ? &m_data.m_value.number_unsigned :
nullptr;
20181 constexpr const number_unsigned_t* get_impl_ptr(
const number_unsigned_t* )
const noexcept {
20182 return is_number_unsigned() ? &m_data.m_value.number_unsigned :
nullptr;
20186 number_float_t* get_impl_ptr(number_float_t* )
noexcept {
20187 return is_number_float() ? &m_data.m_value.number_float :
nullptr;
20191 constexpr const number_float_t* get_impl_ptr(
const number_float_t* )
const noexcept {
20192 return is_number_float() ? &m_data.m_value.number_float :
nullptr;
20196 binary_t* get_impl_ptr(binary_t* )
noexcept {
20197 return is_binary() ? m_data.m_value.binary :
nullptr;
20201 constexpr const binary_t* get_impl_ptr(
const binary_t* )
const noexcept {
20202 return is_binary() ? m_data.m_value.binary :
nullptr;
20216 template<
typename ReferenceType,
typename ThisType>
20217 static ReferenceType get_ref_impl(ThisType& obj) {
20219 auto* ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>();
20221 if (JSON_HEDLEY_LIKELY(ptr !=
nullptr)) {
20225 JSON_THROW(type_error::create(303, detail::concat(
"incompatible ReferenceType for get_ref, actual type is ", obj.type_name()), &obj));
20235 template<
typename PointerType,
typename std::enable_if<
20236 std::is_pointer<PointerType>::value,
int>::type = 0>
20237 auto get_ptr()
noexcept ->
decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>())) {
20239 return get_impl_ptr(
static_cast<PointerType
>(
nullptr));
20244 template <
typename PointerType,
typename std::enable_if <
20245 std::is_pointer<PointerType>::value&&
20246 std::is_const<typename std::remove_pointer<PointerType>::type>::value,
int >::type = 0 >
20247 constexpr auto get_ptr()
const noexcept ->
decltype(std::declval<const basic_json_t&>().get_impl_ptr(std::declval<PointerType>())) {
20249 return get_impl_ptr(
static_cast<PointerType
>(
nullptr));
20291 template <
typename ValueType,
20292 detail::enable_if_t <
20297 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>()))) {
20298 auto ret = ValueType();
20299 JSONSerializer<ValueType>::from_json(*
this, ret);
20333 template <
typename ValueType,
20334 detail::enable_if_t <
20338 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>()))) {
20339 return JSONSerializer<ValueType>::from_json(*
this);
20357 template <
typename BasicJsonType,
20358 detail::enable_if_t <
20379 template<
typename BasicJsonType,
20380 detail::enable_if_t<
20381 std::is_same<BasicJsonType, basic_json_t>::value,
20391 template<
typename PointerType,
20392 detail::enable_if_t<
20393 std::is_pointer<PointerType>::value,
20396 ->
decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>()) {
20398 return get_ptr<PointerType>();
20425 template <
typename ValueTypeCV,
typename ValueType = detail::uncvref_t<ValueTypeCV>>
20426#if defined(JSON_HAS_CPP_14)
20429 auto get()
const noexcept(
20435 static_assert(!std::is_reference<ValueTypeCV>::value,
20436 "get() cannot be used with reference types, you might want to use get_ref()");
20467 template<
typename PointerType,
typename std::enable_if<
20468 std::is_pointer<PointerType>::value,
int>::type = 0>
20469 auto get()
noexcept ->
decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>()) {
20471 return get_ptr<PointerType>();
20476 template <
typename ValueType,
20477 detail::enable_if_t <
20481 ValueType& get_to(ValueType& v)
const noexcept(
noexcept(
20482 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v))) {
20483 JSONSerializer<ValueType>::from_json(*
this, v);
20489 template<
typename ValueType,
20490 detail::enable_if_t <
20493 ValueType& get_to(ValueType& v)
const {
20499 typename T, std::size_t N,
20500 typename Array = T(&)[N],
20501 detail::enable_if_t <
20503 Array get_to(T(&v)[N])
const
20504 noexcept(
noexcept(JSONSerializer<Array>::from_json(
20505 std::declval<const basic_json_t&>(), v))) {
20506 JSONSerializer<Array>::from_json(*
this, v);
20512 template<
typename ReferenceType,
typename std::enable_if<
20513 std::is_reference<ReferenceType>::value,
int>::type = 0>
20514 ReferenceType get_ref() {
20516 return get_ref_impl<ReferenceType>(*
this);
20521 template <
typename ReferenceType,
typename std::enable_if <
20522 std::is_reference<ReferenceType>::value&&
20523 std::is_const<typename std::remove_reference<ReferenceType>::type>::value,
int >::type = 0 >
20524 ReferenceType get_ref()
const {
20526 return get_ref_impl<ReferenceType>(*
this);
20558 template <
typename ValueType,
typename std::enable_if <
20566#if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914))
20569#if defined(JSON_HAS_CPP_17) && JSON_HAS_STATIC_RTTI
20573 >::value,
int >::type = 0 >
20574 JSON_EXPLICIT
operator ValueType()
const {
20576 return get<ValueType>();
20581 binary_t& get_binary() {
20582 if (!is_binary()) {
20583 JSON_THROW(type_error::create(302, detail::concat(
"type must be binary, but is ", type_name()),
this));
20586 return *get_ptr<binary_t*>();
20591 const binary_t& get_binary()
const {
20592 if (!is_binary()) {
20593 JSON_THROW(type_error::create(302, detail::concat(
"type must be binary, but is ", type_name()),
this));
20596 return *get_ptr<const binary_t*>();
20611 reference at(size_type idx) {
20613 if (JSON_HEDLEY_LIKELY(is_array())) {
20616 return set_parent(m_data.m_value.array->at(idx));
20618 JSON_CATCH(std::out_of_range&) {
20620 JSON_THROW(out_of_range::create(401, detail::concat(
"array index ", std::to_string(idx),
" is out of range"),
this));
20624 JSON_THROW(type_error::create(304, detail::concat(
"cannot use at() with ", type_name()),
this));
20630 const_reference at(size_type idx)
const {
20632 if (JSON_HEDLEY_LIKELY(is_array())) {
20635 return m_data.m_value.array->at(idx);
20637 JSON_CATCH(std::out_of_range&) {
20639 JSON_THROW(out_of_range::create(401, detail::concat(
"array index ", std::to_string(idx),
" is out of range"),
this));
20643 JSON_THROW(type_error::create(304, detail::concat(
"cannot use at() with ", type_name()),
this));
20649 reference at(
const typename object_t::key_type& key) {
20651 if (JSON_HEDLEY_UNLIKELY(!is_object())) {
20652 JSON_THROW(type_error::create(304, detail::concat(
"cannot use at() with ", type_name()),
this));
20655 auto it = m_data.m_value.object->find(key);
20656 if (it == m_data.m_value.object->end()) {
20657 JSON_THROW(out_of_range::create(403, detail::concat(
"key '", key,
"' not found"),
this));
20659 return set_parent(it->second);
20664 template<
class KeyType, detail::enable_if_t<
20665 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value,
int> = 0>
20666 reference at(KeyType&& key) {
20668 if (JSON_HEDLEY_UNLIKELY(!is_object())) {
20669 JSON_THROW(type_error::create(304, detail::concat(
"cannot use at() with ", type_name()),
this));
20672 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
20673 if (it == m_data.m_value.object->end()) {
20674 JSON_THROW(out_of_range::create(403, detail::concat(
"key '", string_t(std::forward<KeyType>(key)),
"' not found"),
this));
20676 return set_parent(it->second);
20681 const_reference at(
const typename object_t::key_type& key)
const {
20683 if (JSON_HEDLEY_UNLIKELY(!is_object())) {
20684 JSON_THROW(type_error::create(304, detail::concat(
"cannot use at() with ", type_name()),
this));
20687 auto it = m_data.m_value.object->find(key);
20688 if (it == m_data.m_value.object->end()) {
20689 JSON_THROW(out_of_range::create(403, detail::concat(
"key '", key,
"' not found"),
this));
20696 template<
class KeyType, detail::enable_if_t<
20697 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value,
int> = 0>
20698 const_reference at(KeyType&& key)
const {
20700 if (JSON_HEDLEY_UNLIKELY(!is_object())) {
20701 JSON_THROW(type_error::create(304, detail::concat(
"cannot use at() with ", type_name()),
this));
20704 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
20705 if (it == m_data.m_value.object->end()) {
20706 JSON_THROW(out_of_range::create(403, detail::concat(
"key '", string_t(std::forward<KeyType>(key)),
"' not found"),
this));
20713 reference operator[](size_type idx) {
20716 m_data.m_type = value_t::array;
20717 m_data.m_value.array = create<array_t>();
20718 assert_invariant();
20722 if (JSON_HEDLEY_LIKELY(is_array())) {
20724 if (idx >= m_data.m_value.array->size()) {
20725#if JSON_DIAGNOSTICS
20727 const auto old_size = m_data.m_value.array->size();
20728 const auto old_capacity = m_data.m_value.array->capacity();
20730 m_data.m_value.array->resize(idx + 1);
20732#if JSON_DIAGNOSTICS
20733 if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity)) {
20739 set_parents(begin() +
static_cast<typename iterator::difference_type
>(old_size),
static_cast<typename iterator::difference_type
>(idx + 1 - old_size));
20742 assert_invariant();
20745 return m_data.m_value.array->operator[](idx);
20748 JSON_THROW(type_error::create(305, detail::concat(
"cannot use operator[] with a numeric argument with ", type_name()),
this));
20753 const_reference operator[](size_type idx)
const {
20755 if (JSON_HEDLEY_LIKELY(is_array())) {
20756 return m_data.m_value.array->operator[](idx);
20759 JSON_THROW(type_error::create(305, detail::concat(
"cannot use operator[] with a numeric argument with ", type_name()),
this));
20764 reference operator[](
typename object_t::key_type key)
20768 m_data.m_type = value_t::object;
20769 m_data.m_value.object = create<object_t>();
20770 assert_invariant();
20774 if (JSON_HEDLEY_LIKELY(is_object())) {
20775 auto result = m_data.m_value.object->emplace(std::move(key),
nullptr);
20776 return set_parent(result.first->second);
20779 JSON_THROW(type_error::create(305, detail::concat(
"cannot use operator[] with a string argument with ", type_name()),
this));
20784 const_reference operator[](
const typename object_t::key_type& key)
const {
20786 if (JSON_HEDLEY_LIKELY(is_object())) {
20787 auto it = m_data.m_value.object->find(key);
20788 JSON_ASSERT(it != m_data.m_value.object->end());
20792 JSON_THROW(type_error::create(305, detail::concat(
"cannot use operator[] with a string argument with ", type_name()),
this));
20797 template<
typename T>
20798 reference operator[](T* key) {
20799 return operator[](
typename object_t::key_type(key));
20802 template<
typename T>
20803 const_reference operator[](T* key)
const {
20804 return operator[](
typename object_t::key_type(key));
20809 template<
class KeyType, detail::enable_if_t<
20810 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value,
int > = 0 >
20811 reference operator[](KeyType&& key) {
20814 m_data.m_type = value_t::object;
20815 m_data.m_value.object = create<object_t>();
20816 assert_invariant();
20820 if (JSON_HEDLEY_LIKELY(is_object())) {
20821 auto result = m_data.m_value.object->emplace(std::forward<KeyType>(key),
nullptr);
20822 return set_parent(result.first->second);
20825 JSON_THROW(type_error::create(305, detail::concat(
"cannot use operator[] with a string argument with ", type_name()),
this));
20830 template<
class KeyType, detail::enable_if_t<
20831 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value,
int > = 0 >
20832 const_reference operator[](KeyType&& key)
const {
20834 if (JSON_HEDLEY_LIKELY(is_object())) {
20835 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
20836 JSON_ASSERT(it != m_data.m_value.object->end());
20840 JSON_THROW(type_error::create(305, detail::concat(
"cannot use operator[] with a string argument with ", type_name()),
this));
20844 template<
typename KeyType>
20846 object_comparator_t,
const typename object_t::key_type&, KeyType >;
20848 template<
typename ValueType>
20849 using value_return_type = std::conditional <
20850 detail::is_c_string_uncvref<ValueType>::value,
20851 string_t,
typename std::decay<ValueType>::type >;
20856 template <
class ValueType, detail::enable_if_t <
20858 && detail::is_getable<basic_json_t, ValueType>::value
20859 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value,
int > = 0 >
20860 ValueType value(
const typename object_t::key_type& key,
const ValueType& default_value)
const {
20862 if (JSON_HEDLEY_LIKELY(is_object())) {
20864 const auto it = find(key);
20866 return it->template get<ValueType>();
20869 return default_value;
20872 JSON_THROW(type_error::create(306, detail::concat(
"cannot use value() with ", type_name()),
this));
20877 template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
20878 detail::enable_if_t <
20880 && detail::is_getable<basic_json_t, ReturnType>::value
20881 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value,
int > = 0 >
20882 ReturnType value(
const typename object_t::key_type& key, ValueType&& default_value)
const {
20884 if (JSON_HEDLEY_LIKELY(is_object())) {
20886 const auto it = find(key);
20888 return it->template get<ReturnType>();
20891 return std::forward<ValueType>(default_value);
20894 JSON_THROW(type_error::create(306, detail::concat(
"cannot use value() with ", type_name()),
this));
20899 template <
class ValueType,
class KeyType, detail::enable_if_t <
20901 && !detail::is_json_pointer<KeyType>::value
20902 && is_comparable_with_object_key<KeyType>::value
20903 && detail::is_getable<basic_json_t, ValueType>::value
20904 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value,
int > = 0 >
20905 ValueType value(KeyType&& key,
const ValueType& default_value)
const {
20907 if (JSON_HEDLEY_LIKELY(is_object())) {
20909 const auto it = find(std::forward<KeyType>(key));
20911 return it->template get<ValueType>();
20914 return default_value;
20917 JSON_THROW(type_error::create(306, detail::concat(
"cannot use value() with ", type_name()),
this));
20922 template < class ValueType, class KeyType, class ReturnType = typename value_return_type<ValueType>::type,
20923 detail::enable_if_t <
20925 && !detail::is_json_pointer<KeyType>::value
20926 && is_comparable_with_object_key<KeyType>::value
20927 && detail::is_getable<basic_json_t, ReturnType>::value
20928 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value,
int > = 0 >
20929 ReturnType value(KeyType&& key, ValueType&& default_value)
const {
20931 if (JSON_HEDLEY_LIKELY(is_object())) {
20933 const auto it = find(std::forward<KeyType>(key));
20935 return it->template get<ReturnType>();
20938 return std::forward<ValueType>(default_value);
20941 JSON_THROW(type_error::create(306, detail::concat(
"cannot use value() with ", type_name()),
this));
20946 template <
class ValueType, detail::enable_if_t <
20947 detail::is_getable<basic_json_t, ValueType>::value
20948 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value,
int > = 0 >
20949 ValueType value(
const json_pointer& ptr,
const ValueType& default_value)
const {
20951 if (JSON_HEDLEY_LIKELY(is_object())) {
20956 return ptr.get_checked(
this).template get<ValueType>();
20958 JSON_INTERNAL_CATCH(out_of_range&) {
20959 return default_value;
20963 JSON_THROW(type_error::create(306, detail::concat(
"cannot use value() with ", type_name()),
this));
20968 template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
20969 detail::enable_if_t <
20970 detail::is_getable<basic_json_t, ReturnType>::value
20971 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value,
int > = 0 >
20972 ReturnType value(
const json_pointer& ptr, ValueType&& default_value)
const {
20974 if (JSON_HEDLEY_LIKELY(is_object())) {
20979 return ptr.get_checked(
this).template get<ReturnType>();
20981 JSON_INTERNAL_CATCH(out_of_range&) {
20982 return std::forward<ValueType>(default_value);
20986 JSON_THROW(type_error::create(306, detail::concat(
"cannot use value() with ", type_name()),
this));
20989 template <
class ValueType,
class BasicJsonType, detail::enable_if_t <
20991 && detail::is_getable<basic_json_t, ValueType>::value
20992 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value,
int > = 0 >
20993 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>)
20994 ValueType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr,
const ValueType& default_value)
const {
20995 return value(ptr.convert(), default_value);
20998 template < class ValueType, class BasicJsonType, class ReturnType = typename value_return_type<ValueType>::type,
20999 detail::enable_if_t <
21001 && detail::is_getable<basic_json_t, ReturnType>::value
21002 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value,
int > = 0 >
21003 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>)
21004 ReturnType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, ValueType&& default_value)
const {
21005 return value(ptr.convert(), std::forward<ValueType>(default_value));
21010 reference front() {
21016 const_reference front()
const {
21030 const_reference back()
const {
21038 template <
class IteratorType, detail::enable_if_t <
21039 std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
21040 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value,
int > = 0 >
21041 IteratorType erase(IteratorType pos)
21044 if (JSON_HEDLEY_UNLIKELY(
this != pos.m_object)) {
21045 JSON_THROW(invalid_iterator::create(202,
"iterator does not fit current value",
this));
21048 IteratorType result = end();
21050 switch (m_data.m_type) {
21051 case value_t::boolean:
21052 case value_t::number_float:
21053 case value_t::number_integer:
21054 case value_t::number_unsigned:
21055 case value_t::string:
21056 case value_t::binary:
21058 if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin())) {
21059 JSON_THROW(invalid_iterator::create(205,
"iterator out of range",
this));
21063 AllocatorType<string_t> alloc;
21064 std::allocator_traits<
decltype(alloc)>::destroy(alloc, m_data.m_value.string);
21065 std::allocator_traits<
decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1);
21066 m_data.m_value.string =
nullptr;
21068 else if (is_binary()) {
21069 AllocatorType<binary_t> alloc;
21070 std::allocator_traits<
decltype(alloc)>::destroy(alloc, m_data.m_value.binary);
21071 std::allocator_traits<
decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1);
21072 m_data.m_value.binary =
nullptr;
21075 m_data.m_type = value_t::null;
21076 assert_invariant();
21080 case value_t::object:
21082 result.m_it.object_iterator = m_data.m_value.object->erase(pos.m_it.object_iterator);
21086 case value_t::array:
21088 result.m_it.array_iterator = m_data.m_value.array->erase(pos.m_it.array_iterator);
21092 case value_t::null:
21093 case value_t::discarded:
21095 JSON_THROW(type_error::create(307, detail::concat(
"cannot use erase() with ", type_name()),
this));
21103 template <
class IteratorType, detail::enable_if_t <
21104 std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
21105 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value,
int > = 0 >
21106 IteratorType erase(IteratorType first, IteratorType last)
21109 if (JSON_HEDLEY_UNLIKELY(
this != first.m_object ||
this != last.m_object)) {
21110 JSON_THROW(invalid_iterator::create(203,
"iterators do not fit current value",
this));
21113 IteratorType result = end();
21115 switch (m_data.m_type) {
21116 case value_t::boolean:
21117 case value_t::number_float:
21118 case value_t::number_integer:
21119 case value_t::number_unsigned:
21120 case value_t::string:
21121 case value_t::binary:
21123 if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin()
21124 || !last.m_it.primitive_iterator.is_end())) {
21125 JSON_THROW(invalid_iterator::create(204,
"iterators out of range",
this));
21129 AllocatorType<string_t> alloc;
21130 std::allocator_traits<
decltype(alloc)>::destroy(alloc, m_data.m_value.string);
21131 std::allocator_traits<
decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1);
21132 m_data.m_value.string =
nullptr;
21134 else if (is_binary()) {
21135 AllocatorType<binary_t> alloc;
21136 std::allocator_traits<
decltype(alloc)>::destroy(alloc, m_data.m_value.binary);
21137 std::allocator_traits<
decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1);
21138 m_data.m_value.binary =
nullptr;
21141 m_data.m_type = value_t::null;
21142 assert_invariant();
21146 case value_t::object:
21148 result.m_it.object_iterator = m_data.m_value.object->erase(first.m_it.object_iterator,
21149 last.m_it.object_iterator);
21153 case value_t::array:
21155 result.m_it.array_iterator = m_data.m_value.array->erase(first.m_it.array_iterator,
21156 last.m_it.array_iterator);
21160 case value_t::null:
21161 case value_t::discarded:
21163 JSON_THROW(type_error::create(307, detail::concat(
"cannot use erase() with ", type_name()),
this));
21170 template <
typename KeyType, detail::enable_if_t <
21171 detail::has_erase_with_key_type<basic_json_t, KeyType>::value,
int > = 0 >
21172 size_type erase_internal(KeyType&& key) {
21174 if (JSON_HEDLEY_UNLIKELY(!is_object())) {
21175 JSON_THROW(type_error::create(307, detail::concat(
"cannot use erase() with ", type_name()),
this));
21178 return m_data.m_value.object->erase(std::forward<KeyType>(key));
21181 template <
typename KeyType, detail::enable_if_t <
21182 !detail::has_erase_with_key_type<basic_json_t, KeyType>::value,
int > = 0 >
21183 size_type erase_internal(KeyType&& key) {
21185 if (JSON_HEDLEY_UNLIKELY(!is_object())) {
21186 JSON_THROW(type_error::create(307, detail::concat(
"cannot use erase() with ", type_name()),
this));
21189 const auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
21190 if (it != m_data.m_value.object->end()) {
21191 m_data.m_value.object->erase(it);
21201 size_type erase(
const typename object_t::key_type& key) {
21204 return erase_internal(key);
21209 template<
class KeyType, detail::enable_if_t<
21210 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value,
int> = 0>
21211 size_type erase(KeyType&& key) {
21212 return erase_internal(std::forward<KeyType>(key));
21217 void erase(
const size_type idx) {
21219 if (JSON_HEDLEY_LIKELY(is_array())) {
21220 if (JSON_HEDLEY_UNLIKELY(idx >= size())) {
21221 JSON_THROW(out_of_range::create(401, detail::concat(
"array index ", std::to_string(idx),
" is out of range"),
this));
21224 m_data.m_value.array->erase(m_data.m_value.array->begin() +
static_cast<difference_type
>(idx));
21227 JSON_THROW(type_error::create(307, detail::concat(
"cannot use erase() with ", type_name()),
this));
21242 iterator find(
const typename object_t::key_type& key) {
21243 auto result = end();
21246 result.m_it.object_iterator = m_data.m_value.object->find(key);
21254 const_iterator find(
const typename object_t::key_type& key)
const {
21255 auto result = cend();
21258 result.m_it.object_iterator = m_data.m_value.object->find(key);
21266 template<
class KeyType, detail::enable_if_t<
21267 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value,
int> = 0>
21268 iterator find(KeyType&& key) {
21269 auto result = end();
21272 result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key));
21280 template<
class KeyType, detail::enable_if_t<
21281 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value,
int> = 0>
21282 const_iterator find(KeyType&& key)
const {
21283 auto result = cend();
21286 result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key));
21294 size_type count(
const typename object_t::key_type& key)
const {
21296 return is_object() ? m_data.m_value.object->count(key) : 0;
21301 template<
class KeyType, detail::enable_if_t<
21302 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value,
int> = 0>
21303 size_type count(KeyType&& key)
const {
21305 return is_object() ? m_data.m_value.object->count(std::forward<KeyType>(key)) : 0;
21310 bool contains(
const typename object_t::key_type& key)
const {
21311 return is_object() && m_data.m_value.object->find(key) != m_data.m_value.object->end();
21316 template<
class KeyType, detail::enable_if_t<
21317 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value,
int> = 0>
21318 bool contains(KeyType&& key)
const {
21319 return is_object() && m_data.m_value.object->find(std::forward<KeyType>(key)) != m_data.m_value.object->end();
21324 bool contains(
const json_pointer& ptr)
const {
21325 return ptr.contains(
this);
21328 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value,
int> = 0>
21329 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>)
21330 bool contains(
const typename ::nlohmann::json_pointer<BasicJsonType>& ptr)
const {
21331 return ptr.contains(
this);
21345 iterator begin()
noexcept {
21346 iterator result(
this);
21347 result.set_begin();
21353 const_iterator begin()
const noexcept {
21359 const_iterator cbegin()
const noexcept {
21360 const_iterator result(
this);
21361 result.set_begin();
21367 iterator end()
noexcept {
21368 iterator result(
this);
21375 const_iterator end()
const noexcept {
21381 const_iterator cend()
const noexcept {
21382 const_iterator result(
this);
21389 reverse_iterator rbegin()
noexcept {
21390 return reverse_iterator(end());
21395 const_reverse_iterator rbegin()
const noexcept {
21401 reverse_iterator rend()
noexcept {
21402 return reverse_iterator(begin());
21407 const_reverse_iterator rend()
const noexcept {
21413 const_reverse_iterator crbegin()
const noexcept {
21414 return const_reverse_iterator(cend());
21419 const_reverse_iterator crend()
const noexcept {
21420 return const_reverse_iterator(cbegin());
21429 JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
21430 static iteration_proxy<iterator> iterator_wrapper(reference ref)
noexcept {
21431 return ref.items();
21439 JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
21440 static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref)
noexcept {
21441 return ref.items();
21446 iteration_proxy<iterator> items()
noexcept {
21447 return iteration_proxy<iterator>(*
this);
21452 iteration_proxy<const_iterator> items()
const noexcept {
21453 return iteration_proxy<const_iterator>(*
this);
21467 bool empty()
const noexcept {
21468 switch (m_data.m_type) {
21469 case value_t::null:
21475 case value_t::array:
21478 return m_data.m_value.array->empty();
21481 case value_t::object:
21484 return m_data.m_value.object->empty();
21487 case value_t::string:
21488 case value_t::boolean:
21489 case value_t::number_integer:
21490 case value_t::number_unsigned:
21491 case value_t::number_float:
21492 case value_t::binary:
21493 case value_t::discarded:
21504 size_type size()
const noexcept {
21505 switch (m_data.m_type) {
21506 case value_t::null:
21512 case value_t::array:
21515 return m_data.m_value.array->size();
21518 case value_t::object:
21521 return m_data.m_value.object->size();
21524 case value_t::string:
21525 case value_t::boolean:
21526 case value_t::number_integer:
21527 case value_t::number_unsigned:
21528 case value_t::number_float:
21529 case value_t::binary:
21530 case value_t::discarded:
21541 size_type max_size()
const noexcept {
21542 switch (m_data.m_type) {
21543 case value_t::array:
21546 return m_data.m_value.array->max_size();
21549 case value_t::object:
21552 return m_data.m_value.object->max_size();
21555 case value_t::null:
21556 case value_t::string:
21557 case value_t::boolean:
21558 case value_t::number_integer:
21559 case value_t::number_unsigned:
21560 case value_t::number_float:
21561 case value_t::binary:
21562 case value_t::discarded:
21582 void clear()
noexcept {
21583 switch (m_data.m_type) {
21584 case value_t::number_integer:
21586 m_data.m_value.number_integer = 0;
21590 case value_t::number_unsigned:
21592 m_data.m_value.number_unsigned = 0;
21596 case value_t::number_float:
21598 m_data.m_value.number_float = 0.0;
21602 case value_t::boolean:
21604 m_data.m_value.boolean =
false;
21608 case value_t::string:
21610 m_data.m_value.string->clear();
21614 case value_t::binary:
21616 m_data.m_value.binary->clear();
21620 case value_t::array:
21622 m_data.m_value.array->clear();
21626 case value_t::object:
21628 m_data.m_value.object->clear();
21632 case value_t::null:
21633 case value_t::discarded:
21641 void push_back(basic_json&& val) {
21643 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array()))) {
21644 JSON_THROW(type_error::create(308, detail::concat(
"cannot use push_back() with ", type_name()),
this));
21649 m_data.m_type = value_t::array;
21650 m_data.m_value = value_t::array;
21651 assert_invariant();
21655 const auto old_capacity = m_data.m_value.array->capacity();
21656 m_data.m_value.array->push_back(std::move(val));
21657 set_parent(m_data.m_value.array->back(), old_capacity);
21663 reference operator+=(basic_json&& val) {
21664 push_back(std::move(val));
21670 void push_back(
const basic_json& val) {
21672 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array()))) {
21673 JSON_THROW(type_error::create(308, detail::concat(
"cannot use push_back() with ", type_name()),
this));
21678 m_data.m_type = value_t::array;
21679 m_data.m_value = value_t::array;
21680 assert_invariant();
21684 const auto old_capacity = m_data.m_value.array->capacity();
21685 m_data.m_value.array->push_back(val);
21686 set_parent(m_data.m_value.array->back(), old_capacity);
21691 reference operator+=(
const basic_json& val) {
21698 void push_back(
const typename object_t::value_type& val) {
21700 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object()))) {
21701 JSON_THROW(type_error::create(308, detail::concat(
"cannot use push_back() with ", type_name()),
this));
21706 m_data.m_type = value_t::object;
21707 m_data.m_value = value_t::object;
21708 assert_invariant();
21712 auto res = m_data.m_value.object->insert(val);
21713 set_parent(res.first->second);
21718 reference operator+=(
const typename object_t::value_type& val) {
21725 void push_back(initializer_list_t init) {
21726 if (is_object() && init.size() == 2 && (*init.begin())->is_string()) {
21727 basic_json&& key = init.begin()->moved_or_copied();
21728 push_back(
typename object_t::value_type(
21729 std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied()));
21732 push_back(basic_json(init));
21738 reference operator+=(initializer_list_t init) {
21745 template<
class... Args>
21746 reference emplace_back(Args&& ... args) {
21748 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array()))) {
21749 JSON_THROW(type_error::create(311, detail::concat(
"cannot use emplace_back() with ", type_name()),
this));
21754 m_data.m_type = value_t::array;
21755 m_data.m_value = value_t::array;
21756 assert_invariant();
21760 const auto old_capacity = m_data.m_value.array->capacity();
21761 m_data.m_value.array->emplace_back(std::forward<Args>(args)...);
21762 return set_parent(m_data.m_value.array->back(), old_capacity);
21767 template<
class... Args>
21768 std::pair<iterator, bool> emplace(Args&& ... args) {
21770 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object()))) {
21771 JSON_THROW(type_error::create(311, detail::concat(
"cannot use emplace() with ", type_name()),
this));
21776 m_data.m_type = value_t::object;
21777 m_data.m_value = value_t::object;
21778 assert_invariant();
21782 auto res = m_data.m_value.object->emplace(std::forward<Args>(args)...);
21783 set_parent(res.first->second);
21787 it.m_it.object_iterator = res.first;
21790 return { it, res.second };
21796 template<
typename... Args>
21797 iterator insert_iterator(const_iterator pos, Args&& ... args)
21799 iterator result(
this);
21800 JSON_ASSERT(m_data.m_value.array !=
nullptr);
21802 auto insert_pos = std::distance(m_data.m_value.array->begin(), pos.m_it.array_iterator);
21803 m_data.m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...);
21804 result.m_it.array_iterator = m_data.m_value.array->begin() + insert_pos;
21816 iterator insert(const_iterator pos,
const basic_json& val)
21819 if (JSON_HEDLEY_LIKELY(is_array())) {
21821 if (JSON_HEDLEY_UNLIKELY(pos.m_object !=
this)) {
21822 JSON_THROW(invalid_iterator::create(202,
"iterator does not fit current value",
this));
21826 return insert_iterator(pos, val);
21829 JSON_THROW(type_error::create(309, detail::concat(
"cannot use insert() with ", type_name()),
this));
21834 iterator insert(const_iterator pos, basic_json&& val)
21836 return insert(pos, val);
21841 iterator insert(const_iterator pos, size_type cnt,
const basic_json& val)
21844 if (JSON_HEDLEY_LIKELY(is_array())) {
21846 if (JSON_HEDLEY_UNLIKELY(pos.m_object !=
this)) {
21847 JSON_THROW(invalid_iterator::create(202,
"iterator does not fit current value",
this));
21851 return insert_iterator(pos, cnt, val);
21854 JSON_THROW(type_error::create(309, detail::concat(
"cannot use insert() with ", type_name()),
this));
21859 iterator insert(const_iterator pos, const_iterator first, const_iterator last)
21862 if (JSON_HEDLEY_UNLIKELY(!is_array())) {
21863 JSON_THROW(type_error::create(309, detail::concat(
"cannot use insert() with ", type_name()),
this));
21867 if (JSON_HEDLEY_UNLIKELY(pos.m_object !=
this)) {
21868 JSON_THROW(invalid_iterator::create(202,
"iterator does not fit current value",
this));
21872 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) {
21873 JSON_THROW(invalid_iterator::create(210,
"iterators do not fit",
this));
21876 if (JSON_HEDLEY_UNLIKELY(first.m_object ==
this)) {
21877 JSON_THROW(invalid_iterator::create(211,
"passed iterators may not belong to container",
this));
21881 return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator);
21886 iterator insert(const_iterator pos, initializer_list_t ilist)
21889 if (JSON_HEDLEY_UNLIKELY(!is_array())) {
21890 JSON_THROW(type_error::create(309, detail::concat(
"cannot use insert() with ", type_name()),
this));
21894 if (JSON_HEDLEY_UNLIKELY(pos.m_object !=
this)) {
21895 JSON_THROW(invalid_iterator::create(202,
"iterator does not fit current value",
this));
21899 return insert_iterator(pos, ilist.begin(), ilist.end());
21904 void insert(const_iterator first, const_iterator last)
21907 if (JSON_HEDLEY_UNLIKELY(!is_object())) {
21908 JSON_THROW(type_error::create(309, detail::concat(
"cannot use insert() with ", type_name()),
this));
21912 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) {
21913 JSON_THROW(invalid_iterator::create(210,
"iterators do not fit",
this));
21917 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object())) {
21918 JSON_THROW(invalid_iterator::create(202,
"iterators first and last must point to objects",
this));
21921 m_data.m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);
21927 void update(const_reference j,
bool merge_objects =
false) {
21928 update(j.begin(), j.end(), merge_objects);
21933 void update(const_iterator first, const_iterator last,
bool merge_objects =
false)
21937 m_data.m_type = value_t::object;
21938 m_data.m_value.object = create<object_t>();
21939 assert_invariant();
21942 if (JSON_HEDLEY_UNLIKELY(!is_object())) {
21943 JSON_THROW(type_error::create(312, detail::concat(
"cannot use update() with ", type_name()),
this));
21947 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) {
21948 JSON_THROW(invalid_iterator::create(210,
"iterators do not fit",
this));
21952 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object())) {
21953 JSON_THROW(type_error::create(312, detail::concat(
"cannot use update() with ", first.m_object->type_name()), first.m_object));
21956 for (
auto it = first; it != last; ++it) {
21957 if (merge_objects && it.value().is_object()) {
21958 auto it2 = m_data.m_value.object->find(it.key());
21959 if (it2 != m_data.m_value.object->end()) {
21960 it2->second.update(it.value(),
true);
21964 m_data.m_value.object->operator[](it.key()) = it.value();
21965#if JSON_DIAGNOSTICS
21966 m_data.m_value.object->operator[](it.key()).m_parent =
this;
21973 void swap(reference other)
noexcept (
21974 std::is_nothrow_move_constructible<value_t>::value&&
21975 std::is_nothrow_move_assignable<value_t>::value&&
21976 std::is_nothrow_move_constructible<json_value>::value&&
21977 std::is_nothrow_move_assignable<json_value>::value
21979 std::swap(m_data.m_type, other.m_data.m_type);
21980 std::swap(m_data.m_value, other.m_data.m_value);
21983 other.set_parents();
21984 assert_invariant();
21989 friend void swap(reference left, reference right)
noexcept (
21990 std::is_nothrow_move_constructible<value_t>::value&&
21991 std::is_nothrow_move_assignable<value_t>::value&&
21992 std::is_nothrow_move_constructible<json_value>::value&&
21993 std::is_nothrow_move_assignable<json_value>::value
22000 void swap(array_t& other)
22003 if (JSON_HEDLEY_LIKELY(is_array())) {
22005 swap(*(m_data.m_value.array), other);
22008 JSON_THROW(type_error::create(310, detail::concat(
"cannot use swap(array_t&) with ", type_name()),
this));
22014 void swap(object_t& other)
22017 if (JSON_HEDLEY_LIKELY(is_object())) {
22019 swap(*(m_data.m_value.object), other);
22022 JSON_THROW(type_error::create(310, detail::concat(
"cannot use swap(object_t&) with ", type_name()),
this));
22028 void swap(string_t& other)
22031 if (JSON_HEDLEY_LIKELY(is_string())) {
22033 swap(*(m_data.m_value.string), other);
22036 JSON_THROW(type_error::create(310, detail::concat(
"cannot use swap(string_t&) with ", type_name()),
this));
22042 void swap(binary_t& other)
22045 if (JSON_HEDLEY_LIKELY(is_binary())) {
22047 swap(*(m_data.m_value.binary), other);
22050 JSON_THROW(type_error::create(310, detail::concat(
"cannot use swap(binary_t&) with ", type_name()),
this));
22056 void swap(
typename binary_t::container_type& other)
22059 if (JSON_HEDLEY_LIKELY(is_binary())) {
22061 swap(*(m_data.m_value.binary), other);
22064 JSON_THROW(type_error::create(310, detail::concat(
"cannot use swap(binary_t::container_type&) with ", type_name()),
this));
22079#define JSON_IMPLEMENT_OPERATOR(op, null_result, unordered_result, default_result) \
22080 const auto lhs_type = lhs.type(); \
22081 const auto rhs_type = rhs.type(); \
22083 if (lhs_type == rhs_type) \
22085 switch (lhs_type) \
22087 case value_t::array: \
22088 return (*lhs.m_data.m_value.array) op (*rhs.m_data.m_value.array); \
22090 case value_t::object: \
22091 return (*lhs.m_data.m_value.object) op (*rhs.m_data.m_value.object); \
22093 case value_t::null: \
22094 return (null_result); \
22096 case value_t::string: \
22097 return (*lhs.m_data.m_value.string) op (*rhs.m_data.m_value.string); \
22099 case value_t::boolean: \
22100 return (lhs.m_data.m_value.boolean) op (rhs.m_data.m_value.boolean); \
22102 case value_t::number_integer: \
22103 return (lhs.m_data.m_value.number_integer) op (rhs.m_data.m_value.number_integer); \
22105 case value_t::number_unsigned: \
22106 return (lhs.m_data.m_value.number_unsigned) op (rhs.m_data.m_value.number_unsigned); \
22108 case value_t::number_float: \
22109 return (lhs.m_data.m_value.number_float) op (rhs.m_data.m_value.number_float); \
22111 case value_t::binary: \
22112 return (*lhs.m_data.m_value.binary) op (*rhs.m_data.m_value.binary); \
22114 case value_t::discarded: \
22116 return (unordered_result); \
22119 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float) \
22121 return static_cast<number_float_t>(lhs.m_data.m_value.number_integer) op rhs.m_data.m_value.number_float; \
22123 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer) \
22125 return lhs.m_data.m_value.number_float op static_cast<number_float_t>(rhs.m_data.m_value.number_integer); \
22127 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float) \
22129 return static_cast<number_float_t>(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_float; \
22131 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned) \
22133 return lhs.m_data.m_value.number_float op static_cast<number_float_t>(rhs.m_data.m_value.number_unsigned); \
22135 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer) \
22137 return static_cast<number_integer_t>(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_integer; \
22139 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned) \
22141 return lhs.m_data.m_value.number_integer op static_cast<number_integer_t>(rhs.m_data.m_value.number_unsigned); \
22143 else if(compares_unordered(lhs, rhs))\
22145 return (unordered_result);\
22148 return (default_result);
22150JSON_PRIVATE_UNLESS_TESTED:
22156 static bool compares_unordered(const_reference lhs, const_reference rhs,
bool inverse =
false)
noexcept {
22157 if ((lhs.is_number_float() && std::isnan(lhs.m_data.m_value.number_float) && rhs.is_number())
22158 || (rhs.is_number_float() && std::isnan(rhs.m_data.m_value.number_float) && lhs.is_number())) {
22161#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
22162 return (lhs.is_discarded() || rhs.is_discarded()) && !inverse;
22164 static_cast<void>(inverse);
22165 return lhs.is_discarded() || rhs.is_discarded();
22170 bool compares_unordered(const_reference rhs,
bool inverse =
false)
const noexcept {
22171 return compares_unordered(*
this, rhs, inverse);
22175#if JSON_HAS_THREE_WAY_COMPARISON
22178 bool operator==(const_reference rhs)
const noexcept {
22180#pragma GCC diagnostic push
22181#pragma GCC diagnostic ignored "-Wfloat-equal"
22183 const_reference lhs = *
this;
22184 JSON_IMPLEMENT_OPERATOR(== ,
true,
false,
false)
22186#pragma GCC diagnostic pop
22192 template<
typename ScalarType>
22193 requires std::is_scalar_v<ScalarType>
22194 bool operator==(ScalarType rhs)
const noexcept {
22195 return *
this == basic_json(rhs);
22200 bool operator!=(const_reference rhs)
const noexcept {
22201 if (compares_unordered(rhs,
true)) {
22204 return !operator==(rhs);
22209 std::partial_ordering operator<=>(const_reference rhs)
const noexcept
22211 const_reference lhs = *
this;
22214 JSON_IMPLEMENT_OPERATOR(<=> ,
22215 std::partial_ordering::equivalent,
22216 std::partial_ordering::unordered,
22217 lhs_type <=> rhs_type)
22222 template<
typename ScalarType>
22223 requires std::is_scalar_v<ScalarType>
22224 std::partial_ordering operator<=>(ScalarType rhs)
const noexcept
22226 return *this <=> basic_json(rhs);
22229#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
22235 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON)
22236 bool operator<=(const_reference rhs)
const noexcept {
22237 if (compares_unordered(rhs,
true)) {
22240 return !(rhs < *
this);
22245 template<
typename ScalarType>
22246 requires std::is_scalar_v<ScalarType>
22247 bool operator<=(ScalarType rhs)
const noexcept {
22248 return *
this <= basic_json(rhs);
22253 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON)
22254 bool operator>=(const_reference rhs)
const noexcept {
22255 if (compares_unordered(rhs,
true)) {
22258 return !(*
this < rhs);
22263 template<
typename ScalarType>
22264 requires std::is_scalar_v<ScalarType>
22265 bool operator>=(ScalarType rhs)
const noexcept {
22266 return *
this >= basic_json(rhs);
22272 friend bool operator==(const_reference lhs, const_reference rhs)
noexcept {
22274#pragma GCC diagnostic push
22275#pragma GCC diagnostic ignored "-Wfloat-equal"
22277 JSON_IMPLEMENT_OPERATOR(== ,
true,
false,
false)
22279#pragma GCC diagnostic pop
22285 template<
typename ScalarType,
typename std::enable_if<
22286 std::is_scalar<ScalarType>::value,
int>::type = 0>
22287 friend bool operator==(const_reference lhs, ScalarType rhs)
noexcept {
22288 return lhs == basic_json(rhs);
22293 template<
typename ScalarType,
typename std::enable_if<
22294 std::is_scalar<ScalarType>::value,
int>::type = 0>
22295 friend bool operator==(ScalarType lhs, const_reference rhs)
noexcept {
22296 return basic_json(lhs) == rhs;
22301 friend bool operator!=(const_reference lhs, const_reference rhs)
noexcept {
22302 if (compares_unordered(lhs, rhs,
true)) {
22305 return !(lhs == rhs);
22310 template<
typename ScalarType,
typename std::enable_if<
22311 std::is_scalar<ScalarType>::value,
int>::type = 0>
22312 friend bool operator!=(const_reference lhs, ScalarType rhs)
noexcept {
22313 return lhs != basic_json(rhs);
22318 template<
typename ScalarType,
typename std::enable_if<
22319 std::is_scalar<ScalarType>::value,
int>::type = 0>
22320 friend bool operator!=(ScalarType lhs, const_reference rhs)
noexcept {
22321 return basic_json(lhs) != rhs;
22326 friend bool operator<(const_reference lhs, const_reference rhs)
noexcept {
22330 JSON_IMPLEMENT_OPERATOR(< ,
false,
false,
operator<(lhs_type, rhs_type))
22335 template<
typename ScalarType,
typename std::enable_if<
22336 std::is_scalar<ScalarType>::value,
int>::type = 0>
22337 friend bool operator<(const_reference lhs, ScalarType rhs)
noexcept {
22338 return lhs < basic_json(rhs);
22343 template<
typename ScalarType,
typename std::enable_if<
22344 std::is_scalar<ScalarType>::value,
int>::type = 0>
22345 friend bool operator<(ScalarType lhs, const_reference rhs)
noexcept {
22346 return basic_json(lhs) < rhs;
22351 friend bool operator<=(const_reference lhs, const_reference rhs)
noexcept {
22352 if (compares_unordered(lhs, rhs,
true)) {
22355 return !(rhs < lhs);
22360 template<
typename ScalarType,
typename std::enable_if<
22361 std::is_scalar<ScalarType>::value,
int>::type = 0>
22362 friend bool operator<=(const_reference lhs, ScalarType rhs)
noexcept {
22363 return lhs <= basic_json(rhs);
22368 template<
typename ScalarType,
typename std::enable_if<
22369 std::is_scalar<ScalarType>::value,
int>::type = 0>
22370 friend bool operator<=(ScalarType lhs, const_reference rhs)
noexcept {
22371 return basic_json(lhs) <= rhs;
22376 friend bool operator>(const_reference lhs, const_reference rhs)
noexcept {
22378 if (compares_unordered(lhs, rhs)) {
22381 return !(lhs <= rhs);
22386 template<
typename ScalarType,
typename std::enable_if<
22387 std::is_scalar<ScalarType>::value,
int>::type = 0>
22388 friend bool operator>(const_reference lhs, ScalarType rhs)
noexcept {
22389 return lhs > basic_json(rhs);
22394 template<
typename ScalarType,
typename std::enable_if<
22395 std::is_scalar<ScalarType>::value,
int>::type = 0>
22396 friend bool operator>(ScalarType lhs, const_reference rhs)
noexcept {
22397 return basic_json(lhs) > rhs;
22402 friend bool operator>=(const_reference lhs, const_reference rhs)
noexcept {
22403 if (compares_unordered(lhs, rhs,
true)) {
22406 return !(lhs < rhs);
22411 template<
typename ScalarType,
typename std::enable_if<
22412 std::is_scalar<ScalarType>::value,
int>::type = 0>
22413 friend bool operator>=(const_reference lhs, ScalarType rhs)
noexcept {
22414 return lhs >= basic_json(rhs);
22419 template<
typename ScalarType,
typename std::enable_if<
22420 std::is_scalar<ScalarType>::value,
int>::type = 0>
22421 friend bool operator>=(ScalarType lhs, const_reference rhs)
noexcept {
22422 return basic_json(lhs) >= rhs;
22426#undef JSON_IMPLEMENT_OPERATOR
22439 friend std::ostream& operator<<(std::ostream& o,
const basic_json& j) {
22441 const bool pretty_print = o.width() > 0;
22442 const auto indentation = pretty_print ? o.width() : 0;
22449 s.dump(j, pretty_print,
false,
static_cast<unsigned int>(indentation));
22459 JSON_HEDLEY_DEPRECATED_FOR(3.0.0,
operator<<(std::ostream&,
const basic_json&))
22460 friend std::ostream& operator>>(
const basic_json& j, std::ostream& o) {
22475 template<
typename InputType>
22476 JSON_HEDLEY_WARN_UNUSED_RESULT
22477 static basic_json parse(InputType&& i,
22478 parser_callback_t cb =
nullptr,
22479 const bool allow_exceptions =
true,
22480 const bool ignore_comments =
false,
22481 const bool ignore_trailing_commas =
false) {
22483 parser(detail::input_adapter(std::forward<InputType>(i)), std::move(cb), allow_exceptions, ignore_comments, ignore_trailing_commas).parse(
true, result);
22489 template<
typename IteratorType>
22490 JSON_HEDLEY_WARN_UNUSED_RESULT
22491 static basic_json parse(IteratorType first,
22493 parser_callback_t cb =
nullptr,
22494 const bool allow_exceptions =
true,
22495 const bool ignore_comments =
false,
22496 const bool ignore_trailing_commas =
false) {
22498 parser(detail::input_adapter(std::move(first), std::move(last)), std::move(cb), allow_exceptions, ignore_comments, ignore_trailing_commas).parse(
true, result);
22502 JSON_HEDLEY_WARN_UNUSED_RESULT
22503 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len))
22505 parser_callback_t cb =
nullptr,
22506 const bool allow_exceptions =
true,
22507 const bool ignore_comments =
false,
22508 const bool ignore_trailing_commas =
false) {
22510 parser(i.get(), std::move(cb), allow_exceptions, ignore_comments, ignore_trailing_commas).parse(
true, result);
22516 template<
typename InputType>
22517 static bool accept(InputType&& i,
22518 const bool ignore_comments =
false,
22519 const bool ignore_trailing_commas =
false) {
22520 return parser(detail::input_adapter(std::forward<InputType>(i)),
nullptr,
false, ignore_comments, ignore_trailing_commas).accept(
true);
22525 template<
typename IteratorType>
22526 static bool accept(IteratorType first, IteratorType last,
22527 const bool ignore_comments =
false,
22528 const bool ignore_trailing_commas =
false) {
22529 return parser(detail::input_adapter(std::move(first), std::move(last)),
nullptr,
false, ignore_comments, ignore_trailing_commas).accept(
true);
22532 JSON_HEDLEY_WARN_UNUSED_RESULT
22533 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len))
22535 const bool ignore_comments =
false,
22536 const bool ignore_trailing_commas =
false) {
22537 return parser(i.get(),
nullptr,
false, ignore_comments, ignore_trailing_commas).accept(
true);
22542 template <
typename InputType,
typename SAX>
22543 JSON_HEDLEY_NON_NULL(2)
22544 static bool sax_parse(InputType&& i, SAX* sax,
22545 input_format_t format = input_format_t::json,
22546 const bool strict =
true,
22547 const bool ignore_comments =
false,
22548 const bool ignore_trailing_commas =
false) {
22549#if defined(__clang__)
22550#pragma clang diagnostic push
22551#pragma clang diagnostic ignored "-Wtautological-pointer-compare"
22552#elif defined(__GNUC__)
22553#pragma GCC diagnostic push
22554#pragma GCC diagnostic ignored "-Wnonnull-compare"
22556 if (sax ==
nullptr) {
22557 JSON_THROW(other_error::create(502,
"SAX handler must not be null",
nullptr));
22559#if defined(__clang__)
22560#pragma clang diagnostic pop
22561#elif defined(__GNUC__)
22562#pragma GCC diagnostic pop
22564 auto ia = detail::input_adapter(std::forward<InputType>(i));
22565 return format == input_format_t::json
22566 ? parser(std::move(ia),
nullptr,
true, ignore_comments, ignore_trailing_commas).sax_parse(sax, strict)
22572 template<
class IteratorType,
class SAX>
22573 JSON_HEDLEY_NON_NULL(3)
22574 static bool sax_parse(IteratorType first, IteratorType last, SAX* sax,
22575 input_format_t format = input_format_t::json,
22576 const bool strict =
true,
22577 const bool ignore_comments =
false,
22578 const bool ignore_trailing_commas =
false) {
22579#if defined(__clang__)
22580#pragma clang diagnostic push
22581#pragma clang diagnostic ignored "-Wtautological-pointer-compare"
22582#elif defined(__GNUC__)
22583#pragma GCC diagnostic push
22584#pragma GCC diagnostic ignored "-Wnonnull-compare"
22586 if (sax ==
nullptr) {
22587 JSON_THROW(other_error::create(502,
"SAX handler must not be null",
nullptr));
22589#if defined(__clang__)
22590#pragma clang diagnostic pop
22591#elif defined(__GNUC__)
22592#pragma GCC diagnostic pop
22594 auto ia = detail::input_adapter(std::move(first), std::move(last));
22595 return format == input_format_t::json
22596 ? parser(std::move(ia),
nullptr,
true, ignore_comments, ignore_trailing_commas).sax_parse(sax, strict)
22605 template <
typename SAX>
22606 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...))
22607 JSON_HEDLEY_NON_NULL(2)
22609 input_format_t format = input_format_t::json,
22610 const bool strict =
true,
22611 const bool ignore_comments =
false,
22612 const bool ignore_trailing_commas =
false) {
22613#if defined(__clang__)
22614#pragma clang diagnostic push
22615#pragma clang diagnostic ignored "-Wtautological-pointer-compare"
22616#elif defined(__GNUC__)
22617#pragma GCC diagnostic push
22618#pragma GCC diagnostic ignored "-Wnonnull-compare"
22620 if (sax ==
nullptr) {
22621 JSON_THROW(other_error::create(502,
"SAX handler must not be null",
nullptr));
22623#if defined(__clang__)
22624#pragma clang diagnostic pop
22625#elif defined(__GNUC__)
22626#pragma GCC diagnostic pop
22629 return format == input_format_t::json
22631 ? parser(std::move(ia),
nullptr,
true, ignore_comments, ignore_trailing_commas).sax_parse(sax, strict)
22642 JSON_HEDLEY_DEPRECATED_FOR(3.0.0,
operator>>(std::istream&, basic_json&))
22643 friend std::istream& operator<<(basic_json& j, std::istream& i) {
22644 return operator>>(i, j);
22649 friend std::istream& operator>>(std::istream& i, basic_json& j) {
22650 parser(detail::input_adapter(i)).parse(
false, j);
22662 JSON_HEDLEY_RETURNS_NON_NULL
22663 const char* type_name()
const noexcept {
22664 switch (m_data.m_type) {
22665 case value_t::null:
22667 case value_t::object:
22669 case value_t::array:
22671 case value_t::string:
22673 case value_t::boolean:
22675 case value_t::binary:
22677 case value_t::discarded:
22678 return "discarded";
22679 case value_t::number_integer:
22680 case value_t::number_unsigned:
22681 case value_t::number_float:
22688JSON_PRIVATE_UNLESS_TESTED:
22695 value_t m_type = value_t::null;
22698 json_value m_value = {};
22700 data(
const value_t v)
22701 : m_type(v), m_value(v) {}
22703 data(size_type cnt,
const basic_json& val)
22704 : m_type(value_t::array) {
22705 m_value.array = create<array_t>(cnt, val);
22708 data()
noexcept =
default;
22709 data(data&&)
noexcept =
default;
22710 data(
const data&)
noexcept =
delete;
22711 data& operator=(data&&)
noexcept =
delete;
22712 data& operator=(
const data&)
noexcept =
delete;
22715 m_value.destroy(m_type);
22721#if JSON_DIAGNOSTICS
22723 basic_json* m_parent =
nullptr;
22726#if JSON_DIAGNOSTIC_POSITIONS
22728 std::size_t start_position = std::string::npos;
22730 std::size_t end_position = std::string::npos;
22732 constexpr std::size_t start_pos()
const noexcept {
22733 return start_position;
22736 constexpr std::size_t end_pos()
const noexcept {
22737 return end_position;
22751 static std::vector<std::uint8_t> to_cbor(
const basic_json& j) {
22752 std::vector<std::uint8_t> result;
22753 to_cbor(j, result);
22760 binary_writer<std::uint8_t>(o).write_cbor(j);
22766 binary_writer<char>(o).write_cbor(j);
22771 static std::vector<std::uint8_t> to_msgpack(
const basic_json& j) {
22772 std::vector<std::uint8_t> result;
22773 to_msgpack(j, result);
22780 binary_writer<std::uint8_t>(o).write_msgpack(j);
22786 binary_writer<char>(o).write_msgpack(j);
22791 static std::vector<std::uint8_t> to_ubjson(
const basic_json& j,
22792 const bool use_size =
false,
22793 const bool use_type =
false) {
22794 std::vector<std::uint8_t> result;
22795 to_ubjson(j, result, use_size, use_type);
22802 const bool use_size =
false,
const bool use_type =
false) {
22803 binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type);
22809 const bool use_size =
false,
const bool use_type =
false) {
22810 binary_writer<char>(o).write_ubjson(j, use_size, use_type);
22815 static std::vector<std::uint8_t> to_bjdata(
const basic_json& j,
22816 const bool use_size =
false,
22817 const bool use_type =
false,
22818 const bjdata_version_t version = bjdata_version_t::draft2) {
22819 std::vector<std::uint8_t> result;
22820 to_bjdata(j, result, use_size, use_type, version);
22827 const bool use_size =
false,
const bool use_type =
false,
22828 const bjdata_version_t version = bjdata_version_t::draft2) {
22829 binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type,
true,
true, version);
22835 const bool use_size =
false,
const bool use_type =
false,
22836 const bjdata_version_t version = bjdata_version_t::draft2) {
22837 binary_writer<char>(o).write_ubjson(j, use_size, use_type,
true,
true, version);
22842 static std::vector<std::uint8_t> to_bson(
const basic_json& j) {
22843 std::vector<std::uint8_t> result;
22844 to_bson(j, result);
22851 binary_writer<std::uint8_t>(o).write_bson(j);
22857 binary_writer<char>(o).write_bson(j);
22862 template<
typename InputType>
22863 JSON_HEDLEY_WARN_UNUSED_RESULT
22864 static basic_json from_cbor(InputType&& i,
22865 const bool strict =
true,
22866 const bool allow_exceptions =
true,
22867 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) {
22869 auto ia = detail::input_adapter(std::forward<InputType>(i));
22871 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
22872 return res ? result : basic_json(value_t::discarded);
22877 template<
typename IteratorType>
22878 JSON_HEDLEY_WARN_UNUSED_RESULT
22879 static basic_json from_cbor(IteratorType first, IteratorType last,
22880 const bool strict =
true,
22881 const bool allow_exceptions =
true,
22882 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) {
22884 auto ia = detail::input_adapter(std::move(first), std::move(last));
22886 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
22887 return res ? result : basic_json(value_t::discarded);
22890 template<
typename T>
22891 JSON_HEDLEY_WARN_UNUSED_RESULT
22892 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
22893 static basic_json from_cbor(
const T* ptr, std::size_t len,
22894 const bool strict =
true,
22895 const bool allow_exceptions =
true,
22896 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) {
22897 return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler);
22900 JSON_HEDLEY_WARN_UNUSED_RESULT
22901 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
22903 const bool strict =
true,
22904 const bool allow_exceptions =
true,
22905 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) {
22910 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
22911 return res ? result : basic_json(value_t::discarded);
22916 template<
typename InputType>
22917 JSON_HEDLEY_WARN_UNUSED_RESULT
22918 static basic_json from_msgpack(InputType&& i,
22919 const bool strict =
true,
22920 const bool allow_exceptions =
true) {
22922 auto ia = detail::input_adapter(std::forward<InputType>(i));
22924 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
22925 return res ? result : basic_json(value_t::discarded);
22930 template<
typename IteratorType>
22931 JSON_HEDLEY_WARN_UNUSED_RESULT
22932 static basic_json from_msgpack(IteratorType first, IteratorType last,
22933 const bool strict =
true,
22934 const bool allow_exceptions =
true) {
22936 auto ia = detail::input_adapter(std::move(first), std::move(last));
22938 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
22939 return res ? result : basic_json(value_t::discarded);
22942 template<
typename T>
22943 JSON_HEDLEY_WARN_UNUSED_RESULT
22944 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
22945 static basic_json from_msgpack(
const T* ptr, std::size_t len,
22946 const bool strict =
true,
22947 const bool allow_exceptions =
true) {
22948 return from_msgpack(ptr, ptr + len, strict, allow_exceptions);
22951 JSON_HEDLEY_WARN_UNUSED_RESULT
22952 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
22954 const bool strict =
true,
22955 const bool allow_exceptions =
true) {
22960 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
22961 return res ? result : basic_json(value_t::discarded);
22966 template<
typename InputType>
22967 JSON_HEDLEY_WARN_UNUSED_RESULT
22968 static basic_json from_ubjson(InputType&& i,
22969 const bool strict =
true,
22970 const bool allow_exceptions =
true) {
22972 auto ia = detail::input_adapter(std::forward<InputType>(i));
22974 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
22975 return res ? result : basic_json(value_t::discarded);
22980 template<
typename IteratorType>
22981 JSON_HEDLEY_WARN_UNUSED_RESULT
22982 static basic_json from_ubjson(IteratorType first, IteratorType last,
22983 const bool strict =
true,
22984 const bool allow_exceptions =
true) {
22986 auto ia = detail::input_adapter(std::move(first), std::move(last));
22988 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
22989 return res ? result : basic_json(value_t::discarded);
22992 template<
typename T>
22993 JSON_HEDLEY_WARN_UNUSED_RESULT
22994 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
22995 static basic_json from_ubjson(
const T* ptr, std::size_t len,
22996 const bool strict =
true,
22997 const bool allow_exceptions =
true) {
22998 return from_ubjson(ptr, ptr + len, strict, allow_exceptions);
23001 JSON_HEDLEY_WARN_UNUSED_RESULT
23002 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
23004 const bool strict =
true,
23005 const bool allow_exceptions =
true) {
23010 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
23011 return res ? result : basic_json(value_t::discarded);
23016 template<
typename InputType>
23017 JSON_HEDLEY_WARN_UNUSED_RESULT
23018 static basic_json from_bjdata(InputType&& i,
23019 const bool strict =
true,
23020 const bool allow_exceptions =
true) {
23022 auto ia = detail::input_adapter(std::forward<InputType>(i));
23024 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict);
23025 return res ? result : basic_json(value_t::discarded);
23030 template<
typename IteratorType>
23031 JSON_HEDLEY_WARN_UNUSED_RESULT
23032 static basic_json from_bjdata(IteratorType first, IteratorType last,
23033 const bool strict =
true,
23034 const bool allow_exceptions =
true) {
23036 auto ia = detail::input_adapter(std::move(first), std::move(last));
23038 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict);
23039 return res ? result : basic_json(value_t::discarded);
23044 template<
typename InputType>
23045 JSON_HEDLEY_WARN_UNUSED_RESULT
23046 static basic_json from_bson(InputType&& i,
23047 const bool strict =
true,
23048 const bool allow_exceptions =
true) {
23050 auto ia = detail::input_adapter(std::forward<InputType>(i));
23052 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
23053 return res ? result : basic_json(value_t::discarded);
23058 template<
typename IteratorType>
23059 JSON_HEDLEY_WARN_UNUSED_RESULT
23060 static basic_json from_bson(IteratorType first, IteratorType last,
23061 const bool strict =
true,
23062 const bool allow_exceptions =
true) {
23064 auto ia = detail::input_adapter(std::move(first), std::move(last));
23066 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
23067 return res ? result : basic_json(value_t::discarded);
23070 template<
typename T>
23071 JSON_HEDLEY_WARN_UNUSED_RESULT
23072 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
23073 static basic_json from_bson(
const T* ptr, std::size_t len,
23074 const bool strict =
true,
23075 const bool allow_exceptions =
true) {
23076 return from_bson(ptr, ptr + len, strict, allow_exceptions);
23079 JSON_HEDLEY_WARN_UNUSED_RESULT
23080 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
23082 const bool strict =
true,
23083 const bool allow_exceptions =
true) {
23088 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
23089 return res ? result : basic_json(value_t::discarded);
23102 reference operator[](
const json_pointer& ptr) {
23103 return ptr.get_unchecked(
this);
23106 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value,
int> = 0>
23107 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>)
23108 reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr) {
23109 return ptr.get_unchecked(
this);
23114 const_reference operator[](
const json_pointer& ptr)
const {
23115 return ptr.get_unchecked(
this);
23118 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value,
int> = 0>
23119 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>)
23120 const_reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr)
const {
23121 return ptr.get_unchecked(
this);
23126 reference at(
const json_pointer& ptr) {
23127 return ptr.get_checked(
this);
23130 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value,
int> = 0>
23131 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>)
23132 reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr) {
23133 return ptr.get_checked(
this);
23138 const_reference at(
const json_pointer& ptr)
const {
23139 return ptr.get_checked(
this);
23142 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value,
int> = 0>
23143 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>)
23144 const_reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr)
const {
23145 return ptr.get_checked(
this);
23150 basic_json flatten()
const {
23151 basic_json result(value_t::object);
23152 json_pointer::flatten(
"", *
this, result);
23158 basic_json unflatten()
const {
23159 return json_pointer::unflatten(*
this);
23173 void patch_inplace(
const basic_json& json_patch) {
23174 basic_json& result = *
this;
23176 enum class patch_operations { add, remove, replace, move, copy, test, invalid };
23178 const auto get_op = [](
const string_t& op) {
23180 return patch_operations::add;
23182 if (op ==
"remove") {
23183 return patch_operations::remove;
23185 if (op ==
"replace") {
23186 return patch_operations::replace;
23188 if (op ==
"move") {
23189 return patch_operations::move;
23191 if (op ==
"copy") {
23192 return patch_operations::copy;
23194 if (op ==
"test") {
23195 return patch_operations::test;
23198 return patch_operations::invalid;
23202 const auto operation_add = [&result](json_pointer& ptr,
const basic_json& val) {
23210 json_pointer
const top_pointer = ptr.top();
23211 if (top_pointer != ptr) {
23212 result.at(top_pointer);
23216 const auto last_path = ptr.back();
23219 basic_json& parent = result.at(ptr);
23221 switch (parent.m_data.m_type) {
23222 case value_t::null:
23223 case value_t::object:
23226 parent[last_path] = val;
23230 case value_t::array:
23232 if (last_path ==
"-") {
23234 parent.push_back(val);
23237 const auto idx = json_pointer::template array_index<basic_json_t>(last_path);
23238 if (JSON_HEDLEY_UNLIKELY(idx > parent.size())) {
23240 JSON_THROW(out_of_range::create(401, detail::concat(
"array index ", std::to_string(idx),
" is out of range"), &parent));
23244 parent.insert(parent.begin() +
static_cast<difference_type
>(idx), val);
23250 case value_t::string:
23251 case value_t::boolean:
23252 case value_t::number_integer:
23253 case value_t::number_unsigned:
23254 case value_t::number_float:
23255 case value_t::binary:
23256 case value_t::discarded:
23258 JSON_ASSERT(
false);
23263 const auto operation_remove = [
this, &result](json_pointer& ptr) {
23265 const auto last_path = ptr.back();
23267 basic_json& parent = result.at(ptr);
23270 if (parent.is_object()) {
23272 auto it = parent.find(last_path);
23273 if (JSON_HEDLEY_LIKELY(it != parent.end())) {
23277 JSON_THROW(out_of_range::create(403, detail::concat(
"key '", last_path,
"' not found"),
this));
23280 else if (parent.is_array()) {
23282 parent.erase(json_pointer::template array_index<basic_json_t>(last_path));
23287 if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array())) {
23288 JSON_THROW(parse_error::create(104, 0,
"JSON patch must be an array of objects", &json_patch));
23292 for (
const auto& val : json_patch) {
23294 const auto get_value = [&val](
const string_t& op,
23295 const string_t& member,
23296 bool string_type) -> basic_json& {
23298 auto it = val.m_data.m_value.object->find(member);
23301 const auto error_msg = (op ==
"op") ?
"operation" : detail::concat(
"operation '", op,
'\'');
23304 if (JSON_HEDLEY_UNLIKELY(it == val.m_data.m_value.object->end())) {
23306 JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg,
" must have member '", member,
"'"), &val));
23310 if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string())) {
23312 JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg,
" must have string member '", member,
"'"), &val));
23320 if (JSON_HEDLEY_UNLIKELY(!val.is_object())) {
23321 JSON_THROW(parse_error::create(104, 0,
"JSON patch must be an array of objects", &val));
23325 const auto op = get_value(
"op",
"op",
true).template get<string_t>();
23326 const auto path = get_value(op,
"path",
true).template get<string_t>();
23327 json_pointer ptr(path);
23329 switch (get_op(op)) {
23330 case patch_operations::add:
23332 operation_add(ptr, get_value(
"add",
"value",
false));
23336 case patch_operations::remove:
23338 operation_remove(ptr);
23342 case patch_operations::replace:
23345 result.at(ptr) = get_value(
"replace",
"value",
false);
23349 case patch_operations::move:
23351 const auto from_path = get_value(
"move",
"from",
true).template get<string_t>();
23352 json_pointer from_ptr(from_path);
23355 basic_json
const v = result.at(from_ptr);
23361 operation_remove(from_ptr);
23362 operation_add(ptr, v);
23366 case patch_operations::copy:
23368 const auto from_path = get_value(
"copy",
"from",
true).template get<string_t>();
23369 const json_pointer from_ptr(from_path);
23372 basic_json
const v = result.at(from_ptr);
23377 operation_add(ptr, v);
23381 case patch_operations::test:
23383 bool success =
false;
23388 success = (result.at(ptr) == get_value(
"test",
"value",
false));
23390 JSON_INTERNAL_CATCH(out_of_range&) {
23395 if (JSON_HEDLEY_UNLIKELY(!success)) {
23396 JSON_THROW(other_error::create(501, detail::concat(
"unsuccessful: ", val.dump()), &val));
23402 case patch_operations::invalid:
23407 JSON_THROW(parse_error::create(105, 0, detail::concat(
"operation value '", op,
"' is invalid"), &val));
23415 basic_json patch(
const basic_json& json_patch)
const {
23416 basic_json result = *
this;
23417 result.patch_inplace(json_patch);
23423 JSON_HEDLEY_WARN_UNUSED_RESULT
23424 static basic_json diff(
const basic_json& source,
const basic_json& target,
23425 const string_t& path =
"") {
23427 basic_json result(value_t::array);
23430 if (source == target) {
23434 if (source.type() != target.type()) {
23438 {
"op",
"replace"}, {
"path", path}, {
"value", target}
23443 switch (source.type()) {
23444 case value_t::array:
23448 while (i < source.size() && i < target.size()) {
23450 auto temp_diff = diff(source[i], target[i], detail::concat<string_t>(path,
'/', detail::to_string<string_t>(i)));
23451 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
23459 const auto end_index =
static_cast<difference_type
>(result.size());
23460 while (i < source.size()) {
23463 result.insert(result.begin() + end_index,
object(
23466 {
"path", detail::concat<string_t>(path,
'/', detail::to_string<string_t>(i))}
23472 while (i < target.size()) {
23476 {
"path", detail::concat<string_t>(path,
"/-")},
23477 {
"value", target[i]}
23485 case value_t::object:
23488 for (
auto it = source.cbegin(); it != source.cend(); ++it) {
23490 const auto path_key = detail::concat<string_t>(path,
'/',
detail::escape(it.key()));
23492 if (target.find(it.key()) != target.end()) {
23494 auto temp_diff = diff(it.value(), target[it.key()], path_key);
23495 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
23499 result.push_back(
object(
23501 {
"op",
"remove"}, {
"path", path_key}
23507 for (
auto it = target.cbegin(); it != target.cend(); ++it) {
23508 if (source.find(it.key()) == source.end()) {
23510 const auto path_key = detail::concat<string_t>(path,
'/',
detail::escape(it.key()));
23513 {
"op",
"add"}, {
"path", path_key},
23514 {
"value", it.value()}
23522 case value_t::null:
23523 case value_t::string:
23524 case value_t::boolean:
23525 case value_t::number_integer:
23526 case value_t::number_unsigned:
23527 case value_t::number_float:
23528 case value_t::binary:
23529 case value_t::discarded:
23535 {
"op",
"replace"}, {
"path", path}, {
"value", target}
23554 void merge_patch(
const basic_json& apply_patch) {
23555 if (apply_patch.is_object()) {
23556 if (!is_object()) {
23559 for (
auto it = apply_patch.begin(); it != apply_patch.end(); ++it) {
23560 if (it.value().is_null()) {
23564 operator[](it.key()).merge_patch(it.value());
23569 *
this = apply_patch;