mirror of
https://github.com/nlohmann/json.git
synced 2026-09-07 16:57:59 +00:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4776b9091c | ||
|
|
fd0ca40ea6 |
@@ -996,21 +996,23 @@ class binary_reader
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief reads a definite-length CBOR string
|
||||
@brief reads a CBOR string
|
||||
|
||||
Reads everything @ref get_cbor_string accepts except the indefinite-length
|
||||
form, which that function handles itself. The bytes are appended to @a
|
||||
result, so consecutive chunks of an indefinite-length string can be read
|
||||
into the same string.
|
||||
This function first reads starting bytes to determine the expected
|
||||
string length and then copies this number of bytes into a string.
|
||||
Additionally, CBOR's strings with indefinite lengths are supported.
|
||||
|
||||
@param[out] result string the bytes are appended to
|
||||
@param[out] result created string
|
||||
|
||||
@return whether string creation completed
|
||||
|
||||
@pre @a current is not EOF
|
||||
*/
|
||||
bool get_cbor_string_chunk(string_t& result)
|
||||
bool get_cbor_string(string_t& result)
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string")))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (current)
|
||||
{
|
||||
// UTF-8 string (0x00..0x17 bytes follow)
|
||||
@@ -1066,6 +1068,20 @@ class binary_reader
|
||||
return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
|
||||
}
|
||||
|
||||
case 0x7F: // UTF-8 string (indefinite length)
|
||||
{
|
||||
while (get() != 0xFF)
|
||||
{
|
||||
string_t chunk;
|
||||
if (!get_cbor_string(chunk))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
result.append(chunk);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
auto last_token = get_token_string();
|
||||
@@ -1076,82 +1092,23 @@ class binary_reader
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief reads a CBOR string
|
||||
@brief reads a CBOR byte array
|
||||
|
||||
This function first reads starting bytes to determine the expected
|
||||
string length and then copies this number of bytes into a string.
|
||||
Additionally, CBOR's strings with indefinite lengths are supported.
|
||||
byte array length and then copies this number of bytes into the byte array.
|
||||
Additionally, CBOR's byte arrays with indefinite lengths are supported.
|
||||
|
||||
@param[out] result created string
|
||||
|
||||
@return whether string creation completed
|
||||
*/
|
||||
bool get_cbor_string(string_t& result)
|
||||
{
|
||||
// number of indefinite-length strings that have been opened and not
|
||||
// closed yet. RFC 8949, Section 3.2.3 does not permit nesting them,
|
||||
// but this reader has always accepted it, so the open levels are
|
||||
// counted instead of recursed through, which overflowed the stack for
|
||||
// an input of repeated 0x7F bytes (see #5104). Every chunk is appended
|
||||
// to the same result, so no per-level state is needed.
|
||||
std::size_t open = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string")))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (current == 0x7F) // UTF-8 string (indefinite length)
|
||||
{
|
||||
++open;
|
||||
get();
|
||||
continue;
|
||||
}
|
||||
|
||||
// a break marker closes the innermost indefinite-length string;
|
||||
// outside of one it is not a string and falls through to the error
|
||||
if (open != 0 && current == 0xFF)
|
||||
{
|
||||
if (--open == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
get();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (JSON_HEDLEY_UNLIKELY(!get_cbor_string_chunk(result)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (open == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
get();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief reads a definite-length CBOR byte array
|
||||
|
||||
Reads everything @ref get_cbor_binary accepts except the indefinite-length
|
||||
form, which that function handles itself. The bytes are appended to @a
|
||||
result, so consecutive chunks of an indefinite-length byte array can be
|
||||
read into the same byte array.
|
||||
|
||||
@param[out] result byte array the bytes are appended to
|
||||
@param[out] result created byte array
|
||||
|
||||
@return whether byte array creation completed
|
||||
|
||||
@pre @a current is not EOF
|
||||
*/
|
||||
bool get_cbor_binary_chunk(binary_t& result)
|
||||
bool get_cbor_binary(binary_t& result)
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "binary")))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (current)
|
||||
{
|
||||
// Binary data (0x00..0x17 bytes follow)
|
||||
@@ -1211,6 +1168,20 @@ class binary_reader
|
||||
get_binary(input_format_t::cbor, len, result);
|
||||
}
|
||||
|
||||
case 0x5F: // Binary data (indefinite length)
|
||||
{
|
||||
while (get() != 0xFF)
|
||||
{
|
||||
binary_t chunk;
|
||||
if (!get_cbor_binary(chunk))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
result.insert(result.end(), chunk.begin(), chunk.end());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
auto last_token = get_token_string();
|
||||
@@ -1220,63 +1191,6 @@ class binary_reader
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief reads a CBOR byte array
|
||||
|
||||
This function first reads starting bytes to determine the expected
|
||||
byte array length and then copies this number of bytes into the byte array.
|
||||
Additionally, CBOR's byte arrays with indefinite lengths are supported.
|
||||
|
||||
@param[out] result created byte array
|
||||
|
||||
@return whether byte array creation completed
|
||||
*/
|
||||
bool get_cbor_binary(binary_t& result)
|
||||
{
|
||||
// the open indefinite-length byte arrays are counted rather than
|
||||
// recursed through, for the reason given in @ref get_cbor_string
|
||||
std::size_t open = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "binary")))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (current == 0x5F) // Binary data (indefinite length)
|
||||
{
|
||||
++open;
|
||||
get();
|
||||
continue;
|
||||
}
|
||||
|
||||
// a break marker closes the innermost indefinite-length byte
|
||||
// array; outside of one it falls through to the error below
|
||||
if (open != 0 && current == 0xFF)
|
||||
{
|
||||
if (--open == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
get();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (JSON_HEDLEY_UNLIKELY(!get_cbor_binary_chunk(result)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (open == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
get();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief narrow a definite CBOR array/map length to std::size_t
|
||||
|
||||
|
||||
+28
-70
@@ -4473,11 +4473,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
basic_json result;
|
||||
auto ia = detail::input_adapter(std::forward<InputType>(i));
|
||||
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
||||
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler)) // cppcheck-suppress[accessMoved]
|
||||
{
|
||||
result = value_t::discarded;
|
||||
}
|
||||
return result;
|
||||
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); // cppcheck-suppress[accessMoved]
|
||||
return res ? result : basic_json(value_t::discarded);
|
||||
}
|
||||
|
||||
/// @brief create a JSON value from an input in CBOR format (iterator pair, or iterator+sentinel pair for C++20 ranges support)
|
||||
@@ -4493,11 +4490,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
basic_json result;
|
||||
auto ia = detail::input_adapter(std::move(first), std::move(last));
|
||||
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
||||
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler)) // cppcheck-suppress[accessMoved]
|
||||
{
|
||||
result = value_t::discarded;
|
||||
}
|
||||
return result;
|
||||
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); // cppcheck-suppress[accessMoved]
|
||||
return res ? result : basic_json(value_t::discarded);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
@@ -4522,11 +4516,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
auto ia = i.get();
|
||||
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
||||
// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
|
||||
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler)) // cppcheck-suppress[accessMoved]
|
||||
{
|
||||
result = value_t::discarded;
|
||||
}
|
||||
return result;
|
||||
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); // cppcheck-suppress[accessMoved]
|
||||
return res ? result : basic_json(value_t::discarded);
|
||||
}
|
||||
|
||||
/// @brief create a JSON value from an input in MessagePack format
|
||||
@@ -4540,11 +4531,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
basic_json result;
|
||||
auto ia = detail::input_adapter(std::forward<InputType>(i));
|
||||
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
||||
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict)) // cppcheck-suppress[accessMoved]
|
||||
{
|
||||
result = value_t::discarded;
|
||||
}
|
||||
return result;
|
||||
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict); // cppcheck-suppress[accessMoved]
|
||||
return res ? result : basic_json(value_t::discarded);
|
||||
}
|
||||
|
||||
/// @brief create a JSON value from an input in MessagePack format (iterator pair, or iterator+sentinel pair for C++20 ranges support)
|
||||
@@ -4559,11 +4547,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
basic_json result;
|
||||
auto ia = detail::input_adapter(std::move(first), std::move(last));
|
||||
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
||||
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict)) // cppcheck-suppress[accessMoved]
|
||||
{
|
||||
result = value_t::discarded;
|
||||
}
|
||||
return result;
|
||||
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict); // cppcheck-suppress[accessMoved]
|
||||
return res ? result : basic_json(value_t::discarded);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
@@ -4586,11 +4571,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
auto ia = i.get();
|
||||
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
||||
// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
|
||||
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict)) // cppcheck-suppress[accessMoved]
|
||||
{
|
||||
result = value_t::discarded;
|
||||
}
|
||||
return result;
|
||||
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict); // cppcheck-suppress[accessMoved]
|
||||
return res ? result : basic_json(value_t::discarded);
|
||||
}
|
||||
|
||||
/// @brief create a JSON value from an input in UBJSON format
|
||||
@@ -4604,11 +4586,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
basic_json result;
|
||||
auto ia = detail::input_adapter(std::forward<InputType>(i));
|
||||
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
||||
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict)) // cppcheck-suppress[accessMoved]
|
||||
{
|
||||
result = value_t::discarded;
|
||||
}
|
||||
return result;
|
||||
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict); // cppcheck-suppress[accessMoved]
|
||||
return res ? result : basic_json(value_t::discarded);
|
||||
}
|
||||
|
||||
/// @brief create a JSON value from an input in UBJSON format (iterator pair, or iterator+sentinel pair for C++20 ranges support)
|
||||
@@ -4623,11 +4602,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
basic_json result;
|
||||
auto ia = detail::input_adapter(std::move(first), std::move(last));
|
||||
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
||||
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict)) // cppcheck-suppress[accessMoved]
|
||||
{
|
||||
result = value_t::discarded;
|
||||
}
|
||||
return result;
|
||||
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict); // cppcheck-suppress[accessMoved]
|
||||
return res ? result : basic_json(value_t::discarded);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
@@ -4650,11 +4626,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
auto ia = i.get();
|
||||
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
||||
// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
|
||||
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict)) // cppcheck-suppress[accessMoved]
|
||||
{
|
||||
result = value_t::discarded;
|
||||
}
|
||||
return result;
|
||||
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict); // cppcheck-suppress[accessMoved]
|
||||
return res ? result : basic_json(value_t::discarded);
|
||||
}
|
||||
|
||||
/// @brief create a JSON value from an input in BJData format
|
||||
@@ -4668,11 +4641,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
basic_json result;
|
||||
auto ia = detail::input_adapter(std::forward<InputType>(i));
|
||||
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
||||
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict)) // cppcheck-suppress[accessMoved]
|
||||
{
|
||||
result = value_t::discarded;
|
||||
}
|
||||
return result;
|
||||
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict); // cppcheck-suppress[accessMoved]
|
||||
return res ? result : basic_json(value_t::discarded);
|
||||
}
|
||||
|
||||
/// @brief create a JSON value from an input in BJData format (iterator pair, or iterator+sentinel pair for C++20 ranges support)
|
||||
@@ -4687,11 +4657,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
basic_json result;
|
||||
auto ia = detail::input_adapter(std::move(first), std::move(last));
|
||||
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
||||
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict)) // cppcheck-suppress[accessMoved]
|
||||
{
|
||||
result = value_t::discarded;
|
||||
}
|
||||
return result;
|
||||
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict); // cppcheck-suppress[accessMoved]
|
||||
return res ? result : basic_json(value_t::discarded);
|
||||
}
|
||||
|
||||
/// @brief create a JSON value from an input in BSON format
|
||||
@@ -4705,11 +4672,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
basic_json result;
|
||||
auto ia = detail::input_adapter(std::forward<InputType>(i));
|
||||
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
||||
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict)) // cppcheck-suppress[accessMoved]
|
||||
{
|
||||
result = value_t::discarded;
|
||||
}
|
||||
return result;
|
||||
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict); // cppcheck-suppress[accessMoved]
|
||||
return res ? result : basic_json(value_t::discarded);
|
||||
}
|
||||
|
||||
/// @brief create a JSON value from an input in BSON format (iterator pair, or iterator+sentinel pair for C++20 ranges support)
|
||||
@@ -4724,11 +4688,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
basic_json result;
|
||||
auto ia = detail::input_adapter(std::move(first), std::move(last));
|
||||
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
||||
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict)) // cppcheck-suppress[accessMoved]
|
||||
{
|
||||
result = value_t::discarded;
|
||||
}
|
||||
return result;
|
||||
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict); // cppcheck-suppress[accessMoved]
|
||||
return res ? result : basic_json(value_t::discarded);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
@@ -4751,11 +4712,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
auto ia = i.get();
|
||||
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
||||
// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
|
||||
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict)) // cppcheck-suppress[accessMoved]
|
||||
{
|
||||
result = value_t::discarded;
|
||||
}
|
||||
return result;
|
||||
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict); // cppcheck-suppress[accessMoved]
|
||||
return res ? result : basic_json(value_t::discarded);
|
||||
}
|
||||
/// @}
|
||||
|
||||
|
||||
@@ -11683,21 +11683,23 @@ class binary_reader
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief reads a definite-length CBOR string
|
||||
@brief reads a CBOR string
|
||||
|
||||
Reads everything @ref get_cbor_string accepts except the indefinite-length
|
||||
form, which that function handles itself. The bytes are appended to @a
|
||||
result, so consecutive chunks of an indefinite-length string can be read
|
||||
into the same string.
|
||||
This function first reads starting bytes to determine the expected
|
||||
string length and then copies this number of bytes into a string.
|
||||
Additionally, CBOR's strings with indefinite lengths are supported.
|
||||
|
||||
@param[out] result string the bytes are appended to
|
||||
@param[out] result created string
|
||||
|
||||
@return whether string creation completed
|
||||
|
||||
@pre @a current is not EOF
|
||||
*/
|
||||
bool get_cbor_string_chunk(string_t& result)
|
||||
bool get_cbor_string(string_t& result)
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string")))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (current)
|
||||
{
|
||||
// UTF-8 string (0x00..0x17 bytes follow)
|
||||
@@ -11753,6 +11755,20 @@ class binary_reader
|
||||
return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
|
||||
}
|
||||
|
||||
case 0x7F: // UTF-8 string (indefinite length)
|
||||
{
|
||||
while (get() != 0xFF)
|
||||
{
|
||||
string_t chunk;
|
||||
if (!get_cbor_string(chunk))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
result.append(chunk);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
auto last_token = get_token_string();
|
||||
@@ -11763,82 +11779,23 @@ class binary_reader
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief reads a CBOR string
|
||||
@brief reads a CBOR byte array
|
||||
|
||||
This function first reads starting bytes to determine the expected
|
||||
string length and then copies this number of bytes into a string.
|
||||
Additionally, CBOR's strings with indefinite lengths are supported.
|
||||
byte array length and then copies this number of bytes into the byte array.
|
||||
Additionally, CBOR's byte arrays with indefinite lengths are supported.
|
||||
|
||||
@param[out] result created string
|
||||
|
||||
@return whether string creation completed
|
||||
*/
|
||||
bool get_cbor_string(string_t& result)
|
||||
{
|
||||
// number of indefinite-length strings that have been opened and not
|
||||
// closed yet. RFC 8949, Section 3.2.3 does not permit nesting them,
|
||||
// but this reader has always accepted it, so the open levels are
|
||||
// counted instead of recursed through, which overflowed the stack for
|
||||
// an input of repeated 0x7F bytes (see #5104). Every chunk is appended
|
||||
// to the same result, so no per-level state is needed.
|
||||
std::size_t open = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string")))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (current == 0x7F) // UTF-8 string (indefinite length)
|
||||
{
|
||||
++open;
|
||||
get();
|
||||
continue;
|
||||
}
|
||||
|
||||
// a break marker closes the innermost indefinite-length string;
|
||||
// outside of one it is not a string and falls through to the error
|
||||
if (open != 0 && current == 0xFF)
|
||||
{
|
||||
if (--open == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
get();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (JSON_HEDLEY_UNLIKELY(!get_cbor_string_chunk(result)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (open == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
get();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief reads a definite-length CBOR byte array
|
||||
|
||||
Reads everything @ref get_cbor_binary accepts except the indefinite-length
|
||||
form, which that function handles itself. The bytes are appended to @a
|
||||
result, so consecutive chunks of an indefinite-length byte array can be
|
||||
read into the same byte array.
|
||||
|
||||
@param[out] result byte array the bytes are appended to
|
||||
@param[out] result created byte array
|
||||
|
||||
@return whether byte array creation completed
|
||||
|
||||
@pre @a current is not EOF
|
||||
*/
|
||||
bool get_cbor_binary_chunk(binary_t& result)
|
||||
bool get_cbor_binary(binary_t& result)
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "binary")))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (current)
|
||||
{
|
||||
// Binary data (0x00..0x17 bytes follow)
|
||||
@@ -11898,6 +11855,20 @@ class binary_reader
|
||||
get_binary(input_format_t::cbor, len, result);
|
||||
}
|
||||
|
||||
case 0x5F: // Binary data (indefinite length)
|
||||
{
|
||||
while (get() != 0xFF)
|
||||
{
|
||||
binary_t chunk;
|
||||
if (!get_cbor_binary(chunk))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
result.insert(result.end(), chunk.begin(), chunk.end());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
auto last_token = get_token_string();
|
||||
@@ -11907,63 +11878,6 @@ class binary_reader
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief reads a CBOR byte array
|
||||
|
||||
This function first reads starting bytes to determine the expected
|
||||
byte array length and then copies this number of bytes into the byte array.
|
||||
Additionally, CBOR's byte arrays with indefinite lengths are supported.
|
||||
|
||||
@param[out] result created byte array
|
||||
|
||||
@return whether byte array creation completed
|
||||
*/
|
||||
bool get_cbor_binary(binary_t& result)
|
||||
{
|
||||
// the open indefinite-length byte arrays are counted rather than
|
||||
// recursed through, for the reason given in @ref get_cbor_string
|
||||
std::size_t open = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "binary")))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (current == 0x5F) // Binary data (indefinite length)
|
||||
{
|
||||
++open;
|
||||
get();
|
||||
continue;
|
||||
}
|
||||
|
||||
// a break marker closes the innermost indefinite-length byte
|
||||
// array; outside of one it falls through to the error below
|
||||
if (open != 0 && current == 0xFF)
|
||||
{
|
||||
if (--open == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
get();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (JSON_HEDLEY_UNLIKELY(!get_cbor_binary_chunk(result)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (open == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
get();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief narrow a definite CBOR array/map length to std::size_t
|
||||
|
||||
@@ -25987,11 +25901,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
basic_json result;
|
||||
auto ia = detail::input_adapter(std::forward<InputType>(i));
|
||||
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
||||
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler)) // cppcheck-suppress[accessMoved]
|
||||
{
|
||||
result = value_t::discarded;
|
||||
}
|
||||
return result;
|
||||
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); // cppcheck-suppress[accessMoved]
|
||||
return res ? result : basic_json(value_t::discarded);
|
||||
}
|
||||
|
||||
/// @brief create a JSON value from an input in CBOR format (iterator pair, or iterator+sentinel pair for C++20 ranges support)
|
||||
@@ -26007,11 +25918,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
basic_json result;
|
||||
auto ia = detail::input_adapter(std::move(first), std::move(last));
|
||||
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
||||
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler)) // cppcheck-suppress[accessMoved]
|
||||
{
|
||||
result = value_t::discarded;
|
||||
}
|
||||
return result;
|
||||
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); // cppcheck-suppress[accessMoved]
|
||||
return res ? result : basic_json(value_t::discarded);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
@@ -26036,11 +25944,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
auto ia = i.get();
|
||||
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
||||
// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
|
||||
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler)) // cppcheck-suppress[accessMoved]
|
||||
{
|
||||
result = value_t::discarded;
|
||||
}
|
||||
return result;
|
||||
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); // cppcheck-suppress[accessMoved]
|
||||
return res ? result : basic_json(value_t::discarded);
|
||||
}
|
||||
|
||||
/// @brief create a JSON value from an input in MessagePack format
|
||||
@@ -26054,11 +25959,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
basic_json result;
|
||||
auto ia = detail::input_adapter(std::forward<InputType>(i));
|
||||
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
||||
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict)) // cppcheck-suppress[accessMoved]
|
||||
{
|
||||
result = value_t::discarded;
|
||||
}
|
||||
return result;
|
||||
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict); // cppcheck-suppress[accessMoved]
|
||||
return res ? result : basic_json(value_t::discarded);
|
||||
}
|
||||
|
||||
/// @brief create a JSON value from an input in MessagePack format (iterator pair, or iterator+sentinel pair for C++20 ranges support)
|
||||
@@ -26073,11 +25975,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
basic_json result;
|
||||
auto ia = detail::input_adapter(std::move(first), std::move(last));
|
||||
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
||||
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict)) // cppcheck-suppress[accessMoved]
|
||||
{
|
||||
result = value_t::discarded;
|
||||
}
|
||||
return result;
|
||||
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict); // cppcheck-suppress[accessMoved]
|
||||
return res ? result : basic_json(value_t::discarded);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
@@ -26100,11 +25999,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
auto ia = i.get();
|
||||
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
||||
// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
|
||||
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict)) // cppcheck-suppress[accessMoved]
|
||||
{
|
||||
result = value_t::discarded;
|
||||
}
|
||||
return result;
|
||||
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict); // cppcheck-suppress[accessMoved]
|
||||
return res ? result : basic_json(value_t::discarded);
|
||||
}
|
||||
|
||||
/// @brief create a JSON value from an input in UBJSON format
|
||||
@@ -26118,11 +26014,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
basic_json result;
|
||||
auto ia = detail::input_adapter(std::forward<InputType>(i));
|
||||
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
||||
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict)) // cppcheck-suppress[accessMoved]
|
||||
{
|
||||
result = value_t::discarded;
|
||||
}
|
||||
return result;
|
||||
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict); // cppcheck-suppress[accessMoved]
|
||||
return res ? result : basic_json(value_t::discarded);
|
||||
}
|
||||
|
||||
/// @brief create a JSON value from an input in UBJSON format (iterator pair, or iterator+sentinel pair for C++20 ranges support)
|
||||
@@ -26137,11 +26030,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
basic_json result;
|
||||
auto ia = detail::input_adapter(std::move(first), std::move(last));
|
||||
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
||||
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict)) // cppcheck-suppress[accessMoved]
|
||||
{
|
||||
result = value_t::discarded;
|
||||
}
|
||||
return result;
|
||||
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict); // cppcheck-suppress[accessMoved]
|
||||
return res ? result : basic_json(value_t::discarded);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
@@ -26164,11 +26054,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
auto ia = i.get();
|
||||
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
||||
// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
|
||||
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict)) // cppcheck-suppress[accessMoved]
|
||||
{
|
||||
result = value_t::discarded;
|
||||
}
|
||||
return result;
|
||||
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict); // cppcheck-suppress[accessMoved]
|
||||
return res ? result : basic_json(value_t::discarded);
|
||||
}
|
||||
|
||||
/// @brief create a JSON value from an input in BJData format
|
||||
@@ -26182,11 +26069,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
basic_json result;
|
||||
auto ia = detail::input_adapter(std::forward<InputType>(i));
|
||||
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
||||
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict)) // cppcheck-suppress[accessMoved]
|
||||
{
|
||||
result = value_t::discarded;
|
||||
}
|
||||
return result;
|
||||
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict); // cppcheck-suppress[accessMoved]
|
||||
return res ? result : basic_json(value_t::discarded);
|
||||
}
|
||||
|
||||
/// @brief create a JSON value from an input in BJData format (iterator pair, or iterator+sentinel pair for C++20 ranges support)
|
||||
@@ -26201,11 +26085,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
basic_json result;
|
||||
auto ia = detail::input_adapter(std::move(first), std::move(last));
|
||||
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
||||
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict)) // cppcheck-suppress[accessMoved]
|
||||
{
|
||||
result = value_t::discarded;
|
||||
}
|
||||
return result;
|
||||
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict); // cppcheck-suppress[accessMoved]
|
||||
return res ? result : basic_json(value_t::discarded);
|
||||
}
|
||||
|
||||
/// @brief create a JSON value from an input in BSON format
|
||||
@@ -26219,11 +26100,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
basic_json result;
|
||||
auto ia = detail::input_adapter(std::forward<InputType>(i));
|
||||
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
||||
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict)) // cppcheck-suppress[accessMoved]
|
||||
{
|
||||
result = value_t::discarded;
|
||||
}
|
||||
return result;
|
||||
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict); // cppcheck-suppress[accessMoved]
|
||||
return res ? result : basic_json(value_t::discarded);
|
||||
}
|
||||
|
||||
/// @brief create a JSON value from an input in BSON format (iterator pair, or iterator+sentinel pair for C++20 ranges support)
|
||||
@@ -26238,11 +26116,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
basic_json result;
|
||||
auto ia = detail::input_adapter(std::move(first), std::move(last));
|
||||
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
||||
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict)) // cppcheck-suppress[accessMoved]
|
||||
{
|
||||
result = value_t::discarded;
|
||||
}
|
||||
return result;
|
||||
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict); // cppcheck-suppress[accessMoved]
|
||||
return res ? result : basic_json(value_t::discarded);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
@@ -26265,11 +26140,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
auto ia = i.get();
|
||||
detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
|
||||
// NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
|
||||
if (!binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict)) // cppcheck-suppress[accessMoved]
|
||||
{
|
||||
result = value_t::discarded;
|
||||
}
|
||||
return result;
|
||||
const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict); // cppcheck-suppress[accessMoved]
|
||||
return res ? result : basic_json(value_t::discarded);
|
||||
}
|
||||
/// @}
|
||||
|
||||
|
||||
@@ -2035,58 +2035,6 @@ TEST_CASE("CBOR definite length equal to the indefinite-length sentinel")
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("CBOR indefinite-length strings do not recurse per chunk")
|
||||
{
|
||||
// Reading an indefinite-length string or byte array used to call itself
|
||||
// once per chunk, so a payload of repeated 0x7F (or 0x5F) bytes exhausted
|
||||
// the call stack before any of the input was rejected. The open levels are
|
||||
// counted now, and the levels below prove the reader still reads the same
|
||||
// values and reports the same errors at the same byte offsets.
|
||||
json _;
|
||||
|
||||
SECTION("many open levels are reported, not crashed on")
|
||||
{
|
||||
const std::vector<uint8_t> input(200000, 0x7F);
|
||||
CHECK_THROWS_WITH_AS(_ = json::from_cbor(input), "[json.exception.parse_error.110] parse error at byte 200001: syntax error while parsing CBOR string: unexpected end of input", json::parse_error&);
|
||||
CHECK(json::from_cbor(input, true, false).is_discarded());
|
||||
}
|
||||
|
||||
SECTION("many open levels are reported, not crashed on (binary)")
|
||||
{
|
||||
const std::vector<uint8_t> input(200000, 0x5F);
|
||||
CHECK_THROWS_WITH_AS(_ = json::from_cbor(input), "[json.exception.parse_error.110] parse error at byte 200001: syntax error while parsing CBOR binary: unexpected end of input", json::parse_error&);
|
||||
CHECK(json::from_cbor(input, true, false).is_discarded());
|
||||
}
|
||||
|
||||
SECTION("chunks are still concatenated")
|
||||
{
|
||||
CHECK(json::from_cbor(std::vector<uint8_t>({0x7F, 0xFF})) == json(""));
|
||||
CHECK(json::from_cbor(std::vector<uint8_t>({0x7F, 0x61, 0x61, 0xFF})) == json("a"));
|
||||
// nested indefinite-length strings are concatenated across levels
|
||||
CHECK(json::from_cbor(std::vector<uint8_t>({0x7F, 0x7F, 0x61, 0x61, 0xFF, 0x61, 0x62, 0xFF})) == json("ab"));
|
||||
CHECK(json::from_cbor(std::vector<uint8_t>({0x7F, 0x7F, 0x7F, 0x61, 0x7A, 0xFF, 0xFF, 0xFF})) == json("z"));
|
||||
CHECK(json::from_cbor(std::vector<uint8_t>({0xA1, 0x7F, 0x61, 0x61, 0xFF, 0x01})) == json({{"a", 1}}));
|
||||
}
|
||||
|
||||
SECTION("chunks are still concatenated (binary)")
|
||||
{
|
||||
CHECK(json::from_cbor(std::vector<uint8_t>({0x5F, 0x41, 0x61, 0xFF})) == json::binary({0x61}));
|
||||
CHECK(json::from_cbor(std::vector<uint8_t>({0x5F, 0x5F, 0x41, 0x61, 0xFF, 0x41, 0x62, 0xFF})) == json::binary({0x61, 0x62}));
|
||||
}
|
||||
|
||||
SECTION("a chunk that is not a string is still rejected")
|
||||
{
|
||||
CHECK_THROWS_WITH_AS(_ = json::from_cbor(std::vector<uint8_t>({0x7F, 0x7F, 0x00})), "[json.exception.parse_error.113] parse error at byte 3: syntax error while parsing CBOR string: expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x00", json::parse_error&);
|
||||
CHECK_THROWS_WITH_AS(_ = json::from_cbor(std::vector<uint8_t>({0x5F, 0x5F, 0x00})), "[json.exception.parse_error.113] parse error at byte 3: syntax error while parsing CBOR binary: expected length specification (0x40-0x5B) or indefinite binary array type (0x5F); last byte: 0x00", json::parse_error&);
|
||||
}
|
||||
|
||||
SECTION("a break marker outside an indefinite-length string is not a string")
|
||||
{
|
||||
// 0xFF only closes a string that was opened; on its own it is not one
|
||||
CHECK_THROWS_WITH_AS(_ = json::from_cbor(std::vector<uint8_t>({0xA1, 0xFF, 0x01})), "[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing CBOR string: expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0xFF", json::parse_error&);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("CBOR roundtrips" * doctest::skip())
|
||||
{
|
||||
SECTION("input from flynn")
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
// __ _____ _____ _____
|
||||
// __| | __| | | | JSON for Modern C++ (supporting code)
|
||||
// | | |__ | | | | | | version 3.12.0
|
||||
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
// This file contains the C++17-only part of unit-items.cpp (structured
|
||||
// bindings support for json::items()). It is kept in a separate
|
||||
// translation unit so the (much larger) unit-items.cpp does not need to
|
||||
// be compiled a second time just for this one SECTION.
|
||||
|
||||
#include "doctest_compatibility.h"
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
using nlohmann::json;
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
TEST_CASE("items()")
|
||||
{
|
||||
SECTION("object")
|
||||
{
|
||||
SECTION("structured bindings")
|
||||
{
|
||||
json j = { {"A", 1}, {"B", 2} };
|
||||
|
||||
std::map<std::string, int> m;
|
||||
|
||||
for (auto const&[key, value] : j.items())
|
||||
{
|
||||
m.emplace(key, value);
|
||||
}
|
||||
|
||||
CHECK(j.get<decltype(m)>() == m);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -862,22 +862,6 @@ TEST_CASE("items()")
|
||||
|
||||
CHECK(counter == 3);
|
||||
}
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
SECTION("structured bindings")
|
||||
{
|
||||
json j = { {"A", 1}, {"B", 2} };
|
||||
|
||||
std::map<std::string, int> m;
|
||||
|
||||
for (auto const&[key, value] : j.items())
|
||||
{
|
||||
m.emplace(key, value);
|
||||
}
|
||||
|
||||
CHECK(j.get<decltype(m)>() == m);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("const object")
|
||||
|
||||
@@ -30,10 +30,6 @@ using nlohmann::json;
|
||||
#include <cstdio>
|
||||
#include "make_test_data_available.hpp"
|
||||
|
||||
#ifdef JSON_HAS_CPP_17
|
||||
#include <variant>
|
||||
#endif
|
||||
|
||||
#include "fifo_map.hpp"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
Reference in New Issue
Block a user