diff --git a/src/json.hpp b/src/json.hpp index 9754e464c..35c0b9781 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -91,6 +91,7 @@ SOFTWARE. // allow to disable exceptions #if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && not defined(JSON_NOEXCEPTION) + #define JSON_EXCEPTIONS_ENABLED #define JSON_THROW(exception) throw exception #define JSON_TRY try #define JSON_CATCH(exception) catch(exception) @@ -202,11 +203,18 @@ caught.,exception} class exception : public std::exception { public: - /// returns the explanatory string + /// returns the explanatory string. +#if defined(JSON_EXCEPTIONS_ENABLED) const char* what() const noexcept override { return m.what(); } +#else + const char* what() const noexcept override + { + return m.c_str(); + } +#endif /// the id of the exception const int id; @@ -220,8 +228,16 @@ class exception : public std::exception } private: +#if defined(JSON_EXCEPTIONS_ENABLED) /// an exception object as storage for error messages std::runtime_error m; +#else + /// if exceptions are disabled then std::runtime_error is not + /// guaranteed to contain storage for the string. Use std::string + /// instead because we aren't actually throwing this object. Just + /// passing it back as an out param. + std::string m; +#endif }; /*! @@ -278,12 +294,9 @@ class parse_error : public exception @param[in] what_arg the explanatory string @return parse_error object */ - static parse_error create(int id_, std::size_t byte_, const std::string& what_arg) + parse_error(int id_, std::size_t byte_, const std::string& what_arg) + : exception(id_, format_what(id_, byte_, what_arg).c_str()), byte(byte_) { - std::string w = exception::name("parse_error", id_) + "parse error" + - (byte_ != 0 ? (" at " + std::to_string(byte_)) : "") + - ": " + what_arg; - return parse_error(id_, byte_, w.c_str()); } /*! @@ -297,9 +310,13 @@ class parse_error : public exception */ const std::size_t byte; - private: - parse_error(int id_, std::size_t byte_, const char* what_arg) - : exception(id_, what_arg), byte(byte_) {} + std::string format_what(int id_, std::size_t byte_, const std::string& what_arg) const + { + return + exception::name("parse_error", id_) + "parse error" + + (byte_ != 0 ? (" at " + std::to_string(byte_)) : "") + + ": " + what_arg; + } }; /*! @@ -342,15 +359,14 @@ caught.,invalid_iterator} class invalid_iterator : public exception { public: - static invalid_iterator create(int id_, const std::string& what_arg) - { - std::string w = exception::name("invalid_iterator", id_) + what_arg; - return invalid_iterator(id_, w.c_str()); - } + invalid_iterator(int id_, const std::string& what_arg) + : exception(id_, format_what(id_, what_arg).c_str()) {} private: - invalid_iterator(int id_, const char* what_arg) - : exception(id_, what_arg) {} + static std::string format_what(int id_, const std::string& what_arg) + { + return exception::name("invalid_iterator", id_) + what_arg; + } }; /*! @@ -393,14 +409,14 @@ caught.,type_error} class type_error : public exception { public: - static type_error create(int id_, const std::string& what_arg) - { - std::string w = exception::name("type_error", id_) + what_arg; - return type_error(id_, w.c_str()); - } + type_error(int id_, const std::string& what_arg) + : exception(id_, format_what(id_, what_arg).c_str()) {} private: - type_error(int id_, const char* what_arg) : exception(id_, what_arg) {} + static std::string format_what(int id_, const std::string& what_arg) + { + return exception::name("type_error", id_) + what_arg; + } }; /*! @@ -436,14 +452,14 @@ caught.,out_of_range} class out_of_range : public exception { public: - static out_of_range create(int id_, const std::string& what_arg) - { - std::string w = exception::name("out_of_range", id_) + what_arg; - return out_of_range(id_, w.c_str()); - } + out_of_range(int id_, const std::string& what_arg) + : exception(id_, format_what(id_, what_arg).c_str()) {} private: - out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {} + static std::string format_what(int id_, const std::string& what_arg) + { + return exception::name("out_of_range", id_) + what_arg; + } }; /*! @@ -474,16 +490,54 @@ caught.,other_error} class other_error : public exception { public: - static other_error create(int id_, const std::string& what_arg) - { - std::string w = exception::name("other_error", id_) + what_arg; - return other_error(id_, w.c_str()); - } + other_error(int id_, const std::string& what_arg) : + exception(id_, format_what(id_, what_arg).c_str()) {} private: - other_error(int id_, const char* what_arg) : exception(id_, what_arg) {} + static std::string format_what(int id_, const std::string& what_arg) + { + return exception::name("other_error", id_) + what_arg; + } }; +/*! +@brief helper function to throw a downcasted exception. +*/ +#ifdef JSON_EXCEPTIONS_ENABLED +template +void try_throw_exception(exception* ex) +{ + // Only use RTTI if necessary (exceptions are enabled). This way + // can be compiled with no RTTI. + Exception* down = dynamic_cast(ex); + if(down != nullptr) + { + JSON_THROW(*down); + } +} +#else +template +void try_throw_exception(exception* /*unused*/) +{ + std::abort(); +} +#endif + +/*! +@brief helper function to throw the correct downcasted exception. +*/ +void try_throw_any_exception(exception* ex) +{ + if (ex != nullptr) + { + try_throw_exception(ex); + try_throw_exception(ex); + try_throw_exception(ex); + try_throw_exception(ex); + try_throw_exception(ex); // LCOV_EXCL_LINE + assert(false); // LCOV_EXCL_LINE + } +} /////////////////////////// @@ -1111,7 +1165,7 @@ void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val) } default: - JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()))); + JSON_THROW(type_error(302, "type must be number, but is " + std::string(j.type_name()))); } } @@ -1120,7 +1174,7 @@ void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b) { if (JSON_UNLIKELY(not j.is_boolean())) { - JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(j.type_name()))); + JSON_THROW(type_error(302, "type must be boolean, but is " + std::string(j.type_name()))); } b = *j.template get_ptr(); } @@ -1130,7 +1184,7 @@ void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s) { if (JSON_UNLIKELY(not j.is_string())) { - JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()))); + JSON_THROW(type_error(302, "type must be string, but is " + std::string(j.type_name()))); } s = *j.template get_ptr(); } @@ -1167,7 +1221,7 @@ void from_json(const BasicJsonType& j, typename BasicJsonType::array_t& arr) { if (JSON_UNLIKELY(not j.is_array())) { - JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()))); + JSON_THROW(type_error(302, "type must be array, but is " + std::string(j.type_name()))); } arr = *j.template get_ptr(); } @@ -1179,7 +1233,7 @@ void from_json(const BasicJsonType& j, std::forward_list& l) { if (JSON_UNLIKELY(not j.is_array())) { - JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()))); + JSON_THROW(type_error(302, "type must be array, but is " + std::string(j.type_name()))); } std::transform(j.rbegin(), j.rend(), std::front_inserter(l), [](const BasicJsonType & i) @@ -1195,7 +1249,7 @@ void from_json(const BasicJsonType& j, std::valarray& l) { if (JSON_UNLIKELY(not j.is_array())) { - JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()))); + JSON_THROW(type_error(302, "type must be array, but is " + std::string(j.type_name()))); } l.resize(j.size()); std::copy(j.m_value.array->begin(), j.m_value.array->end(), std::begin(l)); @@ -1250,7 +1304,7 @@ void from_json(const BasicJsonType& j, CompatibleArrayType& arr) { if (JSON_UNLIKELY(not j.is_array())) { - JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()))); + JSON_THROW(type_error(302, "type must be array, but is " + std::string(j.type_name()))); } from_json_array_impl(j, arr, priority_tag<2> {}); @@ -1262,7 +1316,7 @@ void from_json(const BasicJsonType& j, CompatibleObjectType& obj) { if (JSON_UNLIKELY(not j.is_object())) { - JSON_THROW(type_error::create(302, "type must be object, but is " + std::string(j.type_name()))); + JSON_THROW(type_error(302, "type must be object, but is " + std::string(j.type_name()))); } auto inner_object = j.template get_ptr(); @@ -1314,7 +1368,7 @@ void from_json(const BasicJsonType& j, ArithmeticType& val) } default: - JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()))); + JSON_THROW(type_error(302, "type must be number, but is " + std::string(j.type_name()))); } } @@ -2929,10 +2983,8 @@ class parser std::function; /// a parser reading from an input adapter - explicit parser(detail::input_adapter_t adapter, - const parser_callback_t cb = nullptr, - const bool allow_exceptions_ = true) - : callback(cb), m_lexer(adapter), allow_exceptions(allow_exceptions_) + explicit parser(detail::input_adapter_t adapter, const parser_callback_t cb = nullptr) + : callback(cb), m_lexer(adapter) {} /*! @@ -2944,20 +2996,35 @@ class parser @throw parse_error.101 in case of an unexpected token @throw parse_error.102 if to_unicode fails or surrogate error @throw parse_error.103 if to_unicode fails + @throw out_of_range 406 if float not finite */ void parse(const bool strict, BasicJsonType& result) + { + std::unique_ptr ex; + parse(strict, result, ex); + try_throw_any_exception(ex.get()); + } + + /*! + @brief public parser interface + + @param[in] strict whether to expect the last token to be EOF + @param[in,out] result parsed JSON value + @param[in,out] ex exception raised while parsing (not thrown) + */ + void parse(const bool strict, BasicJsonType& result, std::unique_ptr& ex) { // read first token get_token(); - parse_internal(true, result); + parse_internal(true, result, ex); result.assert_invariant(); // in strict mode, input must be completely read - if (strict) + if (!errored && strict) { get_token(); - expect(token_type::end_of_input); + expect(token_type::end_of_input, ex); } // in case of an error, return discarded value @@ -3002,7 +3069,7 @@ class parser @throw parse_error.102 if to_unicode fails or surrogate error @throw parse_error.103 if to_unicode fails */ - void parse_internal(bool keep, BasicJsonType& result) + void parse_internal(bool keep, BasicJsonType& result, std::unique_ptr& ex) { // never parse after a parse error was detected assert(not errored); @@ -3053,7 +3120,7 @@ class parser while (true) { // store key - if (not expect(token_type::value_string)) + if (not expect(token_type::value_string, ex)) { return; } @@ -3075,7 +3142,7 @@ class parser // parse separator (:) get_token(); - if (not expect(token_type::name_separator)) + if (not expect(token_type::name_separator, ex)) { return; } @@ -3084,7 +3151,7 @@ class parser get_token(); value.m_value.destroy(value.m_type); value.m_type = value_t::discarded; - parse_internal(keep, value); + parse_internal(keep, value, ex); if (JSON_UNLIKELY(errored)) { @@ -3105,7 +3172,7 @@ class parser } // closing } - if (not expect(token_type::end_object)) + if (not expect(token_type::end_object, ex)) { return; } @@ -3158,7 +3225,7 @@ class parser // parse value value.m_value.destroy(value.m_type); value.m_type = value_t::discarded; - parse_internal(keep, value); + parse_internal(keep, value, ex); if (JSON_UNLIKELY(errored)) { @@ -3179,7 +3246,7 @@ class parser } // closing ] - if (not expect(token_type::end_array)) + if (not expect(token_type::end_array, ex)) { return; } @@ -3243,12 +3310,9 @@ class parser // throw in case of infinity or NAN if (JSON_UNLIKELY(not std::isfinite(result.m_value.number_float))) { - if (allow_exceptions) - { - JSON_THROW(out_of_range::create(406, "number overflow parsing '" + - m_lexer.get_token_string() + "'")); - } - expect(token_type::uninitialized); + ex = std::unique_ptr(new out_of_range(406, "number overflow parsing '" + m_lexer.get_token_string() + "'")); + errored = true; + return; } break; } @@ -3256,7 +3320,7 @@ class parser case token_type::parse_error: { // using "uninitialized" to avoid "expected" message - if (not expect(token_type::uninitialized)) + if (not expect(token_type::uninitialized, ex)) { return; } @@ -3266,7 +3330,7 @@ class parser default: { // the last token was unexpected; we expected a value - if (not expect(token_type::literal_or_value)) + if (not expect(token_type::literal_or_value, ex)) { return; } @@ -3402,26 +3466,20 @@ class parser /*! @throw parse_error.101 if expected token did not occur */ - bool expect(token_type t) + bool expect(token_type t, std::unique_ptr& ex) { if (JSON_UNLIKELY(t != last_token)) { errored = true; expected = t; - if (allow_exceptions) - { - throw_exception(); - } - else - { - return false; - } + ex = std::move(make_expect_exception()); + return false; } return true; } - [[noreturn]] void throw_exception() const + std::unique_ptr make_expect_exception() const { std::string error_msg = "syntax error - "; if (last_token == token_type::parse_error) @@ -3439,7 +3497,7 @@ class parser error_msg += "; expected " + std::string(lexer_t::token_type_name(expected)); } - JSON_THROW(parse_error::create(101, m_lexer.get_position(), error_msg)); + return std::unique_ptr(new parse_error(101, m_lexer.get_position(), error_msg)); } private: @@ -3455,8 +3513,6 @@ class parser bool errored = false; /// possible reason for the syntax error token_type expected = token_type::uninitialized; - /// whether to throw exceptions in case of errors - const bool allow_exceptions = true; }; /////////////// @@ -3803,7 +3859,7 @@ class iter_impl : public std::iteratorm_type) { case value_t::object: - JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators")); + JSON_THROW(invalid_iterator(213, "cannot compare order of object iterators")); case value_t::array: return (m_it.array_iterator < other.m_it.array_iterator); @@ -4038,7 +4094,7 @@ class iter_impl : public std::iteratorm_type) { case value_t::object: - JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators")); + JSON_THROW(invalid_iterator(209, "cannot use offsets with object iterators")); case value_t::array: { @@ -4109,7 +4165,7 @@ class iter_impl : public std::iteratorm_type) { case value_t::object: - JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators")); + JSON_THROW(invalid_iterator(209, "cannot use offsets with object iterators")); case value_t::array: return m_it.array_iterator - other.m_it.array_iterator; @@ -4130,13 +4186,13 @@ class iter_impl : public std::iteratorm_type) { case value_t::object: - JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators")); + JSON_THROW(invalid_iterator(208, "cannot use operator[] for object iterators")); case value_t::array: return *std::next(m_it.array_iterator, n); case value_t::null: - JSON_THROW(invalid_iterator::create(214, "cannot get value")); + JSON_THROW(invalid_iterator(214, "cannot get value")); default: { @@ -4145,7 +4201,7 @@ class iter_impl : public std::iteratorfirst; } - JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators")); + JSON_THROW(invalid_iterator(207, "cannot use key() for non-object iterators")); } /*! @@ -4563,7 +4619,7 @@ class binary_reader { // EOF case std::char_traits::eof(): - JSON_THROW(parse_error::create(110, chars_read, "unexpected end of input")); + JSON_THROW(parse_error(110, chars_read, "unexpected end of input")); // Integer 0x00..0x17 (0..23) case 0x00: @@ -4870,7 +4926,7 @@ class binary_reader { std::stringstream ss; ss << std::setw(2) << std::setfill('0') << std::hex << current; - JSON_THROW(parse_error::create(112, chars_read, "error reading CBOR; last byte: 0x" + ss.str())); + JSON_THROW(parse_error(112, chars_read, "error reading CBOR; last byte: 0x" + ss.str())); } } } @@ -4881,7 +4937,7 @@ class binary_reader { // EOF case std::char_traits::eof(): - JSON_THROW(parse_error::create(110, chars_read, "unexpected end of input")); + JSON_THROW(parse_error(110, chars_read, "unexpected end of input")); // positive fixint case 0x00: @@ -5194,7 +5250,7 @@ class binary_reader { std::stringstream ss; ss << std::setw(2) << std::setfill('0') << std::hex << current; - JSON_THROW(parse_error::create(112, chars_read, + JSON_THROW(parse_error(112, chars_read, "error reading MessagePack; last byte: 0x" + ss.str())); } } @@ -5362,7 +5418,7 @@ class binary_reader { std::stringstream ss; ss << std::setw(2) << std::setfill('0') << std::hex << current; - JSON_THROW(parse_error::create(113, chars_read, "expected a CBOR string; last byte: 0x" + ss.str())); + JSON_THROW(parse_error(113, chars_read, "expected a CBOR string; last byte: 0x" + ss.str())); } } } @@ -5467,7 +5523,7 @@ class binary_reader { std::stringstream ss; ss << std::setw(2) << std::setfill('0') << std::hex << current; - JSON_THROW(parse_error::create(113, chars_read, + JSON_THROW(parse_error(113, chars_read, "expected a MessagePack string; last byte: 0x" + ss.str())); } } @@ -5510,14 +5566,14 @@ class binary_reader { if (JSON_UNLIKELY(current != std::char_traits::eof())) { - JSON_THROW(parse_error::create(110, chars_read, "expected end of input")); + JSON_THROW(parse_error(110, chars_read, "expected end of input")); } } else { if (JSON_UNLIKELY(current == std::char_traits::eof())) { - JSON_THROW(parse_error::create(110, chars_read, "unexpected end of input")); + JSON_THROW(parse_error(110, chars_read, "unexpected end of input")); } } } @@ -6958,7 +7014,7 @@ class json_pointer { if (JSON_UNLIKELY(is_root())) { - JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent")); + JSON_THROW(detail::out_of_range(405, "JSON pointer has no parent")); } auto last = reference_tokens.back(); @@ -6976,7 +7032,7 @@ class json_pointer { if (JSON_UNLIKELY(is_root())) { - JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent")); + JSON_THROW(detail::out_of_range(405, "JSON pointer has no parent")); } json_pointer result = *this; @@ -7074,9 +7130,9 @@ class json_pointer // check if nonempty reference string begins with slash if (JSON_UNLIKELY(reference_string[0] != '/')) { - JSON_THROW(detail::parse_error::create(107, 1, - "JSON pointer must be empty or begin with '/' - was: '" + - reference_string + "'")); + JSON_THROW(detail::parse_error(107, 1, + "JSON pointer must be empty or begin with '/' - was: '" + + reference_string + "'")); } // extract the reference tokens: @@ -7111,7 +7167,7 @@ class json_pointer (reference_token[pos + 1] != '0' and reference_token[pos + 1] != '1'))) { - JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'")); + JSON_THROW(detail::parse_error(108, 0, "escape character '~' must be followed with '0' or '1'")); } } @@ -8054,7 +8110,7 @@ class basic_json object = nullptr; // silence warning, see #821 if (JSON_UNLIKELY(t == value_t::null)) { - JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 2.1.1")); // LCOV_EXCL_LINE + JSON_THROW(other_error(500, "961c151d2e87f2686a955a9be24d316f1362bf21 2.1.1")); // LCOV_EXCL_LINE } break; } @@ -8444,7 +8500,7 @@ class basic_json // if object is wanted but impossible, throw an exception if (JSON_UNLIKELY(manual_type == value_t::object and not is_an_object)) { - JSON_THROW(type_error::create(301, "cannot create object from initializer list")); + JSON_THROW(type_error(301, "cannot create object from initializer list")); } } @@ -8652,7 +8708,7 @@ class basic_json // make sure iterator fits the current value if (JSON_UNLIKELY(first.m_object != last.m_object)) { - JSON_THROW(invalid_iterator::create(201, "iterators are not compatible")); + JSON_THROW(invalid_iterator(201, "iterators are not compatible")); } // copy type from first iterator @@ -8670,7 +8726,7 @@ class basic_json if (JSON_UNLIKELY(not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())) { - JSON_THROW(invalid_iterator::create(204, "iterators out of range")); + JSON_THROW(invalid_iterator(204, "iterators out of range")); } break; } @@ -8726,7 +8782,7 @@ class basic_json } default: - JSON_THROW(invalid_iterator::create(206, "cannot construct with iterators from " + + JSON_THROW(invalid_iterator(206, "cannot construct with iterators from " + std::string(first.m_object->type_name()))); } @@ -9376,7 +9432,7 @@ class basic_json return m_value.boolean; } - JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(type_name()))); + JSON_THROW(type_error(302, "type must be boolean, but is " + std::string(type_name()))); } /// get a pointer to the value (object) @@ -9485,7 +9541,7 @@ class basic_json return *ptr; } - JSON_THROW(type_error::create(303, "incompatible ReferenceType for get_ref, actual type is " + std::string(obj.type_name()))); + JSON_THROW(type_error(303, "incompatible ReferenceType for get_ref, actual type is " + std::string(obj.type_name()))); } public: @@ -9891,12 +9947,12 @@ class basic_json JSON_CATCH (std::out_of_range&) { // create better exception explanation - JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range")); + JSON_THROW(out_of_range(401, "array index " + std::to_string(idx) + " is out of range")); } } else { - JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()))); + JSON_THROW(type_error(304, "cannot use at() with " + std::string(type_name()))); } } @@ -9938,12 +9994,12 @@ class basic_json JSON_CATCH (std::out_of_range&) { // create better exception explanation - JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range")); + JSON_THROW(out_of_range(401, "array index " + std::to_string(idx) + " is out of range")); } } else { - JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()))); + JSON_THROW(type_error(304, "cannot use at() with " + std::string(type_name()))); } } @@ -9989,12 +10045,12 @@ class basic_json JSON_CATCH (std::out_of_range&) { // create better exception explanation - JSON_THROW(out_of_range::create(403, "key '" + key + "' not found")); + JSON_THROW(out_of_range(403, "key '" + key + "' not found")); } } else { - JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()))); + JSON_THROW(type_error(304, "cannot use at() with " + std::string(type_name()))); } } @@ -10040,12 +10096,12 @@ class basic_json JSON_CATCH (std::out_of_range&) { // create better exception explanation - JSON_THROW(out_of_range::create(403, "key '" + key + "' not found")); + JSON_THROW(out_of_range(403, "key '" + key + "' not found")); } } else { - JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()))); + JSON_THROW(type_error(304, "cannot use at() with " + std::string(type_name()))); } } @@ -10098,7 +10154,7 @@ class basic_json return m_value.array->operator[](idx); } - JSON_THROW(type_error::create(305, "cannot use operator[] with " + std::string(type_name()))); + JSON_THROW(type_error(305, "cannot use operator[] with " + std::string(type_name()))); } /*! @@ -10128,7 +10184,7 @@ class basic_json return m_value.array->operator[](idx); } - JSON_THROW(type_error::create(305, "cannot use operator[] with " + std::string(type_name()))); + JSON_THROW(type_error(305, "cannot use operator[] with " + std::string(type_name()))); } /*! @@ -10174,7 +10230,7 @@ class basic_json return m_value.object->operator[](key); } - JSON_THROW(type_error::create(305, "cannot use operator[] with " + std::string(type_name()))); + JSON_THROW(type_error(305, "cannot use operator[] with " + std::string(type_name()))); } /*! @@ -10216,7 +10272,7 @@ class basic_json return m_value.object->find(key)->second; } - JSON_THROW(type_error::create(305, "cannot use operator[] with " + std::string(type_name()))); + JSON_THROW(type_error(305, "cannot use operator[] with " + std::string(type_name()))); } /*! @@ -10263,7 +10319,7 @@ class basic_json return m_value.object->operator[](key); } - JSON_THROW(type_error::create(305, "cannot use operator[] with " + std::string(type_name()))); + JSON_THROW(type_error(305, "cannot use operator[] with " + std::string(type_name()))); } /*! @@ -10306,7 +10362,7 @@ class basic_json return m_value.object->find(key)->second; } - JSON_THROW(type_error::create(305, "cannot use operator[] with " + std::string(type_name()))); + JSON_THROW(type_error(305, "cannot use operator[] with " + std::string(type_name()))); } /*! @@ -10374,7 +10430,7 @@ class basic_json return default_value; } - JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name()))); + JSON_THROW(type_error(306, "cannot use value() with " + std::string(type_name()))); } /*! @@ -10445,7 +10501,7 @@ class basic_json } } - JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name()))); + JSON_THROW(type_error(306, "cannot use value() with " + std::string(type_name()))); } /*! @@ -10598,7 +10654,7 @@ class basic_json // make sure iterator fits the current value if (JSON_UNLIKELY(this != pos.m_object)) { - JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value")); + JSON_THROW(invalid_iterator(202, "iterator does not fit current value")); } IteratorType result = end(); @@ -10613,7 +10669,7 @@ class basic_json { if (JSON_UNLIKELY(not pos.m_it.primitive_iterator.is_begin())) { - JSON_THROW(invalid_iterator::create(205, "iterator out of range")); + JSON_THROW(invalid_iterator(205, "iterator out of range")); } if (is_string()) @@ -10642,7 +10698,7 @@ class basic_json } default: - JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()))); + JSON_THROW(type_error(307, "cannot use erase() with " + std::string(type_name()))); } return result; @@ -10703,7 +10759,7 @@ class basic_json // make sure iterator fits the current value if (JSON_UNLIKELY(this != first.m_object or this != last.m_object)) { - JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value")); + JSON_THROW(invalid_iterator(203, "iterators do not fit current value")); } IteratorType result = end(); @@ -10719,7 +10775,7 @@ class basic_json if (JSON_LIKELY(not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end())) { - JSON_THROW(invalid_iterator::create(204, "iterators out of range")); + JSON_THROW(invalid_iterator(204, "iterators out of range")); } if (is_string()) @@ -10750,7 +10806,7 @@ class basic_json } default: - JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()))); + JSON_THROW(type_error(307, "cannot use erase() with " + std::string(type_name()))); } return result; @@ -10793,7 +10849,7 @@ class basic_json return m_value.object->erase(key); } - JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()))); + JSON_THROW(type_error(307, "cannot use erase() with " + std::string(type_name()))); } /*! @@ -10827,14 +10883,14 @@ class basic_json { if (JSON_UNLIKELY(idx >= size())) { - JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range")); + JSON_THROW(out_of_range(401, "array index " + std::to_string(idx) + " is out of range")); } m_value.array->erase(m_value.array->begin() + static_cast(idx)); } else { - JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()))); + JSON_THROW(type_error(307, "cannot use erase() with " + std::string(type_name()))); } } @@ -11577,7 +11633,7 @@ class basic_json // push_back only works for null objects or arrays if (JSON_UNLIKELY(not(is_null() or is_array()))) { - JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()))); + JSON_THROW(type_error(308, "cannot use push_back() with " + std::string(type_name()))); } // transform null object into an array @@ -11613,7 +11669,7 @@ class basic_json // push_back only works for null objects or arrays if (JSON_UNLIKELY(not(is_null() or is_array()))) { - JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()))); + JSON_THROW(type_error(308, "cannot use push_back() with " + std::string(type_name()))); } // transform null object into an array @@ -11663,7 +11719,7 @@ class basic_json // push_back only works for null objects or objects if (JSON_UNLIKELY(not(is_null() or is_object()))) { - JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()))); + JSON_THROW(type_error(308, "cannot use push_back() with " + std::string(type_name()))); } // transform null object into an object @@ -11764,7 +11820,7 @@ class basic_json // emplace_back only works for null objects or arrays if (JSON_UNLIKELY(not(is_null() or is_array()))) { - JSON_THROW(type_error::create(311, "cannot use emplace_back() with " + std::string(type_name()))); + JSON_THROW(type_error(311, "cannot use emplace_back() with " + std::string(type_name()))); } // transform null object into an array @@ -11812,7 +11868,7 @@ class basic_json // emplace only works for null objects or arrays if (JSON_UNLIKELY(not(is_null() or is_object()))) { - JSON_THROW(type_error::create(311, "cannot use emplace() with " + std::string(type_name()))); + JSON_THROW(type_error(311, "cannot use emplace() with " + std::string(type_name()))); } // transform null object into an object @@ -11863,7 +11919,7 @@ class basic_json // check if iterator pos fits to this JSON value if (JSON_UNLIKELY(pos.m_object != this)) { - JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value")); + JSON_THROW(invalid_iterator(202, "iterator does not fit current value")); } // insert to array and return iterator @@ -11872,7 +11928,7 @@ class basic_json return result; } - JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()))); + JSON_THROW(type_error(309, "cannot use insert() with " + std::string(type_name()))); } /*! @@ -11916,7 +11972,7 @@ class basic_json // check if iterator pos fits to this JSON value if (JSON_UNLIKELY(pos.m_object != this)) { - JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value")); + JSON_THROW(invalid_iterator(202, "iterator does not fit current value")); } // insert to array and return iterator @@ -11925,7 +11981,7 @@ class basic_json return result; } - JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()))); + JSON_THROW(type_error(309, "cannot use insert() with " + std::string(type_name()))); } /*! @@ -11963,24 +12019,24 @@ class basic_json // insert only works for arrays if (JSON_UNLIKELY(not is_array())) { - JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()))); + JSON_THROW(type_error(309, "cannot use insert() with " + std::string(type_name()))); } // check if iterator pos fits to this JSON value if (JSON_UNLIKELY(pos.m_object != this)) { - JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value")); + JSON_THROW(invalid_iterator(202, "iterator does not fit current value")); } // check if range iterators belong to the same JSON object if (JSON_UNLIKELY(first.m_object != last.m_object)) { - JSON_THROW(invalid_iterator::create(210, "iterators do not fit")); + JSON_THROW(invalid_iterator(210, "iterators do not fit")); } if (JSON_UNLIKELY(first.m_object == this)) { - JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container")); + JSON_THROW(invalid_iterator(211, "passed iterators may not belong to container")); } // insert to array and return iterator @@ -12021,13 +12077,13 @@ class basic_json // insert only works for arrays if (JSON_UNLIKELY(not is_array())) { - JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()))); + JSON_THROW(type_error(309, "cannot use insert() with " + std::string(type_name()))); } // check if iterator pos fits to this JSON value if (JSON_UNLIKELY(pos.m_object != this)) { - JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value")); + JSON_THROW(invalid_iterator(202, "iterator does not fit current value")); } // insert to array and return iterator @@ -12064,19 +12120,19 @@ class basic_json // insert only works for objects if (JSON_UNLIKELY(not is_object())) { - JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()))); + JSON_THROW(type_error(309, "cannot use insert() with " + std::string(type_name()))); } // check if range iterators belong to the same JSON object if (JSON_UNLIKELY(first.m_object != last.m_object)) { - JSON_THROW(invalid_iterator::create(210, "iterators do not fit")); + JSON_THROW(invalid_iterator(210, "iterators do not fit")); } // passed iterators must belong to objects if (JSON_UNLIKELY(not first.m_object->is_object())) { - JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects")); + JSON_THROW(invalid_iterator(202, "iterators first and last must point to objects")); } m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator); @@ -12113,11 +12169,11 @@ class basic_json if (JSON_UNLIKELY(not is_object())) { - JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name()))); + JSON_THROW(type_error(312, "cannot use update() with " + std::string(type_name()))); } if (JSON_UNLIKELY(not j.is_object())) { - JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(j.type_name()))); + JSON_THROW(type_error(312, "cannot use update() with " + std::string(j.type_name()))); } for (auto it = j.begin(); it != j.end(); ++it) @@ -12164,20 +12220,20 @@ class basic_json if (JSON_UNLIKELY(not is_object())) { - JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name()))); + JSON_THROW(type_error(312, "cannot use update() with " + std::string(type_name()))); } // check if range iterators belong to the same JSON object if (JSON_UNLIKELY(first.m_object != last.m_object)) { - JSON_THROW(invalid_iterator::create(210, "iterators do not fit")); + JSON_THROW(invalid_iterator(210, "iterators do not fit")); } // passed iterators must belong to objects if (JSON_UNLIKELY(not first.m_object->is_object() or not first.m_object->is_object())) { - JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects")); + JSON_THROW(invalid_iterator(202, "iterators first and last must point to objects")); } for (auto it = first; it != last; ++it) @@ -12244,7 +12300,7 @@ class basic_json } else { - JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()))); + JSON_THROW(type_error(310, "cannot use swap() with " + std::string(type_name()))); } } @@ -12277,7 +12333,7 @@ class basic_json } else { - JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()))); + JSON_THROW(type_error(310, "cannot use swap() with " + std::string(type_name()))); } } @@ -12310,7 +12366,7 @@ class basic_json } else { - JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()))); + JSON_THROW(type_error(310, "cannot use swap() with " + std::string(type_name()))); } } @@ -12888,11 +12944,10 @@ class basic_json @since version 2.0.3 (contiguous containers) */ static basic_json parse(detail::input_adapter i, - const parser_callback_t cb = nullptr, - const bool allow_exceptions = true) + const parser_callback_t cb = nullptr) { basic_json result; - parser(i, cb, allow_exceptions).parse(true, result); + parser(i, cb).parse(true, result); return result; } @@ -12900,11 +12955,34 @@ class basic_json @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) + const parser_callback_t cb = nullptr) { basic_json result; - parser(i, cb, allow_exceptions).parse(true, result); + parser(i, cb).parse(true, result); + return result; + } + + /*! + @copydoc basic_json parse(detail::input_adapter, const parser_callback_t) + */ + static basic_json parse(detail::input_adapter i, + std::unique_ptr& ex, + const parser_callback_t cb = nullptr) + { + basic_json result; + parser(i, cb).parse(true, result, ex); + return result; + } + + /*! + @copydoc basic_json parse(detail::input_adapter, const parser_callback_t) + */ + static basic_json parse(detail::input_adapter& i, + std::unique_ptr& ex, + const parser_callback_t cb = nullptr) + { + basic_json result; + parser(i, cb).parse(true, result, ex); return result; } @@ -12969,12 +13047,21 @@ class basic_json std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits::iterator_category>::value, int>::type = 0> - static basic_json parse(IteratorType first, IteratorType last, - const parser_callback_t cb = nullptr, - const bool allow_exceptions = true) + static basic_json parse(IteratorType first, IteratorType last, const parser_callback_t cb = nullptr) { basic_json result; - parser(detail::input_adapter(first, last), cb, allow_exceptions).parse(true, result); + parser(detail::input_adapter(first, last), cb).parse(true, result); + return result; + } + + template::iterator_category>::value, int>::type = 0> + static basic_json parse(IteratorType first, IteratorType last, std::unique_ptr& ex, const parser_callback_t cb = nullptr) + { + basic_json result; + parser(detail::input_adapter(first, last), cb).parse(true, result, ex); return result; } @@ -13860,7 +13947,7 @@ class basic_json if (JSON_UNLIKELY(static_cast(idx) > parent.size())) { // avoid undefined behavior - JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range")); + JSON_THROW(out_of_range(401, "array index " + std::to_string(idx) + " is out of range")); } else { @@ -13898,7 +13985,7 @@ class basic_json } else { - JSON_THROW(out_of_range::create(403, "key '" + last_path + "' not found")); + JSON_THROW(out_of_range(403, "key '" + last_path + "' not found")); } } else if (parent.is_array()) @@ -13911,7 +13998,7 @@ class basic_json // type check: top level value must be an array if (JSON_UNLIKELY(not json_patch.is_array())) { - JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects")); + JSON_THROW(parse_error(104, 0, "JSON patch must be an array of objects")); } // iterate and apply the operations @@ -13931,13 +14018,13 @@ class basic_json // check if desired value is present if (JSON_UNLIKELY(it == val.m_value.object->end())) { - JSON_THROW(parse_error::create(105, 0, error_msg + " must have member '" + member + "'")); + JSON_THROW(parse_error(105, 0, error_msg + " must have member '" + member + "'")); } // check if result is of type string if (JSON_UNLIKELY(string_type and not it->second.is_string())) { - JSON_THROW(parse_error::create(105, 0, error_msg + " must have string member '" + member + "'")); + JSON_THROW(parse_error(105, 0, error_msg + " must have string member '" + member + "'")); } // no error: return value @@ -13947,7 +14034,7 @@ class basic_json // type check: every element of the array must be an object if (JSON_UNLIKELY(not val.is_object())) { - JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects")); + JSON_THROW(parse_error(104, 0, "JSON patch must be an array of objects")); } // collect mandatory members @@ -14020,7 +14107,7 @@ class basic_json // throw an exception if test fails if (JSON_UNLIKELY(not success)) { - JSON_THROW(other_error::create(501, "unsuccessful: " + val.dump())); + JSON_THROW(other_error(501, "unsuccessful: " + val.dump())); } break; @@ -14030,7 +14117,7 @@ class basic_json { // op must be "add", "remove", "replace", "move", "copy", or // "test" - JSON_THROW(parse_error::create(105, 0, "operation value '" + op + "' is invalid")); + JSON_THROW(parse_error(105, 0, "operation value '" + op + "' is invalid")); } } } @@ -14260,7 +14347,7 @@ json_pointer::get_and_create(NLOHMANN_BASIC_JSON_TPL& j) const } JSON_CATCH(std::invalid_argument&) { - JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number")); + JSON_THROW(detail::parse_error(109, 0, "array index '" + reference_token + "' is not a number")); } break; } @@ -14272,7 +14359,7 @@ json_pointer::get_and_create(NLOHMANN_BASIC_JSON_TPL& j) const single value; that is, with an empty list of reference tokens. */ default: - JSON_THROW(detail::type_error::create(313, "invalid value to unflatten")); + JSON_THROW(detail::type_error(313, "invalid value to unflatten")); } } @@ -14317,7 +14404,7 @@ json_pointer::get_unchecked(NLOHMANN_BASIC_JSON_TPL* ptr) const // error condition (cf. RFC 6901, Sect. 4) if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0')) { - JSON_THROW(detail::parse_error::create(106, 0, + JSON_THROW(detail::parse_error(106, 0, "array index '" + reference_token + "' must not begin with '0'")); } @@ -14337,14 +14424,14 @@ json_pointer::get_unchecked(NLOHMANN_BASIC_JSON_TPL* ptr) const } JSON_CATCH(std::invalid_argument&) { - JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number")); + JSON_THROW(detail::parse_error(109, 0, "array index '" + reference_token + "' is not a number")); } } break; } default: - JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'")); + JSON_THROW(detail::out_of_range(404, "unresolved reference token '" + reference_token + "'")); } } @@ -14372,15 +14459,15 @@ json_pointer::get_checked(NLOHMANN_BASIC_JSON_TPL* ptr) const if (JSON_UNLIKELY(reference_token == "-")) { // "-" always fails the range check - JSON_THROW(detail::out_of_range::create(402, - "array index '-' (" + std::to_string(ptr->m_value.array->size()) + - ") is out of range")); + JSON_THROW(detail::out_of_range(402, + "array index '-' (" + std::to_string(ptr->m_value.array->size()) + + ") is out of range")); } // error condition (cf. RFC 6901, Sect. 4) if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0')) { - JSON_THROW(detail::parse_error::create(106, 0, + JSON_THROW(detail::parse_error(106, 0, "array index '" + reference_token + "' must not begin with '0'")); } @@ -14392,13 +14479,13 @@ json_pointer::get_checked(NLOHMANN_BASIC_JSON_TPL* ptr) const } JSON_CATCH(std::invalid_argument&) { - JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number")); + JSON_THROW(detail::parse_error(109, 0, "array index '" + reference_token + "' is not a number")); } break; } default: - JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'")); + JSON_THROW(detail::out_of_range(404, "unresolved reference token '" + reference_token + "'")); } } @@ -14426,15 +14513,15 @@ json_pointer::get_unchecked(const NLOHMANN_BASIC_JSON_TPL* ptr) const if (JSON_UNLIKELY(reference_token == "-")) { // "-" cannot be used for const access - JSON_THROW(detail::out_of_range::create(402, - "array index '-' (" + std::to_string(ptr->m_value.array->size()) + - ") is out of range")); + JSON_THROW(detail::out_of_range(402, + "array index '-' (" + std::to_string(ptr->m_value.array->size()) + + ") is out of range")); } // error condition (cf. RFC 6901, Sect. 4) if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0')) { - JSON_THROW(detail::parse_error::create(106, 0, + JSON_THROW(detail::parse_error(106, 0, "array index '" + reference_token + "' must not begin with '0'")); } @@ -14447,13 +14534,13 @@ json_pointer::get_unchecked(const NLOHMANN_BASIC_JSON_TPL* ptr) const } JSON_CATCH(std::invalid_argument&) { - JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number")); + JSON_THROW(detail::parse_error(109, 0, "array index '" + reference_token + "' is not a number")); } break; } default: - JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'")); + JSON_THROW(detail::out_of_range(404, "unresolved reference token '" + reference_token + "'")); } } @@ -14481,15 +14568,15 @@ json_pointer::get_checked(const NLOHMANN_BASIC_JSON_TPL* ptr) const if (JSON_UNLIKELY(reference_token == "-")) { // "-" always fails the range check - JSON_THROW(detail::out_of_range::create(402, - "array index '-' (" + std::to_string(ptr->m_value.array->size()) + - ") is out of range")); + JSON_THROW(detail::out_of_range(402, + "array index '-' (" + std::to_string(ptr->m_value.array->size()) + + ") is out of range")); } // error condition (cf. RFC 6901, Sect. 4) if (JSON_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0')) { - JSON_THROW(detail::parse_error::create(106, 0, + JSON_THROW(detail::parse_error(106, 0, "array index '" + reference_token + "' must not begin with '0'")); } @@ -14501,13 +14588,13 @@ json_pointer::get_checked(const NLOHMANN_BASIC_JSON_TPL* ptr) const } JSON_CATCH(std::invalid_argument&) { - JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number")); + JSON_THROW(detail::parse_error(109, 0, "array index '" + reference_token + "' is not a number")); } break; } default: - JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'")); + JSON_THROW(detail::out_of_range(404, "unresolved reference token '" + reference_token + "'")); } } @@ -14573,7 +14660,7 @@ json_pointer::unflatten(const NLOHMANN_BASIC_JSON_TPL& value) { if (JSON_UNLIKELY(not value.is_object())) { - JSON_THROW(detail::type_error::create(314, "only objects can be unflattened")); + JSON_THROW(detail::type_error(314, "only objects can be unflattened")); } NLOHMANN_BASIC_JSON_TPL result; @@ -14583,7 +14670,7 @@ json_pointer::unflatten(const NLOHMANN_BASIC_JSON_TPL& value) { if (JSON_UNLIKELY(not element.second.is_primitive())) { - JSON_THROW(detail::type_error::create(315, "values in object must be primitive")); + JSON_THROW(detail::type_error(315, "values in object must be primitive")); } // assign value to reference pointed to by JSON pointer; Note that if @@ -14711,6 +14798,7 @@ inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std #endif // clean up +#undef JSON_EXCEPTIONS_DISABLED #undef JSON_CATCH #undef JSON_THROW #undef JSON_TRY diff --git a/test/src/unit-class_parser.cpp b/test/src/unit-class_parser.cpp index 9afa7d269..fee865c18 100644 --- a/test/src/unit-class_parser.cpp +++ b/test/src/unit-class_parser.cpp @@ -45,7 +45,8 @@ json parser_helper(const std::string& s) // if this line was reached, no exception ocurred // -> check if result is the same without exceptions json j_nothrow; - CHECK_NOTHROW(json::parser(nlohmann::detail::input_adapter(s), nullptr, false).parse(true, j_nothrow)); + std::unique_ptr ex; + CHECK_NOTHROW(json::parser(nlohmann::detail::input_adapter(s), nullptr).parse(true, j_nothrow, ex)); CHECK(j_nothrow == j); return j; @@ -55,7 +56,8 @@ bool accept_helper(const std::string& s) { // 1. parse s without exceptions json j; - CHECK_NOTHROW(json::parser(nlohmann::detail::input_adapter(s), nullptr, false).parse(true, j)); + std::unique_ptr ex; + CHECK_NOTHROW(json::parser(nlohmann::detail::input_adapter(s)).parse(true, j, ex)); const bool ok_noexcept = not j.is_discarded(); // 2. accept s diff --git a/test/src/unit-deserialization.cpp b/test/src/unit-deserialization.cpp index 2798f1020..006c8d460 100644 --- a/test/src/unit-deserialization.cpp +++ b/test/src/unit-deserialization.cpp @@ -103,7 +103,8 @@ TEST_CASE("deserialization") CHECK(not json::accept(ss3)); json j_error; - CHECK_NOTHROW(j_error = json::parse(ss1, nullptr, false)); + std::unique_ptr ex; + CHECK_NOTHROW(j_error = json::parse(ss1, ex)); CHECK(j_error.is_discarded()); } @@ -116,7 +117,8 @@ TEST_CASE("deserialization") CHECK(not json::accept(s)); json j_error; - CHECK_NOTHROW(j_error = json::parse(s, nullptr, false)); + std::unique_ptr ex; + CHECK_NOTHROW(j_error = json::parse(s, ex)); CHECK(j_error.is_discarded()); } @@ -272,7 +274,8 @@ TEST_CASE("deserialization") CHECK(not json::accept(std::begin(v), std::end(v))); json j_error; - CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false)); + std::unique_ptr ex; + CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), ex)); CHECK(j_error.is_discarded()); } @@ -283,7 +286,8 @@ TEST_CASE("deserialization") CHECK(not json::accept(std::begin(v), std::end(v))); json j_error; - CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false)); + std::unique_ptr ex; + CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), ex)); CHECK(j_error.is_discarded()); } @@ -294,7 +298,8 @@ TEST_CASE("deserialization") CHECK(not json::accept(std::begin(v), std::end(v))); json j_error; - CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false)); + std::unique_ptr ex; + CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), ex)); CHECK(j_error.is_discarded()); } @@ -305,7 +310,8 @@ TEST_CASE("deserialization") CHECK(not json::accept(std::begin(v), std::end(v))); json j_error; - CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false)); + std::unique_ptr ex; + CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), ex)); CHECK(j_error.is_discarded()); } @@ -316,7 +322,8 @@ TEST_CASE("deserialization") CHECK(not json::accept(std::begin(v), std::end(v))); json j_error; - CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false)); + std::unique_ptr ex; + CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), ex)); CHECK(j_error.is_discarded()); } @@ -329,7 +336,8 @@ TEST_CASE("deserialization") CHECK(not json::accept(std::begin(v), std::end(v))); json j_error; - CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false)); + std::unique_ptr ex; + CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), ex)); CHECK(j_error.is_discarded()); } @@ -340,7 +348,8 @@ TEST_CASE("deserialization") CHECK(not json::accept(std::begin(v), std::end(v))); json j_error; - CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false)); + std::unique_ptr ex; + CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), ex)); CHECK(j_error.is_discarded()); } @@ -351,7 +360,8 @@ TEST_CASE("deserialization") CHECK(not json::accept(std::begin(v), std::end(v))); json j_error; - CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false)); + std::unique_ptr ex; + CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), ex)); CHECK(j_error.is_discarded()); } @@ -362,7 +372,8 @@ TEST_CASE("deserialization") CHECK(not json::accept(std::begin(v), std::end(v))); json j_error; - CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false)); + std::unique_ptr ex; + CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), ex)); CHECK(j_error.is_discarded()); } @@ -373,7 +384,8 @@ TEST_CASE("deserialization") CHECK(not json::accept(std::begin(v), std::end(v))); json j_error; - CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false)); + std::unique_ptr ex; + CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), ex)); CHECK(j_error.is_discarded()); } @@ -384,7 +396,8 @@ TEST_CASE("deserialization") CHECK(not json::accept(std::begin(v), std::end(v))); json j_error; - CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false)); + std::unique_ptr ex; + CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), ex)); CHECK(j_error.is_discarded()); } @@ -395,7 +408,8 @@ TEST_CASE("deserialization") CHECK(not json::accept(std::begin(v), std::end(v))); json j_error; - CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false)); + std::unique_ptr ex; + CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), ex)); CHECK(j_error.is_discarded()); } @@ -406,7 +420,8 @@ TEST_CASE("deserialization") CHECK(not json::accept(std::begin(v), std::end(v))); json j_error; - CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false)); + std::unique_ptr ex; + CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), ex)); CHECK(j_error.is_discarded()); } @@ -417,7 +432,8 @@ TEST_CASE("deserialization") CHECK(not json::accept(std::begin(v), std::end(v))); json j_error; - CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false)); + std::unique_ptr ex; + CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), ex)); CHECK(j_error.is_discarded()); } @@ -428,7 +444,8 @@ TEST_CASE("deserialization") CHECK(not json::accept(std::begin(v), std::end(v))); json j_error; - CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false)); + std::unique_ptr ex; + CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), ex)); CHECK(j_error.is_discarded()); } @@ -439,7 +456,8 @@ TEST_CASE("deserialization") CHECK(not json::accept(std::begin(v), std::end(v))); json j_error; - CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false)); + std::unique_ptr ex; + CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), ex)); CHECK(j_error.is_discarded()); } }