Merge pull request #2273 from nlohmann/issue1968
Add option to ignore CBOR tags
This commit is contained in:
commit
548e7e54c9
4 changed files with 377 additions and 34 deletions
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue