diff --git a/include/nlohmann/detail/input/binary_reader.hpp b/include/nlohmann/detail/input/binary_reader.hpp index f5e1cc34..429502ea 100644 --- a/include/nlohmann/detail/input/binary_reader.hpp +++ b/include/nlohmann/detail/input/binary_reader.hpp @@ -41,6 +41,9 @@ class binary_reader using json_sax_t = json_sax; public: + /// the supported binary input formats + enum class binary_format_t { cbor, msgpack, ubjson }; + /*! @brief create a binary reader @@ -52,77 +55,50 @@ class binary_reader } /*! - @brief create a JSON value from CBOR input - + @param[in] format the binary format to parse + @param[in] sax_ a SAX event processor @param[in] strict whether to expect the input to be consumed completed - @return JSON value created from CBOR input - @throw parse_error.110 if input ended unexpectedly or the end of file was - not reached when @a strict was set to true - @throw parse_error.112 if unsupported byte was read + @return */ - BasicJsonType parse_cbor(const bool strict) + bool sax_parse(const binary_format_t format, json_sax_t* sax_, const bool strict) { - BasicJsonType result; - json_sax_dom_parser sdp(result); - sax = &sdp; - parse_cbor_internal(); - result.assert_invariant(); - if (strict) + sax = sax_; + bool result; + + switch (format) { - get(); - expect_eof(); + case binary_format_t::cbor: + result = parse_cbor_internal(); + break; + + case binary_format_t::msgpack: + result = parse_msgpack_internal(); + break; + + case binary_format_t::ubjson: + result = parse_ubjson_internal(); + break; } - return result; - } - /*! - @brief create a JSON value from MessagePack input - - @param[in] strict whether to expect the input to be consumed completed - @return JSON value created from MessagePack input - - @throw parse_error.110 if input ended unexpectedly or the end of file was - not reached when @a strict was set to true - @throw parse_error.112 if unsupported byte was read - */ - BasicJsonType parse_msgpack(const bool strict) - { - BasicJsonType result; - json_sax_dom_parser sdp(result); - sax = &sdp; - parse_msgpack_internal(); - result.assert_invariant(); - if (strict) + // strict mode: next byte must be EOF + if (result and strict) { - get(); - expect_eof(); + if (format == binary_format_t::ubjson) + { + get_ignore_noop(); + } + else + { + get(); + } + + if (JSON_UNLIKELY(current != std::char_traits::eof())) + { + return sax->parse_error(chars_read, get_token_string(), parse_error::create(110, chars_read, "expected end of input")); + } } - return result; - } - /*! - @brief create a JSON value from UBJSON input - - @param[in] strict whether to expect the input to be consumed completed - @return JSON value created from UBJSON input - - @throw parse_error.110 if input ended unexpectedly or the end of file was - not reached when @a strict was set to true - @throw parse_error.112 if unsupported byte was read - */ - BasicJsonType parse_ubjson(const bool strict) - { - BasicJsonType result; - json_sax_dom_parser sdp(result); - sax = &sdp; - parse_ubjson_internal(); - result.assert_invariant(); - if (strict) - { - get_ignore_noop(); - expect_eof(); - } return result; } @@ -1662,18 +1638,6 @@ class binary_reader return sax->end_object(); } - /*! - @return whether input was completely read - */ - bool expect_eof() const - { - if (JSON_UNLIKELY(current != std::char_traits::eof())) - { - return sax->parse_error(chars_read, get_token_string(), parse_error::create(110, chars_read, "expected end of input")); - } - return true; - } - /*! @return whether the last read character is not EOF */ diff --git a/include/nlohmann/json.hpp b/include/nlohmann/json.hpp index bdc905f1..393fa2ea 100644 --- a/include/nlohmann/json.hpp +++ b/include/nlohmann/json.hpp @@ -6611,6 +6611,9 @@ class basic_json @param[in] i an input in CBOR format convertible to an input adapter @param[in] strict whether to expect the input to be consumed until EOF (true by default) + @param[in] allow_exceptions whether to throw exceptions in case of a + parse error (optional, true by default) + @return deserialized JSON value @throw parse_error.110 if the given input ends prematurely or the end of @@ -6636,9 +6639,13 @@ class basic_json @a strict parameter since 3.0.0 */ static basic_json from_cbor(detail::input_adapter i, - const bool strict = true) + const bool strict = true, + const bool allow_exceptions = true) { - return binary_reader(i).parse_cbor(strict); + basic_json result; + detail::json_sax_dom_parser sdp(result, allow_exceptions); + const bool res = binary_reader(detail::input_adapter(i)).sax_parse(binary_reader::binary_format_t::cbor, &sdp, strict); + return res ? result : basic_json(value_t::discarded); } /*! @@ -6646,9 +6653,14 @@ class basic_json */ template::value, int> = 0> - static basic_json from_cbor(A1 && a1, A2 && a2, const bool strict = true) + static basic_json from_cbor(A1 && a1, A2 && a2, + const bool strict = true, + const bool allow_exceptions = true) { - return binary_reader(detail::input_adapter(std::forward(a1), std::forward(a2))).parse_cbor(strict); + basic_json result; + detail::json_sax_dom_parser sdp(result, allow_exceptions); + const bool res = binary_reader(detail::input_adapter(std::forward(a1), std::forward(a2))).sax_parse(binary_reader::binary_format_t::cbor, &sdp, strict); + return res ? result : basic_json(value_t::discarded); } /*! @@ -6701,6 +6713,10 @@ class basic_json adapter @param[in] strict whether to expect the input to be consumed until EOF (true by default) + @param[in] allow_exceptions whether to throw exceptions in case of a + parse error (optional, true by default) + + @return deserialized JSON value @throw parse_error.110 if the given input ends prematurely or the end of file was not reached when @a strict was set to true @@ -6725,9 +6741,13 @@ class basic_json @a strict parameter since 3.0.0 */ static basic_json from_msgpack(detail::input_adapter i, - const bool strict = true) + const bool strict = true, + const bool allow_exceptions = true) { - return binary_reader(i).parse_msgpack(strict); + basic_json result; + detail::json_sax_dom_parser sdp(result, allow_exceptions); + const bool res = binary_reader(detail::input_adapter(i)).sax_parse(binary_reader::binary_format_t::msgpack, &sdp, strict); + return res ? result : basic_json(value_t::discarded); } /*! @@ -6735,9 +6755,14 @@ class basic_json */ template::value, int> = 0> - static basic_json from_msgpack(A1 && a1, A2 && a2, const bool strict = true) + static basic_json from_msgpack(A1 && a1, A2 && a2, + const bool strict = true, + const bool allow_exceptions = true) { - return binary_reader(detail::input_adapter(std::forward(a1), std::forward(a2))).parse_msgpack(strict); + basic_json result; + detail::json_sax_dom_parser sdp(result, allow_exceptions); + const bool res = binary_reader(detail::input_adapter(std::forward(a1), std::forward(a2))).sax_parse(binary_reader::binary_format_t::msgpack, &sdp, strict); + return res ? result : basic_json(value_t::discarded); } /*! @@ -6772,6 +6797,10 @@ class basic_json @param[in] i an input in UBJSON format convertible to an input adapter @param[in] strict whether to expect the input to be consumed until EOF (true by default) + @param[in] allow_exceptions whether to throw exceptions in case of a + parse error (optional, true by default) + + @return deserialized JSON value @throw parse_error.110 if the given input ends prematurely or the end of file was not reached when @a strict was set to true @@ -6794,16 +6823,25 @@ class basic_json @since version 3.1.0 */ static basic_json from_ubjson(detail::input_adapter i, - const bool strict = true) + const bool strict = true, + const bool allow_exceptions = true) { - return binary_reader(i).parse_ubjson(strict); + basic_json result; + detail::json_sax_dom_parser sdp(result, allow_exceptions); + const bool res = binary_reader(detail::input_adapter(i)).sax_parse(binary_reader::binary_format_t::ubjson, &sdp, strict); + return res ? result : basic_json(value_t::discarded); } template::value, int> = 0> - static basic_json from_ubjson(A1 && a1, A2 && a2, const bool strict = true) + static basic_json from_ubjson(A1 && a1, A2 && a2, + const bool strict = true, + const bool allow_exceptions = true) { - return binary_reader(detail::input_adapter(std::forward(a1), std::forward(a2))).parse_ubjson(strict); + basic_json result; + detail::json_sax_dom_parser sdp(result, allow_exceptions); + const bool res = binary_reader(detail::input_adapter(std::forward(a1), std::forward(a2))).sax_parse(binary_reader::binary_format_t::ubjson, &sdp, strict); + return res ? result : basic_json(value_t::discarded); } /// @} diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 4d8ec2bc..ea4f1995 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -5699,6 +5699,8 @@ class binary_reader using json_sax_t = json_sax; public: + enum class binary_format_t { cbor, msgpack, ubjson }; + /*! @brief create a binary reader @@ -5710,77 +5712,50 @@ class binary_reader } /*! - @brief create a JSON value from CBOR input - + @param[in] format the binary format to parse + @param[in] sax_ a SAX event processor @param[in] strict whether to expect the input to be consumed completed - @return JSON value created from CBOR input - @throw parse_error.110 if input ended unexpectedly or the end of file was - not reached when @a strict was set to true - @throw parse_error.112 if unsupported byte was read + @return */ - BasicJsonType parse_cbor(const bool strict) + bool sax_parse(const binary_format_t format, json_sax_t* sax_, const bool strict) { - BasicJsonType result; - json_sax_dom_parser sdp(result); - sax = &sdp; - parse_cbor_internal(); - result.assert_invariant(); - if (strict) + sax = sax_; + bool result; + + switch (format) { - get(); - expect_eof(); + case binary_format_t::cbor: + result = parse_cbor_internal(); + break; + + case binary_format_t::msgpack: + result = parse_msgpack_internal(); + break; + + case binary_format_t::ubjson: + result = parse_ubjson_internal(); + break; } - return result; - } - /*! - @brief create a JSON value from MessagePack input - - @param[in] strict whether to expect the input to be consumed completed - @return JSON value created from MessagePack input - - @throw parse_error.110 if input ended unexpectedly or the end of file was - not reached when @a strict was set to true - @throw parse_error.112 if unsupported byte was read - */ - BasicJsonType parse_msgpack(const bool strict) - { - BasicJsonType result; - json_sax_dom_parser sdp(result); - sax = &sdp; - parse_msgpack_internal(); - result.assert_invariant(); - if (strict) + // strict mode: next byte must be EOF + if (result and strict) { - get(); - expect_eof(); + if (format == binary_format_t::ubjson) + { + get_ignore_noop(); + } + else + { + get(); + } + + if (JSON_UNLIKELY(current != std::char_traits::eof())) + { + return sax->parse_error(chars_read, get_token_string(), parse_error::create(110, chars_read, "expected end of input")); + } } - return result; - } - /*! - @brief create a JSON value from UBJSON input - - @param[in] strict whether to expect the input to be consumed completed - @return JSON value created from UBJSON input - - @throw parse_error.110 if input ended unexpectedly or the end of file was - not reached when @a strict was set to true - @throw parse_error.112 if unsupported byte was read - */ - BasicJsonType parse_ubjson(const bool strict) - { - BasicJsonType result; - json_sax_dom_parser sdp(result); - sax = &sdp; - parse_ubjson_internal(); - result.assert_invariant(); - if (strict) - { - get_ignore_noop(); - expect_eof(); - } return result; } @@ -7320,18 +7295,6 @@ class binary_reader return sax->end_object(); } - /*! - @return whether input was completely read - */ - bool expect_eof() const - { - if (JSON_UNLIKELY(current != std::char_traits::eof())) - { - return sax->parse_error(chars_read, get_token_string(), parse_error::create(110, chars_read, "expected end of input")); - } - return true; - } - /*! @return whether the last read character is not EOF */ @@ -17392,6 +17355,9 @@ class basic_json @param[in] i an input in CBOR format convertible to an input adapter @param[in] strict whether to expect the input to be consumed until EOF (true by default) + @param[in] allow_exceptions whether to throw exceptions in case of a + parse error (optional, true by default) + @return deserialized JSON value @throw parse_error.110 if the given input ends prematurely or the end of @@ -17417,9 +17383,13 @@ class basic_json @a strict parameter since 3.0.0 */ static basic_json from_cbor(detail::input_adapter i, - const bool strict = true) + const bool strict = true, + const bool allow_exceptions = true) { - return binary_reader(i).parse_cbor(strict); + basic_json result; + detail::json_sax_dom_parser sdp(result, allow_exceptions); + const bool res = binary_reader(detail::input_adapter(i)).sax_parse(binary_reader::binary_format_t::cbor, &sdp, strict); + return res ? result : basic_json(value_t::discarded); } /*! @@ -17427,9 +17397,14 @@ class basic_json */ template::value, int> = 0> - static basic_json from_cbor(A1 && a1, A2 && a2, const bool strict = true) + static basic_json from_cbor(A1 && a1, A2 && a2, + const bool strict = true, + const bool allow_exceptions = true) { - return binary_reader(detail::input_adapter(std::forward(a1), std::forward(a2))).parse_cbor(strict); + basic_json result; + detail::json_sax_dom_parser sdp(result, allow_exceptions); + const bool res = binary_reader(detail::input_adapter(std::forward(a1), std::forward(a2))).sax_parse(binary_reader::binary_format_t::cbor, &sdp, strict); + return res ? result : basic_json(value_t::discarded); } /*! @@ -17482,6 +17457,10 @@ class basic_json adapter @param[in] strict whether to expect the input to be consumed until EOF (true by default) + @param[in] allow_exceptions whether to throw exceptions in case of a + parse error (optional, true by default) + + @return deserialized JSON value @throw parse_error.110 if the given input ends prematurely or the end of file was not reached when @a strict was set to true @@ -17506,9 +17485,13 @@ class basic_json @a strict parameter since 3.0.0 */ static basic_json from_msgpack(detail::input_adapter i, - const bool strict = true) + const bool strict = true, + const bool allow_exceptions = true) { - return binary_reader(i).parse_msgpack(strict); + basic_json result; + detail::json_sax_dom_parser sdp(result, allow_exceptions); + const bool res = binary_reader(detail::input_adapter(i)).sax_parse(binary_reader::binary_format_t::msgpack, &sdp, strict); + return res ? result : basic_json(value_t::discarded); } /*! @@ -17516,9 +17499,14 @@ class basic_json */ template::value, int> = 0> - static basic_json from_msgpack(A1 && a1, A2 && a2, const bool strict = true) + static basic_json from_msgpack(A1 && a1, A2 && a2, + const bool strict = true, + const bool allow_exceptions = true) { - return binary_reader(detail::input_adapter(std::forward(a1), std::forward(a2))).parse_msgpack(strict); + basic_json result; + detail::json_sax_dom_parser sdp(result, allow_exceptions); + const bool res = binary_reader(detail::input_adapter(std::forward(a1), std::forward(a2))).sax_parse(binary_reader::binary_format_t::msgpack, &sdp, strict); + return res ? result : basic_json(value_t::discarded); } /*! @@ -17553,6 +17541,10 @@ class basic_json @param[in] i an input in UBJSON format convertible to an input adapter @param[in] strict whether to expect the input to be consumed until EOF (true by default) + @param[in] allow_exceptions whether to throw exceptions in case of a + parse error (optional, true by default) + + @return deserialized JSON value @throw parse_error.110 if the given input ends prematurely or the end of file was not reached when @a strict was set to true @@ -17575,16 +17567,25 @@ class basic_json @since version 3.1.0 */ static basic_json from_ubjson(detail::input_adapter i, - const bool strict = true) + const bool strict = true, + const bool allow_exceptions = true) { - return binary_reader(i).parse_ubjson(strict); + basic_json result; + detail::json_sax_dom_parser sdp(result, allow_exceptions); + const bool res = binary_reader(detail::input_adapter(i)).sax_parse(binary_reader::binary_format_t::ubjson, &sdp, strict); + return res ? result : basic_json(value_t::discarded); } template::value, int> = 0> - static basic_json from_ubjson(A1 && a1, A2 && a2, const bool strict = true) + static basic_json from_ubjson(A1 && a1, A2 && a2, + const bool strict = true, + const bool allow_exceptions = true) { - return binary_reader(detail::input_adapter(std::forward(a1), std::forward(a2))).parse_ubjson(strict); + basic_json result; + detail::json_sax_dom_parser sdp(result, allow_exceptions); + const bool res = binary_reader(detail::input_adapter(std::forward(a1), std::forward(a2))).sax_parse(binary_reader::binary_format_t::ubjson, &sdp, strict); + return res ? result : basic_json(value_t::discarded); } /// @} diff --git a/test/src/unit-cbor.cpp b/test/src/unit-cbor.cpp index 6b9eac52..e8b8c6f4 100644 --- a/test/src/unit-cbor.cpp +++ b/test/src/unit-cbor.cpp @@ -54,6 +54,7 @@ TEST_CASE("CBOR") // roundtrip CHECK(json::from_cbor(result) == j); + CHECK(json::from_cbor(result, true, false) == j); } SECTION("boolean") @@ -67,6 +68,7 @@ TEST_CASE("CBOR") // roundtrip CHECK(json::from_cbor(result) == j); + CHECK(json::from_cbor(result, true, false) == j); } SECTION("false") @@ -78,6 +80,7 @@ TEST_CASE("CBOR") // roundtrip CHECK(json::from_cbor(result) == j); + CHECK(json::from_cbor(result, true, false) == j); } } @@ -142,6 +145,7 @@ TEST_CASE("CBOR") // roundtrip CHECK(json::from_cbor(result) == j); + CHECK(json::from_cbor(result, true, false) == j); } } @@ -190,6 +194,7 @@ TEST_CASE("CBOR") // roundtrip CHECK(json::from_cbor(result) == j); + CHECK(json::from_cbor(result, true, false) == j); } } @@ -225,6 +230,7 @@ TEST_CASE("CBOR") // roundtrip CHECK(json::from_cbor(result) == j); + CHECK(json::from_cbor(result, true, false) == j); } } @@ -241,6 +247,7 @@ TEST_CASE("CBOR") // roundtrip CHECK(json::from_cbor(result) == j); + CHECK(json::from_cbor(result, true, false) == j); } SECTION("-256..-24") @@ -271,6 +278,7 @@ TEST_CASE("CBOR") // roundtrip CHECK(json::from_cbor(result) == j); + CHECK(json::from_cbor(result, true, false) == j); } } @@ -300,6 +308,7 @@ TEST_CASE("CBOR") // roundtrip CHECK(json::from_cbor(result) == j); + CHECK(json::from_cbor(result, true, false) == j); } } @@ -330,6 +339,7 @@ TEST_CASE("CBOR") // roundtrip CHECK(json::from_cbor(result) == j); + CHECK(json::from_cbor(result, true, false) == j); } } @@ -362,6 +372,7 @@ TEST_CASE("CBOR") // roundtrip CHECK(json::from_cbor(result) == j); + CHECK(json::from_cbor(result, true, false) == j); } } @@ -396,6 +407,7 @@ TEST_CASE("CBOR") // roundtrip CHECK(json::from_cbor(result) == j); + CHECK(json::from_cbor(result, true, false) == j); } } @@ -438,6 +450,7 @@ TEST_CASE("CBOR") // roundtrip CHECK(json::from_cbor(result) == j); + CHECK(json::from_cbor(result, true, false) == j); } } @@ -488,6 +501,7 @@ TEST_CASE("CBOR") // roundtrip CHECK(json::from_cbor(result) == j); + CHECK(json::from_cbor(result, true, false) == j); } } @@ -555,6 +569,7 @@ TEST_CASE("CBOR") // roundtrip CHECK(json::from_cbor(result) == j); + CHECK(json::from_cbor(result, true, false) == j); } } @@ -587,6 +602,7 @@ TEST_CASE("CBOR") // roundtrip CHECK(json::from_cbor(result) == j); + CHECK(json::from_cbor(result, true, false) == j); } } @@ -620,6 +636,7 @@ TEST_CASE("CBOR") // roundtrip CHECK(json::from_cbor(result) == j); + CHECK(json::from_cbor(result, true, false) == j); } } @@ -661,6 +678,7 @@ TEST_CASE("CBOR") // roundtrip CHECK(json::from_cbor(result) == j); + CHECK(json::from_cbor(result, true, false) == j); } } @@ -710,6 +728,7 @@ TEST_CASE("CBOR") // roundtrip CHECK(json::from_cbor(result) == j); + CHECK(json::from_cbor(result, true, false) == j); } } } @@ -730,6 +749,8 @@ TEST_CASE("CBOR") // roundtrip CHECK(json::from_cbor(result) == j); CHECK(json::from_cbor(result) == v); + + CHECK(json::from_cbor(result, true, false) == j); } } @@ -742,12 +763,14 @@ TEST_CASE("CBOR") CHECK_THROWS_AS(json::from_cbor(std::vector({0xf9})), json::parse_error&); CHECK_THROWS_WITH(json::from_cbor(std::vector({0xf9})), "[json.exception.parse_error.110] parse error at 2: unexpected end of input"); + CHECK(json::from_cbor(std::vector({0xf9}), true, false).is_discarded()); } SECTION("only one byte follows") { CHECK_THROWS_AS(json::from_cbor(std::vector({0xf9, 0x7c})), json::parse_error&); CHECK_THROWS_WITH(json::from_cbor(std::vector({0xf9, 0x7c})), "[json.exception.parse_error.110] parse error at 3: unexpected end of input"); + CHECK(json::from_cbor(std::vector({0xf9, 0x7c}), true, false).is_discarded()); } } @@ -868,6 +891,7 @@ TEST_CASE("CBOR") // roundtrip CHECK(json::from_cbor(result) == j); + CHECK(json::from_cbor(result, true, false) == j); } } @@ -899,6 +923,7 @@ TEST_CASE("CBOR") // roundtrip CHECK(json::from_cbor(result) == j); + CHECK(json::from_cbor(result, true, false) == j); } } @@ -931,6 +956,7 @@ TEST_CASE("CBOR") // roundtrip CHECK(json::from_cbor(result) == j); + CHECK(json::from_cbor(result, true, false) == j); } } @@ -965,6 +991,7 @@ TEST_CASE("CBOR") // roundtrip CHECK(json::from_cbor(result) == j); + CHECK(json::from_cbor(result, true, false) == j); } } } @@ -980,6 +1007,7 @@ TEST_CASE("CBOR") // roundtrip CHECK(json::from_cbor(result) == j); + CHECK(json::from_cbor(result, true, false) == j); } SECTION("[null]") @@ -991,6 +1019,7 @@ TEST_CASE("CBOR") // roundtrip CHECK(json::from_cbor(result) == j); + CHECK(json::from_cbor(result, true, false) == j); } SECTION("[1,2,3,4,5]") @@ -1002,6 +1031,7 @@ TEST_CASE("CBOR") // roundtrip CHECK(json::from_cbor(result) == j); + CHECK(json::from_cbor(result, true, false) == j); } SECTION("[[[[]]]]") @@ -1013,6 +1043,7 @@ TEST_CASE("CBOR") // roundtrip CHECK(json::from_cbor(result) == j); + CHECK(json::from_cbor(result, true, false) == j); } SECTION("array with uint16_t elements") @@ -1027,6 +1058,7 @@ TEST_CASE("CBOR") // roundtrip CHECK(json::from_cbor(result) == j); + CHECK(json::from_cbor(result, true, false) == j); } SECTION("array with uint32_t elements") @@ -1043,6 +1075,7 @@ TEST_CASE("CBOR") // roundtrip CHECK(json::from_cbor(result) == j); + CHECK(json::from_cbor(result, true, false) == j); } /* @@ -1079,6 +1112,7 @@ TEST_CASE("CBOR") // roundtrip CHECK(json::from_cbor(result) == j); + CHECK(json::from_cbor(result, true, false) == j); } SECTION("{\"\":null}") @@ -1090,6 +1124,7 @@ TEST_CASE("CBOR") // roundtrip CHECK(json::from_cbor(result) == j); + CHECK(json::from_cbor(result, true, false) == j); } SECTION("{\"a\": {\"b\": {\"c\": {}}}}") @@ -1104,6 +1139,7 @@ TEST_CASE("CBOR") // roundtrip CHECK(json::from_cbor(result) == j); + CHECK(json::from_cbor(result, true, false) == j); } SECTION("object with uint8_t elements") @@ -1130,6 +1166,7 @@ TEST_CASE("CBOR") CHECK(result[1] == 0xff); // size byte (0xff) // roundtrip CHECK(json::from_cbor(result) == j); + CHECK(json::from_cbor(result, true, false) == j); } SECTION("object with uint16_t elements") @@ -1158,6 +1195,7 @@ TEST_CASE("CBOR") // roundtrip CHECK(json::from_cbor(result) == j); + CHECK(json::from_cbor(result, true, false) == j); } SECTION("object with uint32_t elements") @@ -1188,6 +1226,7 @@ TEST_CASE("CBOR") // roundtrip CHECK(json::from_cbor(result) == j); + CHECK(json::from_cbor(result, true, false) == j); } } } @@ -1229,6 +1268,7 @@ TEST_CASE("CBOR") CHECK_THROWS_AS(json::from_cbor(std::vector()), json::parse_error&); CHECK_THROWS_WITH(json::from_cbor(std::vector()), "[json.exception.parse_error.110] parse error at 1: unexpected end of input"); + CHECK(json::from_cbor(std::vector(), true, false).is_discarded()); } SECTION("too short byte vector") @@ -1248,6 +1288,10 @@ TEST_CASE("CBOR") CHECK_THROWS_AS(json::from_cbor(std::vector({0x1b, 0x00, 0x00, 0x00, 0x00, 0x00})), json::parse_error&); CHECK_THROWS_AS(json::from_cbor(std::vector({0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})), json::parse_error&); CHECK_THROWS_AS(json::from_cbor(std::vector({0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})), json::parse_error&); + CHECK_THROWS_AS(json::from_cbor(std::vector({0x62})), json::parse_error&); + CHECK_THROWS_AS(json::from_cbor(std::vector({0x62, 0x60})), json::parse_error&); + CHECK_THROWS_AS(json::from_cbor(std::vector({0x7F})), json::parse_error&); + CHECK_THROWS_AS(json::from_cbor(std::vector({0x7F, 0x60})), json::parse_error&); CHECK_THROWS_WITH(json::from_cbor(std::vector({0x18})), "[json.exception.parse_error.110] parse error at 2: unexpected end of input"); @@ -1279,6 +1323,34 @@ TEST_CASE("CBOR") "[json.exception.parse_error.110] parse error at 8: unexpected end of input"); CHECK_THROWS_WITH(json::from_cbor(std::vector({0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})), "[json.exception.parse_error.110] parse error at 9: unexpected end of input"); + CHECK_THROWS_WITH(json::from_cbor(std::vector({0x62})), + "[json.exception.parse_error.110] parse error at 2: unexpected end of input"); + CHECK_THROWS_WITH(json::from_cbor(std::vector({0x62, 0x60})), + "[json.exception.parse_error.110] parse error at 3: unexpected end of input"); + CHECK_THROWS_WITH(json::from_cbor(std::vector({0x7F})), + "[json.exception.parse_error.110] parse error at 2: unexpected end of input"); + CHECK_THROWS_WITH(json::from_cbor(std::vector({0x7F, 0x60})), + "[json.exception.parse_error.110] parse error at 3: unexpected end of input"); + + CHECK(json::from_cbor(std::vector({0x18}), true, false).is_discarded()); + CHECK(json::from_cbor(std::vector({0x19}), true, false).is_discarded()); + CHECK(json::from_cbor(std::vector({0x19, 0x00}), true, false).is_discarded()); + CHECK(json::from_cbor(std::vector({0x1a}), true, false).is_discarded()); + CHECK(json::from_cbor(std::vector({0x1a, 0x00}), true, false).is_discarded()); + CHECK(json::from_cbor(std::vector({0x1a, 0x00, 0x00}), true, false).is_discarded()); + CHECK(json::from_cbor(std::vector({0x1a, 0x00, 0x00, 0x00}), true, false).is_discarded()); + CHECK(json::from_cbor(std::vector({0x1b}), true, false).is_discarded()); + CHECK(json::from_cbor(std::vector({0x1b, 0x00}), true, false).is_discarded()); + CHECK(json::from_cbor(std::vector({0x1b, 0x00, 0x00}), true, false).is_discarded()); + CHECK(json::from_cbor(std::vector({0x1b, 0x00, 0x00, 0x00}), true, false).is_discarded()); + CHECK(json::from_cbor(std::vector({0x1b, 0x00, 0x00, 0x00, 0x00}), true, false).is_discarded()); + CHECK(json::from_cbor(std::vector({0x1b, 0x00, 0x00, 0x00, 0x00, 0x00}), true, false).is_discarded()); + CHECK(json::from_cbor(std::vector({0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}), true, false).is_discarded()); + CHECK(json::from_cbor(std::vector({0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}), true, false).is_discarded()); + CHECK(json::from_cbor(std::vector({0x62}), true, false).is_discarded()); + CHECK(json::from_cbor(std::vector({0x62, 0x60}), true, false).is_discarded()); + CHECK(json::from_cbor(std::vector({0x7F}), true, false).is_discarded()); + CHECK(json::from_cbor(std::vector({0x7F, 0x60}), true, false).is_discarded()); } SECTION("unsupported bytes") @@ -1288,9 +1360,12 @@ TEST_CASE("CBOR") CHECK_THROWS_AS(json::from_cbor(std::vector({0x1c})), json::parse_error&); CHECK_THROWS_WITH(json::from_cbor(std::vector({0x1c})), "[json.exception.parse_error.112] parse error at 1: error reading CBOR; last byte: 0x1C"); + CHECK(json::from_cbor(std::vector({0x1c}), true, false).is_discarded()); + CHECK_THROWS_AS(json::from_cbor(std::vector({0xf8})), json::parse_error&); CHECK_THROWS_WITH(json::from_cbor(std::vector({0xf8})), "[json.exception.parse_error.112] parse error at 1: error reading CBOR; last byte: 0xF8"); + CHECK(json::from_cbor(std::vector({0xf8}), true, false).is_discarded()); } SECTION("all unsupported bytes") @@ -1340,6 +1415,7 @@ TEST_CASE("CBOR") }) { CHECK_THROWS_AS(json::from_cbor(std::vector({static_cast(byte)})), json::parse_error&); + CHECK(json::from_cbor(std::vector({static_cast(byte)}), true, false).is_discarded()); } } } @@ -1349,6 +1425,7 @@ TEST_CASE("CBOR") CHECK_THROWS_AS(json::from_cbor(std::vector({0xa1, 0xff, 0x01})), json::parse_error&); CHECK_THROWS_WITH(json::from_cbor(std::vector({0xa1, 0xff, 0x01})), "[json.exception.parse_error.113] parse error at 2: expected a CBOR string; last byte: 0xFF"); + CHECK(json::from_cbor(std::vector({0xa1, 0xff, 0x01}), true, false).is_discarded()); } SECTION("strict mode") @@ -1358,6 +1435,7 @@ TEST_CASE("CBOR") { const auto result = json::from_cbor(vec, false); CHECK(result == json()); + CHECK(not json::from_cbor(vec, false, false).is_discarded()); } SECTION("strict mode") @@ -1365,6 +1443,7 @@ TEST_CASE("CBOR") CHECK_THROWS_AS(json::from_cbor(vec), json::parse_error&); CHECK_THROWS_WITH(json::from_cbor(vec), "[json.exception.parse_error.110] parse error at 2: expected end of input"); + CHECK(json::from_cbor(vec, true, false).is_discarded()); } } }