✅ improved coverage
This commit is contained in:
parent
1e38ffc014
commit
9e1abb4842
12 changed files with 412 additions and 180 deletions
|
@ -41,9 +41,6 @@ class binary_reader
|
||||||
using json_sax_t = json_sax<BasicJsonType>;
|
using json_sax_t = json_sax<BasicJsonType>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// the supported binary input formats
|
|
||||||
enum class binary_format_t { cbor, msgpack, ubjson };
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief create a binary reader
|
@brief create a binary reader
|
||||||
|
|
||||||
|
@ -61,30 +58,35 @@ class binary_reader
|
||||||
|
|
||||||
@return
|
@return
|
||||||
*/
|
*/
|
||||||
bool sax_parse(const binary_format_t format, json_sax_t* sax_, const bool strict)
|
bool sax_parse(const input_format_t format,
|
||||||
|
json_sax_t* sax_,
|
||||||
|
const bool strict = true)
|
||||||
{
|
{
|
||||||
sax = sax_;
|
sax = sax_;
|
||||||
bool result;
|
bool result;
|
||||||
|
|
||||||
switch (format)
|
switch (format)
|
||||||
{
|
{
|
||||||
case binary_format_t::cbor:
|
case input_format_t::cbor:
|
||||||
result = parse_cbor_internal();
|
result = parse_cbor_internal();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case binary_format_t::msgpack:
|
case input_format_t::msgpack:
|
||||||
result = parse_msgpack_internal();
|
result = parse_msgpack_internal();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case binary_format_t::ubjson:
|
case input_format_t::ubjson:
|
||||||
result = parse_ubjson_internal();
|
result = parse_ubjson_internal();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
assert(false); // LCOV_EXCL_LINE
|
||||||
}
|
}
|
||||||
|
|
||||||
// strict mode: next byte must be EOF
|
// strict mode: next byte must be EOF
|
||||||
if (result and strict)
|
if (result and strict)
|
||||||
{
|
{
|
||||||
if (format == binary_format_t::ubjson)
|
if (format == input_format_t::ubjson)
|
||||||
{
|
{
|
||||||
get_ignore_noop();
|
get_ignore_noop();
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,9 @@ namespace nlohmann
|
||||||
{
|
{
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
|
/// the supported input formats
|
||||||
|
enum class input_format_t { json, cbor, msgpack, ubjson };
|
||||||
|
|
||||||
////////////////////
|
////////////////////
|
||||||
// input adapters //
|
// input adapters //
|
||||||
////////////////////
|
////////////////////
|
||||||
|
|
|
@ -105,21 +105,12 @@ struct json_sax
|
||||||
*/
|
*/
|
||||||
virtual bool end_array() = 0;
|
virtual bool end_array() = 0;
|
||||||
|
|
||||||
/*!
|
|
||||||
@brief a binary value was read
|
|
||||||
@param[in] val byte vector
|
|
||||||
@return whether parsing should proceed
|
|
||||||
@note examples are CBOR type 2 strings, MessagePack bin, and maybe UBJSON
|
|
||||||
array<uint8t>
|
|
||||||
*/
|
|
||||||
virtual bool binary(const std::vector<uint8_t>& val) = 0;
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief a parse error occurred
|
@brief a parse error occurred
|
||||||
@param[in] position the position in the input where the error occurs
|
@param[in] position the position in the input where the error occurs
|
||||||
@param[in] last_token the last read token
|
@param[in] last_token the last read token
|
||||||
@param[in] error_msg a detailed error message
|
@param[in] error_msg a detailed error message
|
||||||
@return whether parsing should proceed
|
@return whether parsing should proceed (must return false)
|
||||||
*/
|
*/
|
||||||
virtual bool parse_error(std::size_t position,
|
virtual bool parse_error(std::size_t position,
|
||||||
const std::string& last_token,
|
const std::string& last_token,
|
||||||
|
@ -225,11 +216,6 @@ class json_sax_dom_parser : public json_sax<BasicJsonType>
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool binary(const std::vector<uint8_t>&) override
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool parse_error(std::size_t, const std::string&,
|
bool parse_error(std::size_t, const std::string&,
|
||||||
const detail::exception& ex) override
|
const detail::exception& ex) override
|
||||||
{
|
{
|
||||||
|
@ -430,11 +416,6 @@ class json_sax_dom_callback_parser : public json_sax<BasicJsonType>
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool binary(const std::vector<uint8_t>&) override
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool parse_error(std::size_t, const std::string&,
|
bool parse_error(std::size_t, const std::string&,
|
||||||
const detail::exception& ex) override
|
const detail::exception& ex) override
|
||||||
{
|
{
|
||||||
|
@ -580,11 +561,6 @@ class json_sax_acceptor : public json_sax<BasicJsonType>
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool binary(const std::vector<uint8_t>&) override
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool parse_error(std::size_t, const std::string&, const detail::exception&) override
|
bool parse_error(std::size_t, const std::string&, const detail::exception&) override
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -99,7 +99,7 @@ class lexer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
explicit lexer(detail::input_adapter_t adapter)
|
explicit lexer(detail::input_adapter_t&& adapter)
|
||||||
: ia(std::move(adapter)), decimal_point_char(get_decimal_point()) {}
|
: ia(std::move(adapter)), decimal_point_char(get_decimal_point()) {}
|
||||||
|
|
||||||
// delete because of pointer members
|
// delete because of pointer members
|
||||||
|
|
|
@ -60,10 +60,10 @@ class parser
|
||||||
std::function<bool(int depth, parse_event_t event, BasicJsonType& parsed)>;
|
std::function<bool(int depth, parse_event_t event, BasicJsonType& parsed)>;
|
||||||
|
|
||||||
/// a parser reading from an input adapter
|
/// a parser reading from an input adapter
|
||||||
explicit parser(detail::input_adapter_t adapter,
|
explicit parser(detail::input_adapter_t&& adapter,
|
||||||
const parser_callback_t cb = nullptr,
|
const parser_callback_t cb = nullptr,
|
||||||
const bool allow_exceptions_ = true)
|
const bool allow_exceptions_ = true)
|
||||||
: callback(cb), m_lexer(adapter), allow_exceptions(allow_exceptions_)
|
: callback(cb), m_lexer(std::move(adapter)), allow_exceptions(allow_exceptions_)
|
||||||
{
|
{
|
||||||
// read first token
|
// read first token
|
||||||
get_token();
|
get_token();
|
||||||
|
@ -160,19 +160,22 @@ class parser
|
||||||
bool accept(const bool strict = true)
|
bool accept(const bool strict = true)
|
||||||
{
|
{
|
||||||
json_sax_acceptor<BasicJsonType> sax_acceptor;
|
json_sax_acceptor<BasicJsonType> sax_acceptor;
|
||||||
|
return sax_parse(&sax_acceptor, strict);
|
||||||
if (not sax_parse_internal(&sax_acceptor))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// strict => last token must be EOF
|
|
||||||
return not strict or (get_token() == token_type::end_of_input);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sax_parse(json_sax_t* sax)
|
bool sax_parse(json_sax_t* sax, const bool strict = true)
|
||||||
{
|
{
|
||||||
return sax_parse_internal(sax);
|
const bool result = sax_parse_internal(sax);
|
||||||
|
|
||||||
|
// strict mode: next byte must be EOF
|
||||||
|
if (result and strict and (get_token() != token_type::end_of_input))
|
||||||
|
{
|
||||||
|
return sax->parse_error(m_lexer.get_position(),
|
||||||
|
m_lexer.get_token_string(),
|
||||||
|
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -209,6 +209,8 @@ class basic_json
|
||||||
/// 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>>;
|
||||||
|
|
||||||
|
using input_format_t = detail::input_format_t;
|
||||||
|
|
||||||
////////////////
|
////////////////
|
||||||
// exceptions //
|
// exceptions //
|
||||||
////////////////
|
////////////////
|
||||||
|
@ -5996,7 +5998,7 @@ class basic_json
|
||||||
|
|
||||||
@since version 2.0.3 (contiguous containers)
|
@since version 2.0.3 (contiguous containers)
|
||||||
*/
|
*/
|
||||||
static basic_json parse(detail::input_adapter i,
|
static basic_json parse(detail::input_adapter&& i,
|
||||||
const parser_callback_t cb = nullptr,
|
const parser_callback_t cb = nullptr,
|
||||||
const bool allow_exceptions = true)
|
const bool allow_exceptions = true)
|
||||||
{
|
{
|
||||||
|
@ -6005,36 +6007,23 @@ class basic_json
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
static bool accept(detail::input_adapter&& i)
|
||||||
@copydoc basic_json parse(detail::input_adapter, const parser_callback_t)
|
|
||||||
*/
|
|
||||||
static basic_json parse(detail::input_adapter& i,
|
|
||||||
const parser_callback_t cb = nullptr,
|
|
||||||
const bool allow_exceptions = true)
|
|
||||||
{
|
|
||||||
basic_json result;
|
|
||||||
parser(i, cb, allow_exceptions).parse(true, result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool accept(detail::input_adapter i)
|
|
||||||
{
|
{
|
||||||
return parser(i).accept(true);
|
return parser(i).accept(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool accept(detail::input_adapter& i)
|
static bool sax_parse(detail::input_adapter&& i, json_sax_t* sax,
|
||||||
|
input_format_t format = input_format_t::json,
|
||||||
|
const bool strict = true)
|
||||||
{
|
{
|
||||||
return parser(i).accept(true);
|
assert(sax);
|
||||||
}
|
switch (format)
|
||||||
|
{
|
||||||
static bool sax_parse(detail::input_adapter i, json_sax_t* sax)
|
case input_format_t::json:
|
||||||
{
|
return parser(std::move(i)).sax_parse(sax, strict);
|
||||||
return parser(i).sax_parse(sax);
|
default:
|
||||||
}
|
return binary_reader(std::move(i)).sax_parse(format, sax, strict);
|
||||||
|
}
|
||||||
static bool sax_parse(detail::input_adapter& i, json_sax_t* sax)
|
|
||||||
{
|
|
||||||
return parser(i).sax_parse(sax);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -6639,13 +6628,13 @@ class basic_json
|
||||||
@a strict parameter since 3.0.0; added @allow_exceptions parameter
|
@a strict parameter since 3.0.0; added @allow_exceptions parameter
|
||||||
since 3.2.0
|
since 3.2.0
|
||||||
*/
|
*/
|
||||||
static basic_json from_cbor(detail::input_adapter i,
|
static basic_json from_cbor(detail::input_adapter&& i,
|
||||||
const bool strict = true,
|
const bool strict = true,
|
||||||
const bool allow_exceptions = true)
|
const bool allow_exceptions = true)
|
||||||
{
|
{
|
||||||
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);
|
||||||
const bool res = binary_reader(detail::input_adapter(i)).sax_parse(binary_reader::binary_format_t::cbor, &sdp, strict);
|
const bool res = binary_reader(detail::input_adapter(i)).sax_parse(input_format_t::cbor, &sdp, strict);
|
||||||
return res ? result : basic_json(value_t::discarded);
|
return res ? result : basic_json(value_t::discarded);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6660,7 +6649,7 @@ class basic_json
|
||||||
{
|
{
|
||||||
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);
|
||||||
const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(binary_reader::binary_format_t::cbor, &sdp, strict);
|
const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(input_format_t::cbor, &sdp, strict);
|
||||||
return res ? result : basic_json(value_t::discarded);
|
return res ? result : basic_json(value_t::discarded);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6742,13 +6731,13 @@ class basic_json
|
||||||
@a strict parameter since 3.0.0; added @allow_exceptions parameter
|
@a strict parameter since 3.0.0; added @allow_exceptions parameter
|
||||||
since 3.2.0
|
since 3.2.0
|
||||||
*/
|
*/
|
||||||
static basic_json from_msgpack(detail::input_adapter i,
|
static basic_json from_msgpack(detail::input_adapter&& i,
|
||||||
const bool strict = true,
|
const bool strict = true,
|
||||||
const bool allow_exceptions = true)
|
const bool allow_exceptions = true)
|
||||||
{
|
{
|
||||||
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);
|
||||||
const bool res = binary_reader(detail::input_adapter(i)).sax_parse(binary_reader::binary_format_t::msgpack, &sdp, strict);
|
const bool res = binary_reader(detail::input_adapter(i)).sax_parse(input_format_t::msgpack, &sdp, strict);
|
||||||
return res ? result : basic_json(value_t::discarded);
|
return res ? result : basic_json(value_t::discarded);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6763,7 +6752,7 @@ class basic_json
|
||||||
{
|
{
|
||||||
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);
|
||||||
const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(binary_reader::binary_format_t::msgpack, &sdp, strict);
|
const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(input_format_t::msgpack, &sdp, strict);
|
||||||
return res ? result : basic_json(value_t::discarded);
|
return res ? result : basic_json(value_t::discarded);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6824,13 +6813,13 @@ class basic_json
|
||||||
|
|
||||||
@since version 3.1.0; added @allow_exceptions parameter since 3.2.0
|
@since version 3.1.0; added @allow_exceptions parameter since 3.2.0
|
||||||
*/
|
*/
|
||||||
static basic_json from_ubjson(detail::input_adapter i,
|
static basic_json from_ubjson(detail::input_adapter&& i,
|
||||||
const bool strict = true,
|
const bool strict = true,
|
||||||
const bool allow_exceptions = true)
|
const bool allow_exceptions = true)
|
||||||
{
|
{
|
||||||
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);
|
||||||
const bool res = binary_reader(detail::input_adapter(i)).sax_parse(binary_reader::binary_format_t::ubjson, &sdp, strict);
|
const bool res = binary_reader(detail::input_adapter(i)).sax_parse(input_format_t::ubjson, &sdp, strict);
|
||||||
return res ? result : basic_json(value_t::discarded);
|
return res ? result : basic_json(value_t::discarded);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6845,7 +6834,7 @@ class basic_json
|
||||||
{
|
{
|
||||||
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);
|
||||||
const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(binary_reader::binary_format_t::ubjson, &sdp, strict);
|
const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(input_format_t::ubjson, &sdp, strict);
|
||||||
return res ? result : basic_json(value_t::discarded);
|
return res ? result : basic_json(value_t::discarded);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1593,6 +1593,9 @@ namespace nlohmann
|
||||||
{
|
{
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
|
/// the supported input formats
|
||||||
|
enum class input_format_t { json, cbor, msgpack, ubjson };
|
||||||
|
|
||||||
////////////////////
|
////////////////////
|
||||||
// input adapters //
|
// input adapters //
|
||||||
////////////////////
|
////////////////////
|
||||||
|
@ -1938,7 +1941,7 @@ class lexer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
explicit lexer(detail::input_adapter_t adapter)
|
explicit lexer(detail::input_adapter_t&& adapter)
|
||||||
: ia(std::move(adapter)), decimal_point_char(get_decimal_point()) {}
|
: ia(std::move(adapter)), decimal_point_char(get_decimal_point()) {}
|
||||||
|
|
||||||
// delete because of pointer members
|
// delete because of pointer members
|
||||||
|
@ -3242,21 +3245,12 @@ struct json_sax
|
||||||
*/
|
*/
|
||||||
virtual bool end_array() = 0;
|
virtual bool end_array() = 0;
|
||||||
|
|
||||||
/*!
|
|
||||||
@brief a binary value was read
|
|
||||||
@param[in] val byte vector
|
|
||||||
@return whether parsing should proceed
|
|
||||||
@note examples are CBOR type 2 strings, MessagePack bin, and maybe UBJSON
|
|
||||||
array<uint8t>
|
|
||||||
*/
|
|
||||||
virtual bool binary(const std::vector<uint8_t>& val) = 0;
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief a parse error occurred
|
@brief a parse error occurred
|
||||||
@param[in] position the position in the input where the error occurs
|
@param[in] position the position in the input where the error occurs
|
||||||
@param[in] last_token the last read token
|
@param[in] last_token the last read token
|
||||||
@param[in] error_msg a detailed error message
|
@param[in] error_msg a detailed error message
|
||||||
@return whether parsing should proceed
|
@return whether parsing should proceed (must return false)
|
||||||
*/
|
*/
|
||||||
virtual bool parse_error(std::size_t position,
|
virtual bool parse_error(std::size_t position,
|
||||||
const std::string& last_token,
|
const std::string& last_token,
|
||||||
|
@ -3362,11 +3356,6 @@ class json_sax_dom_parser : public json_sax<BasicJsonType>
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool binary(const std::vector<uint8_t>&) override
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool parse_error(std::size_t, const std::string&,
|
bool parse_error(std::size_t, const std::string&,
|
||||||
const detail::exception& ex) override
|
const detail::exception& ex) override
|
||||||
{
|
{
|
||||||
|
@ -3567,11 +3556,6 @@ class json_sax_dom_callback_parser : public json_sax<BasicJsonType>
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool binary(const std::vector<uint8_t>&) override
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool parse_error(std::size_t, const std::string&,
|
bool parse_error(std::size_t, const std::string&,
|
||||||
const detail::exception& ex) override
|
const detail::exception& ex) override
|
||||||
{
|
{
|
||||||
|
@ -3717,11 +3701,6 @@ class json_sax_acceptor : public json_sax<BasicJsonType>
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool binary(const std::vector<uint8_t>&) override
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool parse_error(std::size_t, const std::string&, const detail::exception&) override
|
bool parse_error(std::size_t, const std::string&, const detail::exception&) override
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
@ -3783,10 +3762,10 @@ class parser
|
||||||
std::function<bool(int depth, parse_event_t event, BasicJsonType& parsed)>;
|
std::function<bool(int depth, parse_event_t event, BasicJsonType& parsed)>;
|
||||||
|
|
||||||
/// a parser reading from an input adapter
|
/// a parser reading from an input adapter
|
||||||
explicit parser(detail::input_adapter_t adapter,
|
explicit parser(detail::input_adapter_t&& adapter,
|
||||||
const parser_callback_t cb = nullptr,
|
const parser_callback_t cb = nullptr,
|
||||||
const bool allow_exceptions_ = true)
|
const bool allow_exceptions_ = true)
|
||||||
: callback(cb), m_lexer(adapter), allow_exceptions(allow_exceptions_)
|
: callback(cb), m_lexer(std::move(adapter)), allow_exceptions(allow_exceptions_)
|
||||||
{
|
{
|
||||||
// read first token
|
// read first token
|
||||||
get_token();
|
get_token();
|
||||||
|
@ -3883,19 +3862,22 @@ class parser
|
||||||
bool accept(const bool strict = true)
|
bool accept(const bool strict = true)
|
||||||
{
|
{
|
||||||
json_sax_acceptor<BasicJsonType> sax_acceptor;
|
json_sax_acceptor<BasicJsonType> sax_acceptor;
|
||||||
|
return sax_parse(&sax_acceptor, strict);
|
||||||
if (not sax_parse_internal(&sax_acceptor))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// strict => last token must be EOF
|
|
||||||
return not strict or (get_token() == token_type::end_of_input);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sax_parse(json_sax_t* sax)
|
bool sax_parse(json_sax_t* sax, const bool strict = true)
|
||||||
{
|
{
|
||||||
return sax_parse_internal(sax);
|
const bool result = sax_parse_internal(sax);
|
||||||
|
|
||||||
|
// strict mode: next byte must be EOF
|
||||||
|
if (result and strict and (get_token() != token_type::end_of_input))
|
||||||
|
{
|
||||||
|
return sax->parse_error(m_lexer.get_position(),
|
||||||
|
m_lexer.get_token_string(),
|
||||||
|
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -5699,9 +5681,6 @@ class binary_reader
|
||||||
using json_sax_t = json_sax<BasicJsonType>;
|
using json_sax_t = json_sax<BasicJsonType>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// the supported binary input formats
|
|
||||||
enum class binary_format_t { cbor, msgpack, ubjson };
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief create a binary reader
|
@brief create a binary reader
|
||||||
|
|
||||||
|
@ -5719,30 +5698,35 @@ class binary_reader
|
||||||
|
|
||||||
@return
|
@return
|
||||||
*/
|
*/
|
||||||
bool sax_parse(const binary_format_t format, json_sax_t* sax_, const bool strict)
|
bool sax_parse(const input_format_t format,
|
||||||
|
json_sax_t* sax_,
|
||||||
|
const bool strict = true)
|
||||||
{
|
{
|
||||||
sax = sax_;
|
sax = sax_;
|
||||||
bool result;
|
bool result;
|
||||||
|
|
||||||
switch (format)
|
switch (format)
|
||||||
{
|
{
|
||||||
case binary_format_t::cbor:
|
case input_format_t::cbor:
|
||||||
result = parse_cbor_internal();
|
result = parse_cbor_internal();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case binary_format_t::msgpack:
|
case input_format_t::msgpack:
|
||||||
result = parse_msgpack_internal();
|
result = parse_msgpack_internal();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case binary_format_t::ubjson:
|
case input_format_t::ubjson:
|
||||||
result = parse_ubjson_internal();
|
result = parse_ubjson_internal();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
assert(false); // LCOV_EXCL_LINE
|
||||||
}
|
}
|
||||||
|
|
||||||
// strict mode: next byte must be EOF
|
// strict mode: next byte must be EOF
|
||||||
if (result and strict)
|
if (result and strict)
|
||||||
{
|
{
|
||||||
if (format == binary_format_t::ubjson)
|
if (format == input_format_t::ubjson)
|
||||||
{
|
{
|
||||||
get_ignore_noop();
|
get_ignore_noop();
|
||||||
}
|
}
|
||||||
|
@ -10958,6 +10942,8 @@ class basic_json
|
||||||
/// 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>>;
|
||||||
|
|
||||||
|
using input_format_t = detail::input_format_t;
|
||||||
|
|
||||||
////////////////
|
////////////////
|
||||||
// exceptions //
|
// exceptions //
|
||||||
////////////////
|
////////////////
|
||||||
|
@ -16745,7 +16731,7 @@ class basic_json
|
||||||
|
|
||||||
@since version 2.0.3 (contiguous containers)
|
@since version 2.0.3 (contiguous containers)
|
||||||
*/
|
*/
|
||||||
static basic_json parse(detail::input_adapter i,
|
static basic_json parse(detail::input_adapter&& i,
|
||||||
const parser_callback_t cb = nullptr,
|
const parser_callback_t cb = nullptr,
|
||||||
const bool allow_exceptions = true)
|
const bool allow_exceptions = true)
|
||||||
{
|
{
|
||||||
|
@ -16754,36 +16740,23 @@ class basic_json
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
static bool accept(detail::input_adapter&& i)
|
||||||
@copydoc basic_json parse(detail::input_adapter, const parser_callback_t)
|
|
||||||
*/
|
|
||||||
static basic_json parse(detail::input_adapter& i,
|
|
||||||
const parser_callback_t cb = nullptr,
|
|
||||||
const bool allow_exceptions = true)
|
|
||||||
{
|
|
||||||
basic_json result;
|
|
||||||
parser(i, cb, allow_exceptions).parse(true, result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool accept(detail::input_adapter i)
|
|
||||||
{
|
{
|
||||||
return parser(i).accept(true);
|
return parser(i).accept(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool accept(detail::input_adapter& i)
|
static bool sax_parse(detail::input_adapter&& i, json_sax_t* sax,
|
||||||
|
input_format_t format = input_format_t::json,
|
||||||
|
const bool strict = true)
|
||||||
{
|
{
|
||||||
return parser(i).accept(true);
|
assert(sax);
|
||||||
}
|
switch (format)
|
||||||
|
{
|
||||||
static bool sax_parse(detail::input_adapter i, json_sax_t* sax)
|
case input_format_t::json:
|
||||||
{
|
return parser(std::move(i)).sax_parse(sax, strict);
|
||||||
return parser(i).sax_parse(sax);
|
default:
|
||||||
}
|
return binary_reader(std::move(i)).sax_parse(format, sax, strict);
|
||||||
|
}
|
||||||
static bool sax_parse(detail::input_adapter& i, json_sax_t* sax)
|
|
||||||
{
|
|
||||||
return parser(i).sax_parse(sax);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -17388,13 +17361,13 @@ class basic_json
|
||||||
@a strict parameter since 3.0.0; added @allow_exceptions parameter
|
@a strict parameter since 3.0.0; added @allow_exceptions parameter
|
||||||
since 3.2.0
|
since 3.2.0
|
||||||
*/
|
*/
|
||||||
static basic_json from_cbor(detail::input_adapter i,
|
static basic_json from_cbor(detail::input_adapter&& i,
|
||||||
const bool strict = true,
|
const bool strict = true,
|
||||||
const bool allow_exceptions = true)
|
const bool allow_exceptions = true)
|
||||||
{
|
{
|
||||||
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);
|
||||||
const bool res = binary_reader(detail::input_adapter(i)).sax_parse(binary_reader::binary_format_t::cbor, &sdp, strict);
|
const bool res = binary_reader(detail::input_adapter(i)).sax_parse(input_format_t::cbor, &sdp, strict);
|
||||||
return res ? result : basic_json(value_t::discarded);
|
return res ? result : basic_json(value_t::discarded);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17409,7 +17382,7 @@ class basic_json
|
||||||
{
|
{
|
||||||
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);
|
||||||
const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(binary_reader::binary_format_t::cbor, &sdp, strict);
|
const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(input_format_t::cbor, &sdp, strict);
|
||||||
return res ? result : basic_json(value_t::discarded);
|
return res ? result : basic_json(value_t::discarded);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17491,13 +17464,13 @@ class basic_json
|
||||||
@a strict parameter since 3.0.0; added @allow_exceptions parameter
|
@a strict parameter since 3.0.0; added @allow_exceptions parameter
|
||||||
since 3.2.0
|
since 3.2.0
|
||||||
*/
|
*/
|
||||||
static basic_json from_msgpack(detail::input_adapter i,
|
static basic_json from_msgpack(detail::input_adapter&& i,
|
||||||
const bool strict = true,
|
const bool strict = true,
|
||||||
const bool allow_exceptions = true)
|
const bool allow_exceptions = true)
|
||||||
{
|
{
|
||||||
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);
|
||||||
const bool res = binary_reader(detail::input_adapter(i)).sax_parse(binary_reader::binary_format_t::msgpack, &sdp, strict);
|
const bool res = binary_reader(detail::input_adapter(i)).sax_parse(input_format_t::msgpack, &sdp, strict);
|
||||||
return res ? result : basic_json(value_t::discarded);
|
return res ? result : basic_json(value_t::discarded);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17512,7 +17485,7 @@ class basic_json
|
||||||
{
|
{
|
||||||
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);
|
||||||
const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(binary_reader::binary_format_t::msgpack, &sdp, strict);
|
const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(input_format_t::msgpack, &sdp, strict);
|
||||||
return res ? result : basic_json(value_t::discarded);
|
return res ? result : basic_json(value_t::discarded);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17573,13 +17546,13 @@ class basic_json
|
||||||
|
|
||||||
@since version 3.1.0; added @allow_exceptions parameter since 3.2.0
|
@since version 3.1.0; added @allow_exceptions parameter since 3.2.0
|
||||||
*/
|
*/
|
||||||
static basic_json from_ubjson(detail::input_adapter i,
|
static basic_json from_ubjson(detail::input_adapter&& i,
|
||||||
const bool strict = true,
|
const bool strict = true,
|
||||||
const bool allow_exceptions = true)
|
const bool allow_exceptions = true)
|
||||||
{
|
{
|
||||||
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);
|
||||||
const bool res = binary_reader(detail::input_adapter(i)).sax_parse(binary_reader::binary_format_t::ubjson, &sdp, strict);
|
const bool res = binary_reader(detail::input_adapter(i)).sax_parse(input_format_t::ubjson, &sdp, strict);
|
||||||
return res ? result : basic_json(value_t::discarded);
|
return res ? result : basic_json(value_t::discarded);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17594,7 +17567,7 @@ class basic_json
|
||||||
{
|
{
|
||||||
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);
|
||||||
const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(binary_reader::binary_format_t::ubjson, &sdp, strict);
|
const bool res = binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).sax_parse(input_format_t::ubjson, &sdp, strict);
|
||||||
return res ? result : basic_json(value_t::discarded);
|
return res ? result : basic_json(value_t::discarded);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,76 @@ using nlohmann::json;
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
|
class SaxCountdown : public nlohmann::json::json_sax_t
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit SaxCountdown(const int count) : events_left(count)
|
||||||
|
{}
|
||||||
|
|
||||||
|
bool null() override
|
||||||
|
{
|
||||||
|
return events_left-- > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool boolean(bool) override
|
||||||
|
{
|
||||||
|
return events_left-- > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool number_integer(json::number_integer_t) override
|
||||||
|
{
|
||||||
|
return events_left-- > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool number_unsigned(json::number_unsigned_t) override
|
||||||
|
{
|
||||||
|
return events_left-- > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool number_float(json::number_float_t, const std::string&) override
|
||||||
|
{
|
||||||
|
return events_left-- > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool string(std::string&&) override
|
||||||
|
{
|
||||||
|
return events_left-- > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool start_object(std::size_t) override
|
||||||
|
{
|
||||||
|
return events_left-- > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool key(std::string&&) override
|
||||||
|
{
|
||||||
|
return events_left-- > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool end_object() override
|
||||||
|
{
|
||||||
|
return events_left-- > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool start_array(std::size_t) override
|
||||||
|
{
|
||||||
|
return events_left-- > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool end_array() override
|
||||||
|
{
|
||||||
|
return events_left-- > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool parse_error(std::size_t, const std::string&, const json::exception&) override
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int events_left = 0;
|
||||||
|
};
|
||||||
|
|
||||||
TEST_CASE("CBOR")
|
TEST_CASE("CBOR")
|
||||||
{
|
{
|
||||||
SECTION("individual values")
|
SECTION("individual values")
|
||||||
|
@ -1467,6 +1537,30 @@ TEST_CASE("CBOR")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("SAX aborts")
|
||||||
|
{
|
||||||
|
SECTION("start_array(len)")
|
||||||
|
{
|
||||||
|
std::vector<uint8_t> v = {0x83, 0x01, 0x02, 0x03};
|
||||||
|
SaxCountdown scp(0);
|
||||||
|
CHECK(not json::sax_parse(v, &scp, json::input_format_t::cbor));
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("start_object(len)")
|
||||||
|
{
|
||||||
|
std::vector<uint8_t> v = {0xA1, 0x63, 0x66, 0x6F, 0x6F, 0xF4};
|
||||||
|
SaxCountdown scp(0);
|
||||||
|
CHECK(not json::sax_parse(v, &scp, json::input_format_t::cbor));
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("key()")
|
||||||
|
{
|
||||||
|
std::vector<uint8_t> v = {0xA1, 0x63, 0x66, 0x6F, 0x6F, 0xF4};
|
||||||
|
SaxCountdown scp(1);
|
||||||
|
CHECK(not json::sax_parse(v, &scp, json::input_format_t::cbor));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// use this testcase outside [hide] to run it with Valgrind
|
// use this testcase outside [hide] to run it with Valgrind
|
||||||
|
|
|
@ -117,12 +117,6 @@ class SaxEventLogger : public nlohmann::json::json_sax_t
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool binary(const std::vector<uint8_t>&) override
|
|
||||||
{
|
|
||||||
events.push_back("binary()");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool parse_error(std::size_t position, const std::string&, const json::exception&) override
|
bool parse_error(std::size_t position, const std::string&, const json::exception&) override
|
||||||
{
|
{
|
||||||
errored = true;
|
errored = true;
|
||||||
|
@ -195,11 +189,6 @@ class SaxCountdown : public nlohmann::json::json_sax_t
|
||||||
return events_left-- > 0;
|
return events_left-- > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool binary(const std::vector<uint8_t>&) override
|
|
||||||
{
|
|
||||||
return events_left-- > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool parse_error(std::size_t, const std::string&, const json::exception&) override
|
bool parse_error(std::size_t, const std::string&, const json::exception&) override
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
@ -248,7 +237,7 @@ bool accept_helper(const std::string& s)
|
||||||
|
|
||||||
// 4. parse with SAX (compare with relaxed accept result)
|
// 4. parse with SAX (compare with relaxed accept result)
|
||||||
SaxEventLogger el;
|
SaxEventLogger el;
|
||||||
CHECK_NOTHROW(json::sax_parse(s, &el));
|
CHECK_NOTHROW(json::sax_parse(s, &el, json::input_format_t::json, false));
|
||||||
CHECK(json::parser(nlohmann::detail::input_adapter(s)).accept(false) == not el.errored);
|
CHECK(json::parser(nlohmann::detail::input_adapter(s)).accept(false) == not el.errored);
|
||||||
|
|
||||||
// 5. parse with simple callback
|
// 5. parse with simple callback
|
||||||
|
|
|
@ -116,12 +116,6 @@ struct SaxEventLogger : public nlohmann::json::json_sax_t
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool binary(const std::vector<uint8_t>&) override
|
|
||||||
{
|
|
||||||
events.push_back("binary()");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool parse_error(std::size_t position, const std::string&, const json::exception&) override
|
bool parse_error(std::size_t position, const std::string&, const json::exception&) override
|
||||||
{
|
{
|
||||||
events.push_back("parse_error(" + std::to_string(position) + ")");
|
events.push_back("parse_error(" + std::to_string(position) + ")");
|
||||||
|
|
|
@ -33,6 +33,76 @@ using nlohmann::json;
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
|
class SaxCountdown : public nlohmann::json::json_sax_t
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit SaxCountdown(const int count) : events_left(count)
|
||||||
|
{}
|
||||||
|
|
||||||
|
bool null() override
|
||||||
|
{
|
||||||
|
return events_left-- > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool boolean(bool) override
|
||||||
|
{
|
||||||
|
return events_left-- > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool number_integer(json::number_integer_t) override
|
||||||
|
{
|
||||||
|
return events_left-- > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool number_unsigned(json::number_unsigned_t) override
|
||||||
|
{
|
||||||
|
return events_left-- > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool number_float(json::number_float_t, const std::string&) override
|
||||||
|
{
|
||||||
|
return events_left-- > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool string(std::string&&) override
|
||||||
|
{
|
||||||
|
return events_left-- > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool start_object(std::size_t) override
|
||||||
|
{
|
||||||
|
return events_left-- > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool key(std::string&&) override
|
||||||
|
{
|
||||||
|
return events_left-- > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool end_object() override
|
||||||
|
{
|
||||||
|
return events_left-- > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool start_array(std::size_t) override
|
||||||
|
{
|
||||||
|
return events_left-- > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool end_array() override
|
||||||
|
{
|
||||||
|
return events_left-- > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool parse_error(std::size_t, const std::string&, const json::exception&) override
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int events_left = 0;
|
||||||
|
};
|
||||||
|
|
||||||
TEST_CASE("MessagePack")
|
TEST_CASE("MessagePack")
|
||||||
{
|
{
|
||||||
SECTION("individual values")
|
SECTION("individual values")
|
||||||
|
@ -1200,6 +1270,30 @@ TEST_CASE("MessagePack")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("SAX aborts")
|
||||||
|
{
|
||||||
|
SECTION("start_array(len)")
|
||||||
|
{
|
||||||
|
std::vector<uint8_t> v = {0x93, 0x01, 0x02, 0x03};
|
||||||
|
SaxCountdown scp(0);
|
||||||
|
CHECK(not json::sax_parse(v, &scp, json::input_format_t::msgpack));
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("start_object(len)")
|
||||||
|
{
|
||||||
|
std::vector<uint8_t> v = {0x81, 0xa3, 0x66, 0x6F, 0x6F, 0xc2};
|
||||||
|
SaxCountdown scp(0);
|
||||||
|
CHECK(not json::sax_parse(v, &scp, json::input_format_t::msgpack));
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("key()")
|
||||||
|
{
|
||||||
|
std::vector<uint8_t> v = {0x81, 0xa3, 0x66, 0x6F, 0x6F, 0xc2};
|
||||||
|
SaxCountdown scp(1);
|
||||||
|
CHECK(not json::sax_parse(v, &scp, json::input_format_t::msgpack));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,76 @@ using nlohmann::json;
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
|
class SaxCountdown : public nlohmann::json::json_sax_t
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit SaxCountdown(const int count) : events_left(count)
|
||||||
|
{}
|
||||||
|
|
||||||
|
bool null() override
|
||||||
|
{
|
||||||
|
return events_left-- > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool boolean(bool) override
|
||||||
|
{
|
||||||
|
return events_left-- > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool number_integer(json::number_integer_t) override
|
||||||
|
{
|
||||||
|
return events_left-- > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool number_unsigned(json::number_unsigned_t) override
|
||||||
|
{
|
||||||
|
return events_left-- > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool number_float(json::number_float_t, const std::string&) override
|
||||||
|
{
|
||||||
|
return events_left-- > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool string(std::string&&) override
|
||||||
|
{
|
||||||
|
return events_left-- > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool start_object(std::size_t) override
|
||||||
|
{
|
||||||
|
return events_left-- > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool key(std::string&&) override
|
||||||
|
{
|
||||||
|
return events_left-- > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool end_object() override
|
||||||
|
{
|
||||||
|
return events_left-- > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool start_array(std::size_t) override
|
||||||
|
{
|
||||||
|
return events_left-- > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool end_array() override
|
||||||
|
{
|
||||||
|
return events_left-- > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool parse_error(std::size_t, const std::string&, const json::exception&) override
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int events_left = 0;
|
||||||
|
};
|
||||||
|
|
||||||
TEST_CASE("UBJSON")
|
TEST_CASE("UBJSON")
|
||||||
{
|
{
|
||||||
SECTION("individual values")
|
SECTION("individual values")
|
||||||
|
@ -1241,6 +1311,51 @@ TEST_CASE("UBJSON")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("SAX aborts")
|
||||||
|
{
|
||||||
|
SECTION("start_array()")
|
||||||
|
{
|
||||||
|
std::vector<uint8_t> v = {'[', 'T', 'F', ']'};
|
||||||
|
SaxCountdown scp(0);
|
||||||
|
CHECK(not json::sax_parse(v, &scp, json::input_format_t::ubjson));
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("start_object()")
|
||||||
|
{
|
||||||
|
std::vector<uint8_t> v = {'{', 'i', 3, 'f', 'o', 'o', 'F', '}'};
|
||||||
|
SaxCountdown scp(0);
|
||||||
|
CHECK(not json::sax_parse(v, &scp, json::input_format_t::ubjson));
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("key() in object")
|
||||||
|
{
|
||||||
|
std::vector<uint8_t> v = {'{', 'i', 3, 'f', 'o', 'o', 'F', '}'};
|
||||||
|
SaxCountdown scp(1);
|
||||||
|
CHECK(not json::sax_parse(v, &scp, json::input_format_t::ubjson));
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("start_array(len)")
|
||||||
|
{
|
||||||
|
std::vector<uint8_t> v = {'[', '#', 'i', '2', 'T', 'F'};
|
||||||
|
SaxCountdown scp(0);
|
||||||
|
CHECK(not json::sax_parse(v, &scp, json::input_format_t::ubjson));
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("start_object(len)")
|
||||||
|
{
|
||||||
|
std::vector<uint8_t> v = {'{', '#', 'i', '1', 3, 'f', 'o', 'o', 'F'};
|
||||||
|
SaxCountdown scp(0);
|
||||||
|
CHECK(not json::sax_parse(v, &scp, json::input_format_t::ubjson));
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("key() in object with length")
|
||||||
|
{
|
||||||
|
std::vector<uint8_t> v = {'{', 'i', 3, 'f', 'o', 'o', 'F', '}'};
|
||||||
|
SaxCountdown scp(1);
|
||||||
|
CHECK(not json::sax_parse(v, &scp, json::input_format_t::ubjson));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SECTION("parsing values")
|
SECTION("parsing values")
|
||||||
{
|
{
|
||||||
SECTION("strings")
|
SECTION("strings")
|
||||||
|
|
Loading…
Reference in a new issue