diff --git a/include/nlohmann/detail/input/binary_reader.hpp b/include/nlohmann/detail/input/binary_reader.hpp index 234017f7d..655c30f21 100644 --- a/include/nlohmann/detail/input/binary_reader.hpp +++ b/include/nlohmann/detail/input/binary_reader.hpp @@ -2434,11 +2434,17 @@ class binary_reader case 0xFD: return sax->number_float(1.0, ""); - default: // anything else + case 0xFE: { auto last_token = get_token_string(); return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::bon8, "invalid byte: 0x" + last_token, "value"), BasicJsonType())); } + + default: + { + string_t s; + return get_bon8_string(s) && sax->string(s); + } } } @@ -2475,7 +2481,97 @@ class binary_reader bool get_bon8_object(const std::size_t len) { - return false; + if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len))) + { + return false; + } + + if (len != 0) + { + string_t key; + if (len != std::size_t(-1)) + { + for (std::size_t i = 0; i < len; ++i) + { + get(); + if (JSON_HEDLEY_UNLIKELY(!get_bon8_string(key) || !sax->key(key))) + { + return false; + } + + if (JSON_HEDLEY_UNLIKELY(!parse_bon8_internal(false))) + { + return false; + } + key.clear(); + } + } + else + { + while (get() != 0xFE) + { + if (JSON_HEDLEY_UNLIKELY(!get_bon8_string(key) || !sax->key(key))) + { + return false; + } + + if (JSON_HEDLEY_UNLIKELY(!parse_bon8_internal(false))) + { + return false; + } + key.clear(); + } + } + } + + return sax->end_object(); + } + + bool get_bon8_string(string_t& result) + { + while (true) + { + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bon8, "string"))) + { + return false; + } + + if ((current & 0x80) == 0x00) + { + result.push_back(static_cast(current)); + get(); + } + else if ((current & 0xE0) == 0xC0) + { + result.push_back(static_cast(current)); + result.push_back(static_cast(get())); + get(); + } + else if ((current & 0xF0) == 0xE0) + { + result.push_back(static_cast(current)); + result.push_back(static_cast(get())); + result.push_back(static_cast(get())); + get(); + } + else if ((current & 0xF8) == 0xF0) + { + result.push_back(static_cast(current)); + result.push_back(static_cast(get())); + result.push_back(static_cast(get())); + result.push_back(static_cast(get())); + get(); + } + else if (current == 0xFF) + { + get(); + return true; + } + else + { + return true; + } + } } /////////////////////// diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 2cea5f013..af4c3caa0 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -10728,11 +10728,17 @@ class binary_reader case 0xFD: return sax->number_float(1.0, ""); - default: // anything else + case 0xFE: { auto last_token = get_token_string(); return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::bon8, "invalid byte: 0x" + last_token, "value"), BasicJsonType())); } + + default: + { + string_t s; + return get_bon8_string(s) && sax->string(s); + } } } @@ -10769,7 +10775,97 @@ class binary_reader bool get_bon8_object(const std::size_t len) { - return false; + if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len))) + { + return false; + } + + if (len != 0) + { + string_t key; + if (len != std::size_t(-1)) + { + for (std::size_t i = 0; i < len; ++i) + { + get(); + if (JSON_HEDLEY_UNLIKELY(!get_bon8_string(key) || !sax->key(key))) + { + return false; + } + + if (JSON_HEDLEY_UNLIKELY(!parse_bon8_internal(false))) + { + return false; + } + key.clear(); + } + } + else + { + while (get() != 0xFE) + { + if (JSON_HEDLEY_UNLIKELY(!get_bon8_string(key) || !sax->key(key))) + { + return false; + } + + if (JSON_HEDLEY_UNLIKELY(!parse_bon8_internal(false))) + { + return false; + } + key.clear(); + } + } + } + + return sax->end_object(); + } + + bool get_bon8_string(string_t& result) + { + while (true) + { + if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bon8, "string"))) + { + return false; + } + + if ((current & 0x80) == 0x00) + { + result.push_back(static_cast(current)); + get(); + } + else if ((current & 0xE0) == 0xC0) + { + result.push_back(static_cast(current)); + result.push_back(static_cast(get())); + get(); + } + else if ((current & 0xF0) == 0xE0) + { + result.push_back(static_cast(current)); + result.push_back(static_cast(get())); + result.push_back(static_cast(get())); + get(); + } + else if ((current & 0xF8) == 0xF0) + { + result.push_back(static_cast(current)); + result.push_back(static_cast(get())); + result.push_back(static_cast(get())); + result.push_back(static_cast(get())); + get(); + } + else if (current == 0xFF) + { + get(); + return true; + } + else + { + return true; + } + } } /////////////////////// diff --git a/test/src/unit-bon8.cpp b/test/src/unit-bon8.cpp index 1858e05b9..471deeb2d 100644 --- a/test/src/unit-bon8.cpp +++ b/test/src/unit-bon8.cpp @@ -552,6 +552,7 @@ TEST_CASE("BON8") std::vector expected = {0xFF}; const auto result = json::to_bon8(j); CHECK(result == expected); + CHECK(json::from_bon8(result) == j); } SECTION("other strings") @@ -560,6 +561,7 @@ TEST_CASE("BON8") std::vector expected = {'T', 'h', 'i', 's', ' ', 'i', 's', ' ', 'a', ' ', 's', 't', 'r', 'i', 'n', 'g', '.', 0xFF}; const auto result = json::to_bon8(j); CHECK(result == expected); + CHECK(json::from_bon8(result) == j); } } @@ -634,6 +636,7 @@ TEST_CASE("BON8") std::vector expected = {0x81, 0x81, 0x81, 'f', 'o', 'o', 0xFF}; const auto result = json::to_bon8(j); CHECK(result == expected); + CHECK(json::from_bon8(result) == j); } SECTION("[[[1]]]") @@ -651,6 +654,7 @@ TEST_CASE("BON8") std::vector expected = {0x81, 0x81, 0x81, 0xFF}; const auto result = json::to_bon8(j); CHECK(result == expected); + CHECK(json::from_bon8(result) == j); } } @@ -677,6 +681,7 @@ TEST_CASE("BON8") std::vector expected = {0x86}; const auto result = json::to_bon8(j); CHECK(result == expected); + CHECK(json::from_bon8(result) == j); } SECTION("{\"foo\": null}") @@ -685,6 +690,7 @@ TEST_CASE("BON8") std::vector expected = {0x87, 'f', 'o', 'o', 0xFA}; const auto result = json::to_bon8(j); CHECK(result == expected); + CHECK(json::from_bon8(result) == j); } SECTION("{\"\": true, \"foo\": null}") @@ -693,6 +699,7 @@ TEST_CASE("BON8") std::vector expected = {0x88, 0xFF, 0xF9, 'f', 'o', 'o', 0xFA}; const auto result = json::to_bon8(j); CHECK(result == expected); + CHECK(json::from_bon8(result) == j); } SECTION("{\"a\": \"\", \"c\": \"d\"}") @@ -720,6 +727,7 @@ TEST_CASE("BON8") std::vector expected = {0x8b, 'f', 'i', 'v', 'e', 0x95, 'f', 'o', 'u', 'r', 0x94, 'o', 'n', 'e', 0x91, 't', 'h', 'r', 'e', 'e', 0x93, 't', 'w', 'o', 0x92, 0xFE}; const auto result = json::to_bon8(j); CHECK(result == expected); + CHECK(json::from_bon8(result) == j); } } }