implemented non-throwing binary reader

parent a271ee5f
...@@ -41,6 +41,9 @@ class binary_reader ...@@ -41,6 +41,9 @@ 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
...@@ -52,77 +55,50 @@ class binary_reader ...@@ -52,77 +55,50 @@ class binary_reader
} }
/*! /*!
@brief create a JSON value from CBOR input @param[in] format the binary format to parse
@param[in] sax_ a SAX event processor
@param[in] strict whether to expect the input to be consumed completed @param[in] strict whether to expect the input to be consumed completed
@return JSON value created from CBOR input
@throw parse_error.110 if input ended unexpectedly or the end of file was @return
not reached when @a strict was set to true
@throw parse_error.112 if unsupported byte was read
*/ */
BasicJsonType parse_cbor(const bool strict) bool sax_parse(const binary_format_t format, json_sax_t* sax_, const bool strict)
{ {
BasicJsonType result; sax = sax_;
json_sax_dom_parser<BasicJsonType> sdp(result); bool result;
sax = &sdp;
parse_cbor_internal(); switch (format)
result.assert_invariant();
if (strict)
{ {
get(); case binary_format_t::cbor:
expect_eof(); result = parse_cbor_internal();
} break;
return result;
}
/*! case binary_format_t::msgpack:
@brief create a JSON value from MessagePack input result = parse_msgpack_internal();
break;
@param[in] strict whether to expect the input to be consumed completed case binary_format_t::ubjson:
@return JSON value created from MessagePack input result = parse_ubjson_internal();
break;
}
@throw parse_error.110 if input ended unexpectedly or the end of file was // strict mode: next byte must be EOF
not reached when @a strict was set to true if (result and strict)
@throw parse_error.112 if unsupported byte was read
*/
BasicJsonType parse_msgpack(const bool strict)
{ {
BasicJsonType result; if (format == binary_format_t::ubjson)
json_sax_dom_parser<BasicJsonType> sdp(result);
sax = &sdp;
parse_msgpack_internal();
result.assert_invariant();
if (strict)
{ {
get(); get_ignore_noop();
expect_eof();
} }
return result; else
{
get();
} }
/*! if (JSON_UNLIKELY(current != std::char_traits<char>::eof()))
@brief create a JSON value from UBJSON input
@param[in] strict whether to expect the input to be consumed completed
@return JSON value created from UBJSON input
@throw parse_error.110 if input ended unexpectedly or the end of file was
not reached when @a strict was set to true
@throw parse_error.112 if unsupported byte was read
*/
BasicJsonType parse_ubjson(const bool strict)
{
BasicJsonType result;
json_sax_dom_parser<BasicJsonType> sdp(result);
sax = &sdp;
parse_ubjson_internal();
result.assert_invariant();
if (strict)
{ {
get_ignore_noop(); return sax->parse_error(chars_read, get_token_string(), parse_error::create(110, chars_read, "expected end of input"));
expect_eof(); }
} }
return result; return result;
} }
...@@ -1662,18 +1638,6 @@ class binary_reader ...@@ -1662,18 +1638,6 @@ class binary_reader
return sax->end_object(); return sax->end_object();
} }
/*!
@return whether input was completely read
*/
bool expect_eof() const
{
if (JSON_UNLIKELY(current != std::char_traits<char>::eof()))
{
return sax->parse_error(chars_read, get_token_string(), parse_error::create(110, chars_read, "expected end of input"));
}
return true;
}
/*! /*!
@return whether the last read character is not EOF @return whether the last read character is not EOF
*/ */
......
...@@ -6611,6 +6611,9 @@ class basic_json ...@@ -6611,6 +6611,9 @@ class basic_json
@param[in] i an input in CBOR format convertible to an input adapter @param[in] i an input in CBOR format convertible to an input adapter
@param[in] strict whether to expect the input to be consumed until EOF @param[in] strict whether to expect the input to be consumed until EOF
(true by default) (true by default)
@param[in] allow_exceptions whether to throw exceptions in case of a
parse error (optional, true by default)
@return deserialized JSON value @return deserialized JSON value
@throw parse_error.110 if the given input ends prematurely or the end of @throw parse_error.110 if the given input ends prematurely or the end of
...@@ -6636,9 +6639,13 @@ class basic_json ...@@ -6636,9 +6639,13 @@ class basic_json
@a strict parameter since 3.0.0 @a strict parameter since 3.0.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)
{ {
return binary_reader(i).parse_cbor(strict); basic_json result;
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);
return res ? result : basic_json(value_t::discarded);
} }
/*! /*!
...@@ -6646,9 +6653,14 @@ class basic_json ...@@ -6646,9 +6653,14 @@ class basic_json
*/ */
template<typename A1, typename A2, template<typename A1, typename A2,
detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0> detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
static basic_json from_cbor(A1 && a1, A2 && a2, const bool strict = true) static basic_json from_cbor(A1 && a1, A2 && a2,
const bool strict = true,
const bool allow_exceptions = true)
{ {
return binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).parse_cbor(strict); basic_json result;
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);
return res ? result : basic_json(value_t::discarded);
} }
/*! /*!
...@@ -6701,6 +6713,10 @@ class basic_json ...@@ -6701,6 +6713,10 @@ class basic_json
adapter adapter
@param[in] strict whether to expect the input to be consumed until EOF @param[in] strict whether to expect the input to be consumed until EOF
(true by default) (true by default)
@param[in] allow_exceptions whether to throw exceptions in case of a
parse error (optional, true by default)
@return deserialized JSON value
@throw parse_error.110 if the given input ends prematurely or the end of @throw parse_error.110 if the given input ends prematurely or the end of
file was not reached when @a strict was set to true file was not reached when @a strict was set to true
...@@ -6725,9 +6741,13 @@ class basic_json ...@@ -6725,9 +6741,13 @@ class basic_json
@a strict parameter since 3.0.0 @a strict parameter since 3.0.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)
{ {
return binary_reader(i).parse_msgpack(strict); basic_json result;
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);
return res ? result : basic_json(value_t::discarded);
} }
/*! /*!
...@@ -6735,9 +6755,14 @@ class basic_json ...@@ -6735,9 +6755,14 @@ class basic_json
*/ */
template<typename A1, typename A2, template<typename A1, typename A2,
detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0> detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
static basic_json from_msgpack(A1 && a1, A2 && a2, const bool strict = true) static basic_json from_msgpack(A1 && a1, A2 && a2,
const bool strict = true,
const bool allow_exceptions = true)
{ {
return binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).parse_msgpack(strict); basic_json result;
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);
return res ? result : basic_json(value_t::discarded);
} }
/*! /*!
...@@ -6772,6 +6797,10 @@ class basic_json ...@@ -6772,6 +6797,10 @@ class basic_json
@param[in] i an input in UBJSON format convertible to an input adapter @param[in] i an input in UBJSON format convertible to an input adapter
@param[in] strict whether to expect the input to be consumed until EOF @param[in] strict whether to expect the input to be consumed until EOF
(true by default) (true by default)
@param[in] allow_exceptions whether to throw exceptions in case of a
parse error (optional, true by default)
@return deserialized JSON value
@throw parse_error.110 if the given input ends prematurely or the end of @throw parse_error.110 if the given input ends prematurely or the end of
file was not reached when @a strict was set to true file was not reached when @a strict was set to true
...@@ -6794,16 +6823,25 @@ class basic_json ...@@ -6794,16 +6823,25 @@ class basic_json
@since version 3.1.0 @since version 3.1.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)
{ {
return binary_reader(i).parse_ubjson(strict); basic_json result;
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);
return res ? result : basic_json(value_t::discarded);
} }
template<typename A1, typename A2, template<typename A1, typename A2,
detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0> detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
static basic_json from_ubjson(A1 && a1, A2 && a2, const bool strict = true) static basic_json from_ubjson(A1 && a1, A2 && a2,
const bool strict = true,
const bool allow_exceptions = true)
{ {
return binary_reader(detail::input_adapter(std::forward<A1>(a1), std::forward<A2>(a2))).parse_ubjson(strict); basic_json result;
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);
return res ? result : basic_json(value_t::discarded);
} }
/// @} /// @}
......
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment