diff --git a/include/nlohmann/detail/input/binary_reader.hpp b/include/nlohmann/detail/input/binary_reader.hpp index 8f55e1959..0212d24c6 100644 --- a/include/nlohmann/detail/input/binary_reader.hpp +++ b/include/nlohmann/detail/input/binary_reader.hpp @@ -30,8 +30,9 @@ namespace detail /// how to treat CBOR tags enum class cbor_tag_handler_t { - error, ///< throw a parse_error exception in case of a tag - ignore ///< ignore tags + error, ///< throw a parse_error exception in case of a tag + ignore, ///< ignore tags + store ///< store tags as binary type }; /*! @@ -722,30 +723,31 @@ class binary_reader case cbor_tag_handler_t::ignore: { + // ignore binary subtype switch (current) { case 0xD8: { - std::uint8_t len{}; - get_number(input_format_t::cbor, len); + std::uint8_t subtype_to_ignore{}; + get_number(input_format_t::cbor, subtype_to_ignore); break; } case 0xD9: { - std::uint16_t len{}; - get_number(input_format_t::cbor, len); + std::uint16_t subtype_to_ignore{}; + get_number(input_format_t::cbor, subtype_to_ignore); break; } case 0xDA: { - std::uint32_t len{}; - get_number(input_format_t::cbor, len); + std::uint32_t subtype_to_ignore{}; + get_number(input_format_t::cbor, subtype_to_ignore); break; } case 0xDB: { - std::uint64_t len{}; - get_number(input_format_t::cbor, len); + std::uint64_t subtype_to_ignore{}; + get_number(input_format_t::cbor, subtype_to_ignore); break; } default: @@ -754,6 +756,47 @@ class binary_reader return parse_cbor_internal(true, tag_handler); } + case cbor_tag_handler_t::store: + { + binary_t b; + // use binary subtype and store in binary container + switch (current) + { + case 0xD8: + { + std::uint8_t subtype{}; + get_number(input_format_t::cbor, subtype); + b.set_subtype(detail::conditional_static_cast(subtype)); + break; + } + case 0xD9: + { + std::uint16_t subtype{}; + get_number(input_format_t::cbor, subtype); + b.set_subtype(detail::conditional_static_cast(subtype)); + break; + } + case 0xDA: + { + std::uint32_t subtype{}; + get_number(input_format_t::cbor, subtype); + b.set_subtype(detail::conditional_static_cast(subtype)); + break; + } + case 0xDB: + { + std::uint64_t subtype{}; + get_number(input_format_t::cbor, subtype); + b.set_subtype(detail::conditional_static_cast(subtype)); + break; + } + default: + break; + } + get(); + return get_cbor_binary(b) && sax->binary(b); + } + default: // LCOV_EXCL_LINE JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE return false; // LCOV_EXCL_LINE diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 1d69fb63f..b7304f346 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -8269,8 +8269,9 @@ namespace detail /// how to treat CBOR tags enum class cbor_tag_handler_t { - error, ///< throw a parse_error exception in case of a tag - ignore ///< ignore tags + error, ///< throw a parse_error exception in case of a tag + ignore, ///< ignore tags + store ///< store tags as binary type }; /*! @@ -8961,30 +8962,31 @@ class binary_reader case cbor_tag_handler_t::ignore: { + // ignore binary subtype switch (current) { case 0xD8: { - std::uint8_t len{}; - get_number(input_format_t::cbor, len); + std::uint8_t subtype_to_ignore{}; + get_number(input_format_t::cbor, subtype_to_ignore); break; } case 0xD9: { - std::uint16_t len{}; - get_number(input_format_t::cbor, len); + std::uint16_t subtype_to_ignore{}; + get_number(input_format_t::cbor, subtype_to_ignore); break; } case 0xDA: { - std::uint32_t len{}; - get_number(input_format_t::cbor, len); + std::uint32_t subtype_to_ignore{}; + get_number(input_format_t::cbor, subtype_to_ignore); break; } case 0xDB: { - std::uint64_t len{}; - get_number(input_format_t::cbor, len); + std::uint64_t subtype_to_ignore{}; + get_number(input_format_t::cbor, subtype_to_ignore); break; } default: @@ -8993,6 +8995,47 @@ class binary_reader return parse_cbor_internal(true, tag_handler); } + case cbor_tag_handler_t::store: + { + binary_t b; + // use binary subtype and store in binary container + switch (current) + { + case 0xD8: + { + std::uint8_t subtype{}; + get_number(input_format_t::cbor, subtype); + b.set_subtype(detail::conditional_static_cast(subtype)); + break; + } + case 0xD9: + { + std::uint16_t subtype{}; + get_number(input_format_t::cbor, subtype); + b.set_subtype(detail::conditional_static_cast(subtype)); + break; + } + case 0xDA: + { + std::uint32_t subtype{}; + get_number(input_format_t::cbor, subtype); + b.set_subtype(detail::conditional_static_cast(subtype)); + break; + } + case 0xDB: + { + std::uint64_t subtype{}; + get_number(input_format_t::cbor, subtype); + b.set_subtype(detail::conditional_static_cast(subtype)); + break; + } + default: + break; + } + get(); + return get_cbor_binary(b) && sax->binary(b); + } + default: // LCOV_EXCL_LINE JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE return false; // LCOV_EXCL_LINE diff --git a/test/src/unit-cbor.cpp b/test/src/unit-cbor.cpp index 19cdf1879..1660cf945 100644 --- a/test/src/unit-cbor.cpp +++ b/test/src/unit-cbor.cpp @@ -2488,12 +2488,20 @@ TEST_CASE("examples from RFC 7049 Appendix A") // 0xd8 CHECK(json::to_cbor(json::binary(std::vector {}, 0x42)) == std::vector {0xd8, 0x42, 0x40}); + CHECK(!json::from_cbor(json::to_cbor(json::binary(std::vector {}, 0x42)), true, true, json::cbor_tag_handler_t::ignore).get_binary().has_subtype()); + CHECK(json::from_cbor(json::to_cbor(json::binary(std::vector {}, 0x42)), true, true, json::cbor_tag_handler_t::store).get_binary().subtype() == 0x42); // 0xd9 CHECK(json::to_cbor(json::binary(std::vector {}, 1000)) == std::vector {0xd9, 0x03, 0xe8, 0x40}); + CHECK(!json::from_cbor(json::to_cbor(json::binary(std::vector {}, 1000)), true, true, json::cbor_tag_handler_t::ignore).get_binary().has_subtype()); + CHECK(json::from_cbor(json::to_cbor(json::binary(std::vector {}, 1000)), true, true, json::cbor_tag_handler_t::store).get_binary().subtype() == 1000); // 0xda CHECK(json::to_cbor(json::binary(std::vector {}, 394216)) == std::vector {0xda, 0x00, 0x06, 0x03, 0xe8, 0x40}); + CHECK(!json::from_cbor(json::to_cbor(json::binary(std::vector {}, 394216)), true, true, json::cbor_tag_handler_t::ignore).get_binary().has_subtype()); + CHECK(json::from_cbor(json::to_cbor(json::binary(std::vector {}, 394216)), true, true, json::cbor_tag_handler_t::store).get_binary().subtype() == 394216); // 0xdb CHECK(json::to_cbor(json::binary(std::vector {}, 8589934590)) == std::vector {0xdb, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xfe, 0x40}); + CHECK(!json::from_cbor(json::to_cbor(json::binary(std::vector {}, 8589934590)), true, true, json::cbor_tag_handler_t::ignore).get_binary().has_subtype()); + CHECK(json::from_cbor(json::to_cbor(json::binary(std::vector {}, 8589934590)), true, true, json::cbor_tag_handler_t::store).get_binary().subtype() == 8589934590); } SECTION("arrays")