Merge pull request #2273 from nlohmann/issue1968

Add option to ignore CBOR tags
This commit is contained in:
Niels Lohmann 2020-07-17 13:59:55 +02:00 committed by GitHub
commit 548e7e54c9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 377 additions and 34 deletions

View file

@ -24,6 +24,13 @@ namespace nlohmann
namespace detail 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
};
/*! /*!
@brief determine system byte order @brief determine system byte order
@ -78,13 +85,15 @@ class binary_reader
@param[in] format the binary format to parse @param[in] format the binary format to parse
@param[in] sax_ a SAX event processor @param[in] sax_ a SAX event processor
@param[in] strict whether to expect the input to be consumed completed @param[in] strict whether to expect the input to be consumed completed
@param[in] tag_handler how to treat CBOR tags
@return @return
*/ */
JSON_HEDLEY_NON_NULL(3) JSON_HEDLEY_NON_NULL(3)
bool sax_parse(const input_format_t format, bool sax_parse(const input_format_t format,
json_sax_t* sax_, json_sax_t* sax_,
const bool strict = true) const bool strict = true,
const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
{ {
sax = sax_; sax = sax_;
bool result = false; bool result = false;
@ -96,7 +105,7 @@ class binary_reader
break; break;
case input_format_t::cbor: case input_format_t::cbor:
result = parse_cbor_internal(); result = parse_cbor_internal(true, tag_handler);
break; break;
case input_format_t::msgpack: case input_format_t::msgpack:
@ -386,10 +395,12 @@ class binary_reader
@param[in] get_char whether a new character should be retrieved from the @param[in] get_char whether a new character should be retrieved from the
input (true, default) or whether the last read input (true, default) or whether the last read
character should be considered instead character should be considered instead
@param[in] tag_handler how CBOR tags should be treated
@return whether a valid CBOR value was passed to the SAX parser @return whether a valid CBOR value was passed to the SAX parser
*/ */
bool parse_cbor_internal(const bool get_char = true) bool parse_cbor_internal(const bool get_char = true,
cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
{ {
switch (get_char ? get() : current) switch (get_char ? get() : current)
{ {
@ -678,6 +689,73 @@ class binary_reader
case 0xBF: // map (indefinite length) case 0xBF: // map (indefinite length)
return get_cbor_object(std::size_t(-1)); return get_cbor_object(std::size_t(-1));
case 0xC6: // tagged item
case 0xC7:
case 0xC8:
case 0xC9:
case 0xCA:
case 0xCB:
case 0xCC:
case 0xCD:
case 0xCE:
case 0xCF:
case 0xD0:
case 0xD1:
case 0xD2:
case 0xD3:
case 0xD4:
case 0xD8: // tagged item (1 bytes follow)
case 0xD9: // tagged item (2 bytes follow)
case 0xDA: // tagged item (4 bytes follow)
case 0xDB: // tagged item (8 bytes follow)
{
switch (tag_handler)
{
case cbor_tag_handler_t::error:
{
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::cbor, "invalid byte: 0x" + last_token, "value")));
}
case cbor_tag_handler_t::ignore:
{
switch (current)
{
case 0xD8:
{
std::uint8_t len{};
get_number(input_format_t::cbor, len);
break;
}
case 0xD9:
{
std::uint16_t len{};
get_number(input_format_t::cbor, len);
break;
}
case 0xDA:
{
std::uint32_t len{};
get_number(input_format_t::cbor, len);
break;
}
case 0xDB:
{
std::uint64_t len{};
get_number(input_format_t::cbor, len);
break;
}
default:
break;
}
return parse_cbor_internal(true, tag_handler);
}
default: // LCOV_EXCL_LINE
JSON_ASSERT(false); // LCOV_EXCL_LINE
}
}
case 0xF4: // false case 0xF4: // false
return sax->boolean(false); return sax->boolean(false);

View file

@ -230,6 +230,8 @@ class basic_json
using json_serializer = JSONSerializer<T, SFINAE>; using json_serializer = JSONSerializer<T, SFINAE>;
/// how to treat decoding errors /// how to treat decoding errors
using error_handler_t = detail::error_handler_t; using error_handler_t = detail::error_handler_t;
/// how to treat CBOR tags
using cbor_tag_handler_t = detail::cbor_tag_handler_t;
/// helper type for initializer lists of basic_json values /// helper type for initializer lists of basic_json values
using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>; using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
@ -7049,7 +7051,7 @@ class basic_json
vector in CBOR format.,to_cbor} vector in CBOR format.,to_cbor}
@sa http://cbor.io @sa http://cbor.io
@sa @ref from_cbor(detail::input_adapter&&, const bool, const bool) for the @sa @ref from_cbor(detail::input_adapter&&, const bool, const bool, const cbor_tag_handler_t) for the
analogous deserialization analogous deserialization
@sa @ref to_msgpack(const basic_json&) for the related MessagePack format @sa @ref to_msgpack(const basic_json&) for the related MessagePack format
@sa @ref to_ubjson(const basic_json&, const bool, const bool) for the @sa @ref to_ubjson(const basic_json&, const bool, const bool) for the
@ -7437,6 +7439,7 @@ class basic_json
(true by default) (true by default)
@param[in] allow_exceptions whether to throw exceptions in case of a @param[in] allow_exceptions whether to throw exceptions in case of a
parse error (optional, true by default) parse error (optional, true by default)
@param[in] tag_handler how to treat CBOR tags (optional, error by default)
@return deserialized JSON value; in case of a parse error and @return deserialized JSON value; in case of a parse error and
@a allow_exceptions set to `false`, the return value will be @a allow_exceptions set to `false`, the return value will be
@ -7463,34 +7466,36 @@ class basic_json
@since version 2.0.9; parameter @a start_index since 2.1.1; changed to @since version 2.0.9; parameter @a start_index since 2.1.1; changed to
consume input adapters, removed start_index parameter, and added consume input adapters, removed start_index parameter, and added
@a strict parameter since 3.0.0; added @a allow_exceptions parameter @a strict parameter since 3.0.0; added @a allow_exceptions parameter
since 3.2.0 since 3.2.0; added @a tag_handler parameter since 3.9.0.
*/ */
template<typename InputType> template<typename InputType>
JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_WARN_UNUSED_RESULT
static basic_json from_cbor(InputType&& i, static basic_json from_cbor(InputType&& i,
const bool strict = true, const bool strict = true,
const bool allow_exceptions = true) const bool allow_exceptions = true,
const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
{ {
basic_json result; basic_json result;
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
auto ia = detail::input_adapter(std::forward<InputType>(i)); auto ia = detail::input_adapter(std::forward<InputType>(i));
const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict); const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
return res ? result : basic_json(value_t::discarded); return res ? result : basic_json(value_t::discarded);
} }
/*! /*!
@copydoc from_cbor(detail::input_adapter&&, const bool, const bool) @copydoc from_cbor(detail::input_adapter&&, const bool, const bool, const cbor_tag_handler_t)
*/ */
template<typename IteratorType> template<typename IteratorType>
JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_WARN_UNUSED_RESULT
static basic_json from_cbor(IteratorType first, IteratorType last, static basic_json from_cbor(IteratorType first, IteratorType last,
const bool strict = true, const bool strict = true,
const bool allow_exceptions = true) const bool allow_exceptions = true,
const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
{ {
basic_json result; basic_json result;
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
auto ia = detail::input_adapter(std::move(first), std::move(last)); auto ia = detail::input_adapter(std::move(first), std::move(last));
const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict); const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
return res ? result : basic_json(value_t::discarded); return res ? result : basic_json(value_t::discarded);
} }
@ -7499,9 +7504,10 @@ class basic_json
JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len)) JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
static basic_json from_cbor(const T* ptr, std::size_t len, static basic_json from_cbor(const T* ptr, std::size_t len,
const bool strict = true, const bool strict = true,
const bool allow_exceptions = true) const bool allow_exceptions = true,
const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
{ {
return from_cbor(ptr, ptr + len, strict, allow_exceptions); return from_cbor(ptr, ptr + len, strict, tag_handler);
} }
@ -7509,12 +7515,13 @@ class basic_json
JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len)) JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
static basic_json from_cbor(detail::span_input_adapter&& i, static basic_json from_cbor(detail::span_input_adapter&& i,
const bool strict = true, const bool strict = true,
const bool allow_exceptions = true) const bool allow_exceptions = true,
const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
{ {
basic_json result; basic_json result;
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
auto ia = i.get(); auto ia = i.get();
const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict); const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
return res ? result : basic_json(value_t::discarded); return res ? result : basic_json(value_t::discarded);
} }
@ -7592,7 +7599,7 @@ class basic_json
@sa http://msgpack.org @sa http://msgpack.org
@sa @ref to_msgpack(const basic_json&) for the analogous serialization @sa @ref to_msgpack(const basic_json&) for the analogous serialization
@sa @ref from_cbor(detail::input_adapter&&, const bool, const bool) for the @sa @ref from_cbor(detail::input_adapter&&, const bool, const bool, const cbor_tag_handler_t) for the
related CBOR format related CBOR format
@sa @ref from_ubjson(detail::input_adapter&&, const bool, const bool) for @sa @ref from_ubjson(detail::input_adapter&&, const bool, const bool) for
the related UBJSON format the related UBJSON format
@ -7710,7 +7717,7 @@ class basic_json
@sa http://ubjson.org @sa http://ubjson.org
@sa @ref to_ubjson(const basic_json&, const bool, const bool) for the @sa @ref to_ubjson(const basic_json&, const bool, const bool) for the
analogous serialization analogous serialization
@sa @ref from_cbor(detail::input_adapter&&, const bool, const bool) for the @sa @ref from_cbor(detail::input_adapter&&, const bool, const bool, const cbor_tag_handler_t) for the
related CBOR format related CBOR format
@sa @ref from_msgpack(detail::input_adapter&&, const bool, const bool) for @sa @ref from_msgpack(detail::input_adapter&&, const bool, const bool) for
the related MessagePack format the related MessagePack format
@ -7825,7 +7832,7 @@ class basic_json
@sa http://bsonspec.org/spec.html @sa http://bsonspec.org/spec.html
@sa @ref to_bson(const basic_json&) for the analogous serialization @sa @ref to_bson(const basic_json&) for the analogous serialization
@sa @ref from_cbor(detail::input_adapter&&, const bool, const bool) for the @sa @ref from_cbor(detail::input_adapter&&, const bool, const bool, const cbor_tag_handler_t) for the
related CBOR format related CBOR format
@sa @ref from_msgpack(detail::input_adapter&&, const bool, const bool) for @sa @ref from_msgpack(detail::input_adapter&&, const bool, const bool) for
the related MessagePack format the related MessagePack format

View file

@ -5921,6 +5921,13 @@ namespace nlohmann
namespace detail 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
};
/*! /*!
@brief determine system byte order @brief determine system byte order
@ -5975,13 +5982,15 @@ class binary_reader
@param[in] format the binary format to parse @param[in] format the binary format to parse
@param[in] sax_ a SAX event processor @param[in] sax_ a SAX event processor
@param[in] strict whether to expect the input to be consumed completed @param[in] strict whether to expect the input to be consumed completed
@param[in] tag_handler how to treat CBOR tags
@return @return
*/ */
JSON_HEDLEY_NON_NULL(3) JSON_HEDLEY_NON_NULL(3)
bool sax_parse(const input_format_t format, bool sax_parse(const input_format_t format,
json_sax_t* sax_, json_sax_t* sax_,
const bool strict = true) const bool strict = true,
const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
{ {
sax = sax_; sax = sax_;
bool result = false; bool result = false;
@ -5993,7 +6002,7 @@ class binary_reader
break; break;
case input_format_t::cbor: case input_format_t::cbor:
result = parse_cbor_internal(); result = parse_cbor_internal(true, tag_handler);
break; break;
case input_format_t::msgpack: case input_format_t::msgpack:
@ -6283,10 +6292,12 @@ class binary_reader
@param[in] get_char whether a new character should be retrieved from the @param[in] get_char whether a new character should be retrieved from the
input (true, default) or whether the last read input (true, default) or whether the last read
character should be considered instead character should be considered instead
@param[in] tag_handler how CBOR tags should be treated
@return whether a valid CBOR value was passed to the SAX parser @return whether a valid CBOR value was passed to the SAX parser
*/ */
bool parse_cbor_internal(const bool get_char = true) bool parse_cbor_internal(const bool get_char = true,
cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
{ {
switch (get_char ? get() : current) switch (get_char ? get() : current)
{ {
@ -6575,6 +6586,73 @@ class binary_reader
case 0xBF: // map (indefinite length) case 0xBF: // map (indefinite length)
return get_cbor_object(std::size_t(-1)); return get_cbor_object(std::size_t(-1));
case 0xC6: // tagged item
case 0xC7:
case 0xC8:
case 0xC9:
case 0xCA:
case 0xCB:
case 0xCC:
case 0xCD:
case 0xCE:
case 0xCF:
case 0xD0:
case 0xD1:
case 0xD2:
case 0xD3:
case 0xD4:
case 0xD8: // tagged item (1 bytes follow)
case 0xD9: // tagged item (2 bytes follow)
case 0xDA: // tagged item (4 bytes follow)
case 0xDB: // tagged item (8 bytes follow)
{
switch (tag_handler)
{
case cbor_tag_handler_t::error:
{
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::cbor, "invalid byte: 0x" + last_token, "value")));
}
case cbor_tag_handler_t::ignore:
{
switch (current)
{
case 0xD8:
{
std::uint8_t len{};
get_number(input_format_t::cbor, len);
break;
}
case 0xD9:
{
std::uint16_t len{};
get_number(input_format_t::cbor, len);
break;
}
case 0xDA:
{
std::uint32_t len{};
get_number(input_format_t::cbor, len);
break;
}
case 0xDB:
{
std::uint64_t len{};
get_number(input_format_t::cbor, len);
break;
}
default:
break;
}
return parse_cbor_internal(true, tag_handler);
}
default: // LCOV_EXCL_LINE
JSON_ASSERT(false); // LCOV_EXCL_LINE
}
}
case 0xF4: // false case 0xF4: // false
return sax->boolean(false); return sax->boolean(false);
@ -16336,6 +16414,8 @@ class basic_json
using json_serializer = JSONSerializer<T, SFINAE>; using json_serializer = JSONSerializer<T, SFINAE>;
/// how to treat decoding errors /// how to treat decoding errors
using error_handler_t = detail::error_handler_t; using error_handler_t = detail::error_handler_t;
/// how to treat CBOR tags
using cbor_tag_handler_t = detail::cbor_tag_handler_t;
/// helper type for initializer lists of basic_json values /// helper type for initializer lists of basic_json values
using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>; using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
@ -23155,7 +23235,7 @@ class basic_json
vector in CBOR format.,to_cbor} vector in CBOR format.,to_cbor}
@sa http://cbor.io @sa http://cbor.io
@sa @ref from_cbor(detail::input_adapter&&, const bool, const bool) for the @sa @ref from_cbor(detail::input_adapter&&, const bool, const bool, const cbor_tag_handler_t) for the
analogous deserialization analogous deserialization
@sa @ref to_msgpack(const basic_json&) for the related MessagePack format @sa @ref to_msgpack(const basic_json&) for the related MessagePack format
@sa @ref to_ubjson(const basic_json&, const bool, const bool) for the @sa @ref to_ubjson(const basic_json&, const bool, const bool) for the
@ -23543,6 +23623,7 @@ class basic_json
(true by default) (true by default)
@param[in] allow_exceptions whether to throw exceptions in case of a @param[in] allow_exceptions whether to throw exceptions in case of a
parse error (optional, true by default) parse error (optional, true by default)
@param[in] tag_handler how to treat CBOR tags (optional, error by default)
@return deserialized JSON value; in case of a parse error and @return deserialized JSON value; in case of a parse error and
@a allow_exceptions set to `false`, the return value will be @a allow_exceptions set to `false`, the return value will be
@ -23569,34 +23650,36 @@ class basic_json
@since version 2.0.9; parameter @a start_index since 2.1.1; changed to @since version 2.0.9; parameter @a start_index since 2.1.1; changed to
consume input adapters, removed start_index parameter, and added consume input adapters, removed start_index parameter, and added
@a strict parameter since 3.0.0; added @a allow_exceptions parameter @a strict parameter since 3.0.0; added @a allow_exceptions parameter
since 3.2.0 since 3.2.0; added @a tag_handler parameter since 3.9.0.
*/ */
template<typename InputType> template<typename InputType>
JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_WARN_UNUSED_RESULT
static basic_json from_cbor(InputType&& i, static basic_json from_cbor(InputType&& i,
const bool strict = true, const bool strict = true,
const bool allow_exceptions = true) const bool allow_exceptions = true,
const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
{ {
basic_json result; basic_json result;
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
auto ia = detail::input_adapter(std::forward<InputType>(i)); auto ia = detail::input_adapter(std::forward<InputType>(i));
const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict); const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
return res ? result : basic_json(value_t::discarded); return res ? result : basic_json(value_t::discarded);
} }
/*! /*!
@copydoc from_cbor(detail::input_adapter&&, const bool, const bool) @copydoc from_cbor(detail::input_adapter&&, const bool, const bool, const cbor_tag_handler_t)
*/ */
template<typename IteratorType> template<typename IteratorType>
JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_WARN_UNUSED_RESULT
static basic_json from_cbor(IteratorType first, IteratorType last, static basic_json from_cbor(IteratorType first, IteratorType last,
const bool strict = true, const bool strict = true,
const bool allow_exceptions = true) const bool allow_exceptions = true,
const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
{ {
basic_json result; basic_json result;
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
auto ia = detail::input_adapter(std::move(first), std::move(last)); auto ia = detail::input_adapter(std::move(first), std::move(last));
const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict); const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
return res ? result : basic_json(value_t::discarded); return res ? result : basic_json(value_t::discarded);
} }
@ -23605,9 +23688,10 @@ class basic_json
JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len)) JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
static basic_json from_cbor(const T* ptr, std::size_t len, static basic_json from_cbor(const T* ptr, std::size_t len,
const bool strict = true, const bool strict = true,
const bool allow_exceptions = true) const bool allow_exceptions = true,
const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
{ {
return from_cbor(ptr, ptr + len, strict, allow_exceptions); return from_cbor(ptr, ptr + len, strict, tag_handler);
} }
@ -23615,12 +23699,13 @@ class basic_json
JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len)) JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
static basic_json from_cbor(detail::span_input_adapter&& i, static basic_json from_cbor(detail::span_input_adapter&& i,
const bool strict = true, const bool strict = true,
const bool allow_exceptions = true) const bool allow_exceptions = true,
const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
{ {
basic_json result; basic_json result;
detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions); detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
auto ia = i.get(); auto ia = i.get();
const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict); const bool res = binary_reader<decltype(ia)>(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
return res ? result : basic_json(value_t::discarded); return res ? result : basic_json(value_t::discarded);
} }
@ -23698,7 +23783,7 @@ class basic_json
@sa http://msgpack.org @sa http://msgpack.org
@sa @ref to_msgpack(const basic_json&) for the analogous serialization @sa @ref to_msgpack(const basic_json&) for the analogous serialization
@sa @ref from_cbor(detail::input_adapter&&, const bool, const bool) for the @sa @ref from_cbor(detail::input_adapter&&, const bool, const bool, const cbor_tag_handler_t) for the
related CBOR format related CBOR format
@sa @ref from_ubjson(detail::input_adapter&&, const bool, const bool) for @sa @ref from_ubjson(detail::input_adapter&&, const bool, const bool) for
the related UBJSON format the related UBJSON format
@ -23816,7 +23901,7 @@ class basic_json
@sa http://ubjson.org @sa http://ubjson.org
@sa @ref to_ubjson(const basic_json&, const bool, const bool) for the @sa @ref to_ubjson(const basic_json&, const bool, const bool) for the
analogous serialization analogous serialization
@sa @ref from_cbor(detail::input_adapter&&, const bool, const bool) for the @sa @ref from_cbor(detail::input_adapter&&, const bool, const bool, const cbor_tag_handler_t) for the
related CBOR format related CBOR format
@sa @ref from_msgpack(detail::input_adapter&&, const bool, const bool) for @sa @ref from_msgpack(detail::input_adapter&&, const bool, const bool) for
the related MessagePack format the related MessagePack format
@ -23931,7 +24016,7 @@ class basic_json
@sa http://bsonspec.org/spec.html @sa http://bsonspec.org/spec.html
@sa @ref to_bson(const basic_json&) for the analogous serialization @sa @ref to_bson(const basic_json&) for the analogous serialization
@sa @ref from_cbor(detail::input_adapter&&, const bool, const bool) for the @sa @ref from_cbor(detail::input_adapter&&, const bool, const bool, const cbor_tag_handler_t) for the
related CBOR format related CBOR format
@sa @ref from_msgpack(detail::input_adapter&&, const bool, const bool) for @sa @ref from_msgpack(detail::input_adapter&&, const bool, const bool) for
the related MessagePack format the related MessagePack format

View file

@ -2548,3 +2548,176 @@ TEST_CASE("examples from RFC 7049 Appendix A")
CHECK(json::parse("{\"Fun\": true, \"Amt\": -2}") == json::from_cbor(std::vector<uint8_t>({0xbf, 0x63, 0x46, 0x75, 0x6e, 0xf5, 0x63, 0x41, 0x6d, 0x74, 0x21, 0xff}))); CHECK(json::parse("{\"Fun\": true, \"Amt\": -2}") == json::from_cbor(std::vector<uint8_t>({0xbf, 0x63, 0x46, 0x75, 0x6e, 0xf5, 0x63, 0x41, 0x6d, 0x74, 0x21, 0xff})));
} }
} }
TEST_CASE("Tagged values")
{
json j = "s";
auto v = json::to_cbor(j);
SECTION("0xC6..0xD4")
{
for (std::uint8_t b :
{
0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4
})
{
// add tag to value
auto v_tagged = v;
v_tagged.insert(v_tagged.begin(), b);
// check that parsing fails in error mode
CHECK_THROWS_AS(json::from_cbor(v_tagged), json::parse_error);
CHECK_THROWS_AS(json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::error), json::parse_error);
// check that parsing succeeds and gets original value in ignore mode
auto j_tagged = json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::ignore);
CHECK(j_tagged == j);
}
}
SECTION("0xD8 - 1 byte follows")
{
SECTION("success")
{
// add tag to value
auto v_tagged = v;
v_tagged.insert(v_tagged.begin(), 0x42); // 1 byte
v_tagged.insert(v_tagged.begin(), 0xD8); // tag
// check that parsing fails in error mode
CHECK_THROWS_AS(json::from_cbor(v_tagged), json::parse_error);
CHECK_THROWS_AS(json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::error), json::parse_error);
// check that parsing succeeds and gets original value in ignore mode
auto j_tagged = json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::ignore);
CHECK(j_tagged == j);
}
SECTION("missing byte after tag")
{
// add tag to value
auto v_tagged = v;
v_tagged.insert(v_tagged.begin(), 0xD8); // tag
// check that parsing fails in all modes
CHECK_THROWS_AS(json::from_cbor(v_tagged), json::parse_error);
CHECK_THROWS_AS(json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::error), json::parse_error);
CHECK_THROWS_AS(json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::ignore), json::parse_error);
}
}
SECTION("0xD9 - 2 byte follow")
{
SECTION("success")
{
// add tag to value
auto v_tagged = v;
v_tagged.insert(v_tagged.begin(), 0x42); // 1 byte
v_tagged.insert(v_tagged.begin(), 0x23); // 1 byte
v_tagged.insert(v_tagged.begin(), 0xD9); // tag
// check that parsing fails in error mode
CHECK_THROWS_AS(json::from_cbor(v_tagged), json::parse_error);
CHECK_THROWS_AS(json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::error), json::parse_error);
// check that parsing succeeds and gets original value in ignore mode
auto j_tagged = json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::ignore);
CHECK(j_tagged == j);
}
SECTION("missing byte after tag")
{
// add tag to value
auto v_tagged = v;
v_tagged.insert(v_tagged.begin(), 0x23); // 1 byte
v_tagged.insert(v_tagged.begin(), 0xD9); // tag
// check that parsing fails in all modes
CHECK_THROWS_AS(json::from_cbor(v_tagged), json::parse_error);
CHECK_THROWS_AS(json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::error), json::parse_error);
CHECK_THROWS_AS(json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::ignore), json::parse_error);
}
}
SECTION("0xDA - 4 bytes follow")
{
SECTION("success")
{
// add tag to value
auto v_tagged = v;
v_tagged.insert(v_tagged.begin(), 0x42); // 1 byte
v_tagged.insert(v_tagged.begin(), 0x23); // 1 byte
v_tagged.insert(v_tagged.begin(), 0x22); // 1 byte
v_tagged.insert(v_tagged.begin(), 0x11); // 1 byte
v_tagged.insert(v_tagged.begin(), 0xDA); // tag
// check that parsing fails in error mode
CHECK_THROWS_AS(json::from_cbor(v_tagged), json::parse_error);
CHECK_THROWS_AS(json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::error), json::parse_error);
// check that parsing succeeds and gets original value in ignore mode
auto j_tagged = json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::ignore);
CHECK(j_tagged == j);
}
SECTION("missing bytes after tag")
{
// add tag to value
auto v_tagged = v;
v_tagged.insert(v_tagged.begin(), 0x23); // 1 byte
v_tagged.insert(v_tagged.begin(), 0x22); // 1 byte
v_tagged.insert(v_tagged.begin(), 0x11); // 1 byte
v_tagged.insert(v_tagged.begin(), 0xDA); // tag
// check that parsing fails in all modes
CHECK_THROWS_AS(json::from_cbor(v_tagged), json::parse_error);
CHECK_THROWS_AS(json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::error), json::parse_error);
CHECK_THROWS_AS(json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::ignore), json::parse_error);
}
}
SECTION("0xDB - 8 bytes follow")
{
SECTION("success")
{
// add tag to value
auto v_tagged = v;
v_tagged.insert(v_tagged.begin(), 0x42); // 1 byte
v_tagged.insert(v_tagged.begin(), 0x23); // 1 byte
v_tagged.insert(v_tagged.begin(), 0x22); // 1 byte
v_tagged.insert(v_tagged.begin(), 0x11); // 1 byte
v_tagged.insert(v_tagged.begin(), 0x42); // 1 byte
v_tagged.insert(v_tagged.begin(), 0x23); // 1 byte
v_tagged.insert(v_tagged.begin(), 0x22); // 1 byte
v_tagged.insert(v_tagged.begin(), 0x11); // 1 byte
v_tagged.insert(v_tagged.begin(), 0xDB); // tag
// check that parsing fails in error mode
CHECK_THROWS_AS(json::from_cbor(v_tagged), json::parse_error);
CHECK_THROWS_AS(json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::error), json::parse_error);
// check that parsing succeeds and gets original value in ignore mode
auto j_tagged = json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::ignore);
CHECK(j_tagged == j);
}
SECTION("missing byte after tag")
{
// add tag to value
auto v_tagged = v;
v_tagged.insert(v_tagged.begin(), 0x42); // 1 byte
v_tagged.insert(v_tagged.begin(), 0x23); // 1 byte
v_tagged.insert(v_tagged.begin(), 0x22); // 1 byte
v_tagged.insert(v_tagged.begin(), 0x11); // 1 byte
v_tagged.insert(v_tagged.begin(), 0x23); // 1 byte
v_tagged.insert(v_tagged.begin(), 0x22); // 1 byte
v_tagged.insert(v_tagged.begin(), 0x11); // 1 byte
v_tagged.insert(v_tagged.begin(), 0xDB); // tag
// check that parsing fails in all modes
CHECK_THROWS_AS(json::from_cbor(v_tagged), json::parse_error);
CHECK_THROWS_AS(json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::error), json::parse_error);
CHECK_THROWS_AS(json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::ignore), json::parse_error);
}
}
}