From 9eacdfe65fd251f4ce28eb079516a692b4a8632f Mon Sep 17 00:00:00 2001 From: Alexander Karzhenkov Date: Sun, 24 Jan 2021 14:14:33 +0500 Subject: [PATCH 1/5] Fix exception arguments --- include/nlohmann/detail/json_pointer.hpp | 2 +- single_include/nlohmann/json.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/nlohmann/detail/json_pointer.hpp b/include/nlohmann/detail/json_pointer.hpp index 52cf171345..9fb7d0d22a 100644 --- a/include/nlohmann/detail/json_pointer.hpp +++ b/include/nlohmann/detail/json_pointer.hpp @@ -884,7 +884,7 @@ class json_pointer { if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive())) { - JSON_THROW(detail::type_error::create(315, "values in object must be primitive", diagnostics_t(element))); + JSON_THROW(detail::type_error::create(315, "values in object must be primitive", diagnostics_t(element.second))); } // assign value to reference pointed to by JSON pointer; Note that if diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index fc9f6d630a..33ca9ad89a 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -12739,7 +12739,7 @@ class json_pointer { if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive())) { - JSON_THROW(detail::type_error::create(315, "values in object must be primitive", diagnostics_t(element))); + JSON_THROW(detail::type_error::create(315, "values in object must be primitive", diagnostics_t(element.second))); } // assign value to reference pointed to by JSON pointer; Note that if From 8fcbcb02ddd5f7e9ed424d9789cd85775d3aedf3 Mon Sep 17 00:00:00 2001 From: Alexander Karzhenkov Date: Sun, 24 Jan 2021 11:53:44 +0500 Subject: [PATCH 2/5] Introduce "diagnostics context" --- include/nlohmann/detail/diagnostics_t.hpp | 23 + include/nlohmann/detail/exceptions.hpp | 36 +- single_include/nlohmann/json.hpp | 1822 +++++++++++---------- 3 files changed, 964 insertions(+), 917 deletions(-) diff --git a/include/nlohmann/detail/diagnostics_t.hpp b/include/nlohmann/detail/diagnostics_t.hpp index f89b0e3d13..68bd9c5179 100644 --- a/include/nlohmann/detail/diagnostics_t.hpp +++ b/include/nlohmann/detail/diagnostics_t.hpp @@ -4,6 +4,7 @@ #include #include #include +#include namespace nlohmann { @@ -82,5 +83,27 @@ class diagnostics_t const BasicJsonType* m_j = nullptr; }; +template +std::string diagonstics_message(const DiagnosticsContext&) = delete; + +template +std::string diagnostics_message(const diagnostics_t& context) +{ + return context.diagnostics(); +} + +template +typename std::enable_if::value, std::string>::type +diagnostics_message(const BasicJsonType& context) +{ + return diagnostics_message(diagnostics_t(context)); +} + +inline +std::string diagnostics_message(std::nullptr_t) +{ + return {}; +} + } // namespace detail } // namespace nlohmann diff --git a/include/nlohmann/detail/exceptions.hpp b/include/nlohmann/detail/exceptions.hpp index 56a582f794..10d688d4a1 100644 --- a/include/nlohmann/detail/exceptions.hpp +++ b/include/nlohmann/detail/exceptions.hpp @@ -128,20 +128,20 @@ class parse_error : public exception @param[in] what_arg the explanatory string @return parse_error object */ - template - static parse_error create(int id_, const position_t& pos, const std::string& what_arg, const detail::diagnostics_t& diagnostics) + template + static parse_error create(int id_, const position_t& pos, const std::string& what_arg, const DiagnosticsContext& context = nullptr) { std::string w = exception::name("parse_error", id_) + "parse error" + - position_string(pos) + ": " + diagnostics.diagnostics() + what_arg; + position_string(pos) + ": " + diagnostics_message(context) + what_arg; return parse_error(id_, pos.chars_read_total, w.c_str()); } - template - static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, const detail::diagnostics_t& diagnostics) + template + static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, const DiagnosticsContext& context = nullptr) { std::string w = exception::name("parse_error", id_) + "parse error" + (byte_ != 0 ? (" at byte " + std::to_string(byte_)) : "") + - ": " + diagnostics.diagnostics() + what_arg; + ": " + diagnostics_message(context) + what_arg; return parse_error(id_, byte_, w.c_str()); } @@ -207,10 +207,10 @@ caught.,invalid_iterator} class invalid_iterator : public exception { public: - template - static invalid_iterator create(int id_, const std::string& what_arg, const detail::diagnostics_t& diagnostics) + template + static invalid_iterator create(int id_, const std::string& what_arg, const DiagnosticsContext& context = nullptr) { - std::string w = exception::name("invalid_iterator", id_) + diagnostics.diagnostics() + what_arg; + std::string w = exception::name("invalid_iterator", id_) + diagnostics_message(context) + what_arg; return invalid_iterator(id_, w.c_str()); } @@ -262,10 +262,10 @@ caught.,type_error} class type_error : public exception { public: - template - static type_error create(int id_, const std::string& what_arg, const detail::diagnostics_t& diagnostics) + template + static type_error create(int id_, const std::string& what_arg, const DiagnosticsContext& context = nullptr) { - std::string w = exception::name("type_error", id_) + diagnostics.diagnostics() + what_arg; + std::string w = exception::name("type_error", id_) + diagnostics_message(context) + what_arg; return type_error(id_, w.c_str()); } @@ -310,10 +310,10 @@ caught.,out_of_range} class out_of_range : public exception { public: - template - static out_of_range create(int id_, const std::string& what_arg, const detail::diagnostics_t& diagnostics) + template + static out_of_range create(int id_, const std::string& what_arg, const DiagnosticsContext& context = nullptr) { - std::string w = exception::name("out_of_range", id_) + diagnostics.diagnostics() + what_arg; + std::string w = exception::name("out_of_range", id_) + diagnostics_message(context) + what_arg; return out_of_range(id_, w.c_str()); } @@ -349,10 +349,10 @@ caught.,other_error} class other_error : public exception { public: - template - static other_error create(int id_, const std::string& what_arg, const detail::diagnostics_t& diagnostics) + template + static other_error create(int id_, const std::string& what_arg, const DiagnosticsContext& context = nullptr) { - std::string w = exception::name("other_error", id_) + diagnostics.diagnostics() + what_arg; + std::string w = exception::name("other_error", id_) + diagnostics_message(context) + what_arg; return other_error(id_, w.c_str()); } diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 33ca9ad89a..f07ebf2f0a 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -2502,115 +2502,40 @@ static void unescape(std::string& s) } // namespace detail } // namespace nlohmann +// #include -namespace nlohmann -{ -namespace detail -{ - -template -class diagnostics_t -{ - public: - diagnostics_t() noexcept = default; - diagnostics_t(const BasicJsonType& j) noexcept - : m_j(&j) - {} - - std::string diagnostics() const - { -#if JSON_DIAGNOSTICS - if (m_j == nullptr) - { - return ""; - } - - std::vector tokens; - for (const auto* current = m_j; current->m_parent != nullptr; current = current->m_parent) - { - switch (current->m_parent->type()) - { - case value_t::array: - { - for (std::size_t i = 0; i < current->m_parent->m_value.array->size(); ++i) - { - if (¤t->m_parent->m_value.array->operator[](i) == current) - { - tokens.emplace_back(std::to_string(i)); - break; - } - } - break; - } - - case value_t::object: - { - for (const auto& element : *current->m_parent->m_value.object) - { - if (&element.second == current) - { - tokens.emplace_back(element.first.c_str()); - break; - } - } - break; - } - - default: // LCOV_EXCL_LINE - break; // LCOV_EXCL_LINE - } - } - - if (tokens.empty()) - { - return ""; // LCOV_EXCL_LINE - } - return "(" + std::accumulate(tokens.rbegin(), tokens.rend(), std::string{}, - [](const std::string & a, const std::string & b) - { - return a + "/" + detail::escape(b); - }) + ") "; -#else - return ""; -#endif - } +#include // numeric_limits +#include // false_type, is_constructible, is_integral, is_same, true_type +#include // declval +#include // tuple - private: - const BasicJsonType* m_j = nullptr; -}; +// #include -} // namespace detail -} // namespace nlohmann -// #include +#include // random_access_iterator_tag +// #include -#include // size_t namespace nlohmann { namespace detail { -/// struct to capture the start position of the current token -struct position_t +template struct make_void { - /// the total number of characters read - std::size_t chars_read_total = 0; - /// the number of characters read in the current line - std::size_t chars_read_current_line = 0; - /// the number of lines read - std::size_t lines_read = 0; - - /// conversion to size_t to preserve SAX interface - constexpr operator size_t() const - { - return chars_read_total; - } + using type = void; }; - +template using void_t = typename make_void::type; } // namespace detail -} // namespace nlohmann +} // namespace nlohmann + +// #include + + +#include // size_t +#include // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type +#include // index_sequence, make_index_sequence, index_sequence_for // #include @@ -2619,1049 +2544,1148 @@ namespace nlohmann { namespace detail { -//////////////// -// exceptions // -//////////////// -/*! -@brief general exception of the @ref basic_json class +template +using uncvref_t = typename std::remove_cv::type>::type; -This class is an extension of `std::exception` objects with a member @a id for -exception ids. It is used as the base class for all exceptions thrown by the -@ref basic_json class. This class can hence be used as "wildcard" to catch -exceptions. +#ifdef JSON_HAS_CPP_14 -Subclasses: -- @ref parse_error for exceptions indicating a parse error -- @ref invalid_iterator for exceptions indicating errors with iterators -- @ref type_error for exceptions indicating executing a member function with - a wrong type -- @ref out_of_range for exceptions indicating access out of the defined range -- @ref other_error for exceptions indicating other library errors +// the following utilities are natively available in C++14 +using std::enable_if_t; +using std::index_sequence; +using std::make_index_sequence; +using std::index_sequence_for; -@internal -@note To have nothrow-copy-constructible exceptions, we internally use - `std::runtime_error` which can cope with arbitrary-length error messages. - Intermediate strings are built with static functions and then passed to - the actual constructor. -@endinternal +#else -@liveexample{The following code shows how arbitrary library exceptions can be -caught.,exception} +// alias templates to reduce boilerplate +template +using enable_if_t = typename std::enable_if::type; -@since version 3.0.0 -*/ -class exception : public std::exception +// source: https://stackoverflow.com/a/32223343 +template +struct index_sequence { - public: - /// returns the explanatory string - JSON_HEDLEY_RETURNS_NON_NULL - const char* what() const noexcept override + using type = index_sequence; + using value_type = std::size_t; + static constexpr std::size_t size() noexcept { - return m.what(); + return sizeof...(Ints); } +}; - /// the id of the exception - const int id; +template +struct merge_and_renumber; - protected: - JSON_HEDLEY_NON_NULL(3) - exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} +template +struct merge_and_renumber, index_sequence> + : index_sequence < I1..., (sizeof...(I1) + I2)... > {}; - static std::string name(const std::string& ename, int id_) - { - return "[json.exception." + ename + "." + std::to_string(id_) + "] "; - } +template +struct make_index_sequence + : merge_and_renumber < typename make_index_sequence < N / 2 >::type, + typename make_index_sequence < N - N / 2 >::type > {}; - private: - /// an exception object as storage for error messages - std::runtime_error m; -}; +template<> struct make_index_sequence<0> : index_sequence<> {}; +template<> struct make_index_sequence<1> : index_sequence<0> {}; -/*! -@brief exception indicating a parse error +template +using index_sequence_for = make_index_sequence; -This exception is thrown by the library when a parse error occurs. Parse errors -can occur during the deserialization of JSON text, CBOR, MessagePack, as well -as when using JSON Patch. +#endif -Member @a byte holds the byte index of the last read character in the input -file. +// dispatch utility (taken from ranges-v3) +template struct priority_tag : priority_tag < N - 1 > {}; +template<> struct priority_tag<0> {}; -Exceptions have ids 1xx. +// taken from ranges-v3 +template +struct static_const +{ + static constexpr T value{}; +}; -name / id | example message | description ------------------------------- | --------------- | ------------------------- -json.exception.parse_error.101 | parse error at 2: unexpected end of input; expected string literal | This error indicates a syntax error while deserializing a JSON text. The error message describes that an unexpected token (character) was encountered, and the member @a byte indicates the error position. -json.exception.parse_error.102 | parse error at 14: missing or wrong low surrogate | JSON uses the `\uxxxx` format to describe Unicode characters. Code points above above 0xFFFF are split into two `\uxxxx` entries ("surrogate pairs"). This error indicates that the surrogate pair is incomplete or contains an invalid code point. -json.exception.parse_error.103 | parse error: code points above 0x10FFFF are invalid | Unicode supports code points up to 0x10FFFF. Code points above 0x10FFFF are invalid. -json.exception.parse_error.104 | parse error: JSON patch must be an array of objects | [RFC 6902](https://tools.ietf.org/html/rfc6902) requires a JSON Patch document to be a JSON document that represents an array of objects. -json.exception.parse_error.105 | parse error: operation must have string member 'op' | An operation of a JSON Patch document must contain exactly one "op" member, whose value indicates the operation to perform. Its value must be one of "add", "remove", "replace", "move", "copy", or "test"; other values are errors. -json.exception.parse_error.106 | parse error: array index '01' must not begin with '0' | An array index in a JSON Pointer ([RFC 6901](https://tools.ietf.org/html/rfc6901)) may be `0` or any number without a leading `0`. -json.exception.parse_error.107 | parse error: JSON pointer must be empty or begin with '/' - was: 'foo' | A JSON Pointer must be a Unicode string containing a sequence of zero or more reference tokens, each prefixed by a `/` character. -json.exception.parse_error.108 | parse error: escape character '~' must be followed with '0' or '1' | In a JSON Pointer, only `~0` and `~1` are valid escape sequences. -json.exception.parse_error.109 | parse error: array index 'one' is not a number | A JSON Pointer array index must be a number. -json.exception.parse_error.110 | parse error at 1: cannot read 2 bytes from vector | When parsing CBOR or MessagePack, the byte vector ends before the complete value has been read. -json.exception.parse_error.112 | parse error at 1: error reading CBOR; last byte: 0xF8 | Not all types of CBOR or MessagePack are supported. This exception occurs if an unsupported byte was read. -json.exception.parse_error.113 | parse error at 2: expected a CBOR string; last byte: 0x98 | While parsing a map key, a value that is not a string has been read. -json.exception.parse_error.114 | parse error: Unsupported BSON record type 0x0F | The parsing of the corresponding BSON record type is not implemented (yet). -json.exception.parse_error.115 | parse error at byte 5: syntax error while parsing UBJSON high-precision number: invalid number text: 1A | A UBJSON high-precision number could not be parsed. +template +constexpr T static_const::value; -@note For an input with n bytes, 1 is the index of the first character and n+1 - is the index of the terminating null byte or the end of file. This also - holds true when reading a byte vector (CBOR or MessagePack). +} // namespace detail +} // namespace nlohmann -@liveexample{The following code shows how a `parse_error` exception can be -caught.,parse_error} -@sa - @ref exception for the base class of the library exceptions -@sa - @ref invalid_iterator for exceptions indicating errors with iterators -@sa - @ref type_error for exceptions indicating executing a member function with - a wrong type -@sa - @ref out_of_range for exceptions indicating access out of the defined range -@sa - @ref other_error for exceptions indicating other library errors +namespace nlohmann +{ +namespace detail +{ +template +struct iterator_types {}; -@since version 3.0.0 -*/ -class parse_error : public exception +template +struct iterator_types < + It, + void_t> { - public: - /*! - @brief create a parse error exception - @param[in] id_ the id of the exception - @param[in] pos the position where the error occurred (or with - chars_read_total=0 if the position cannot be - determined) - @param[in] what_arg the explanatory string - @return parse_error object - */ - template - static parse_error create(int id_, const position_t& pos, const std::string& what_arg, const detail::diagnostics_t& diagnostics) - { - std::string w = exception::name("parse_error", id_) + "parse error" + - position_string(pos) + ": " + diagnostics.diagnostics() + what_arg; - return parse_error(id_, pos.chars_read_total, w.c_str()); - } - - template - static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, const detail::diagnostics_t& diagnostics) - { - std::string w = exception::name("parse_error", id_) + "parse error" + - (byte_ != 0 ? (" at byte " + std::to_string(byte_)) : "") + - ": " + diagnostics.diagnostics() + what_arg; - return parse_error(id_, byte_, w.c_str()); - } + using difference_type = typename It::difference_type; + using value_type = typename It::value_type; + using pointer = typename It::pointer; + using reference = typename It::reference; + using iterator_category = typename It::iterator_category; +}; - /*! - @brief byte index of the parse error +// This is required as some compilers implement std::iterator_traits in a way that +// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341. +template +struct iterator_traits +{ +}; - The byte index of the last read character in the input file. +template +struct iterator_traits < T, enable_if_t < !std::is_pointer::value >> + : iterator_types +{ +}; - @note For an input with n bytes, 1 is the index of the first character and - n+1 is the index of the terminating null byte or the end of file. - This also holds true when reading a byte vector (CBOR or MessagePack). - */ - const std::size_t byte; +template +struct iterator_traits::value>> +{ + using iterator_category = std::random_access_iterator_tag; + using value_type = T; + using difference_type = ptrdiff_t; + using pointer = T*; + using reference = T&; +}; +} // namespace detail +} // namespace nlohmann - private: - parse_error(int id_, std::size_t byte_, const char* what_arg) - : exception(id_, what_arg), byte(byte_) {} +// #include - static std::string position_string(const position_t& pos) - { - return " at line " + std::to_string(pos.lines_read + 1) + - ", column " + std::to_string(pos.chars_read_current_line); - } -}; +// #include -/*! -@brief exception indicating errors with iterators +// #include -This exception is thrown if iterators passed to a library function do not match -the expected semantics. -Exceptions have ids 2xx. +#include -name / id | example message | description ------------------------------------ | --------------- | ------------------------- -json.exception.invalid_iterator.201 | iterators are not compatible | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid. -json.exception.invalid_iterator.202 | iterator does not fit current value | In an erase or insert function, the passed iterator @a pos does not belong to the JSON value for which the function was called. It hence does not define a valid position for the deletion/insertion. -json.exception.invalid_iterator.203 | iterators do not fit current value | Either iterator passed to function @ref erase(IteratorType first, IteratorType last) does not belong to the JSON value from which values shall be erased. It hence does not define a valid range to delete values from. -json.exception.invalid_iterator.204 | iterators out of range | When an iterator range for a primitive type (number, boolean, or string) is passed to a constructor or an erase function, this range has to be exactly (@ref begin(), @ref end()), because this is the only way the single stored value is expressed. All other ranges are invalid. -json.exception.invalid_iterator.205 | iterator out of range | When an iterator for a primitive type (number, boolean, or string) is passed to an erase function, the iterator has to be the @ref begin() iterator, because it is the only way to address the stored value. All other iterators are invalid. -json.exception.invalid_iterator.206 | cannot construct with iterators from null | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) belong to a JSON null value and hence to not define a valid range. -json.exception.invalid_iterator.207 | cannot use key() for non-object iterators | The key() member function can only be used on iterators belonging to a JSON object, because other types do not have a concept of a key. -json.exception.invalid_iterator.208 | cannot use operator[] for object iterators | The operator[] to specify a concrete offset cannot be used on iterators belonging to a JSON object, because JSON objects are unordered. -json.exception.invalid_iterator.209 | cannot use offsets with object iterators | The offset operators (+, -, +=, -=) cannot be used on iterators belonging to a JSON object, because JSON objects are unordered. -json.exception.invalid_iterator.210 | iterators do not fit | The iterator range passed to the insert function are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid. -json.exception.invalid_iterator.211 | passed iterators may not belong to container | The iterator range passed to the insert function must not be a subrange of the container to insert to. -json.exception.invalid_iterator.212 | cannot compare iterators of different containers | When two iterators are compared, they must belong to the same container. -json.exception.invalid_iterator.213 | cannot compare order of object iterators | The order of object iterators cannot be compared, because JSON objects are unordered. -json.exception.invalid_iterator.214 | cannot get value | Cannot get value for iterator: Either the iterator belongs to a null value or it is an iterator to a primitive type (number, boolean, or string), but the iterator is different to @ref begin(). +// #include -@liveexample{The following code shows how an `invalid_iterator` exception can be -caught.,invalid_iterator} -@sa - @ref exception for the base class of the library exceptions -@sa - @ref parse_error for exceptions indicating a parse error -@sa - @ref type_error for exceptions indicating executing a member function with - a wrong type -@sa - @ref out_of_range for exceptions indicating access out of the defined range -@sa - @ref other_error for exceptions indicating other library errors +// https://en.cppreference.com/w/cpp/experimental/is_detected +namespace nlohmann +{ +namespace detail +{ +struct nonesuch +{ + nonesuch() = delete; + ~nonesuch() = delete; + nonesuch(nonesuch const&) = delete; + nonesuch(nonesuch const&&) = delete; + void operator=(nonesuch const&) = delete; + void operator=(nonesuch&&) = delete; +}; -@since version 3.0.0 -*/ -class invalid_iterator : public exception +template class Op, + class... Args> +struct detector { - public: - template - static invalid_iterator create(int id_, const std::string& what_arg, const detail::diagnostics_t& diagnostics) - { - std::string w = exception::name("invalid_iterator", id_) + diagnostics.diagnostics() + what_arg; - return invalid_iterator(id_, w.c_str()); - } + using value_t = std::false_type; + using type = Default; +}; - private: - JSON_HEDLEY_NON_NULL(3) - invalid_iterator(int id_, const char* what_arg) - : exception(id_, what_arg) {} +template class Op, class... Args> +struct detector>, Op, Args...> +{ + using value_t = std::true_type; + using type = Op; }; -/*! -@brief exception indicating executing a member function with a wrong type +template class Op, class... Args> +using is_detected = typename detector::value_t; -This exception is thrown in case of a type error; that is, a library function is -executed on a JSON value whose type does not match the expected semantics. +template class Op, class... Args> +using detected_t = typename detector::type; -Exceptions have ids 3xx. +template class Op, class... Args> +using detected_or = detector; -name / id | example message | description ------------------------------ | --------------- | ------------------------- -json.exception.type_error.301 | cannot create object from initializer list | To create an object from an initializer list, the initializer list must consist only of a list of pairs whose first element is a string. When this constraint is violated, an array is created instead. -json.exception.type_error.302 | type must be object, but is array | During implicit or explicit value conversion, the JSON type must be compatible to the target type. For instance, a JSON string can only be converted into string types, but not into numbers or boolean types. -json.exception.type_error.303 | incompatible ReferenceType for get_ref, actual type is object | To retrieve a reference to a value stored in a @ref basic_json object with @ref get_ref, the type of the reference must match the value type. For instance, for a JSON array, the @a ReferenceType must be @ref array_t &. -json.exception.type_error.304 | cannot use at() with string | The @ref at() member functions can only be executed for certain JSON types. -json.exception.type_error.305 | cannot use operator[] with string | The @ref operator[] member functions can only be executed for certain JSON types. -json.exception.type_error.306 | cannot use value() with string | The @ref value() member functions can only be executed for certain JSON types. -json.exception.type_error.307 | cannot use erase() with string | The @ref erase() member functions can only be executed for certain JSON types. -json.exception.type_error.308 | cannot use push_back() with string | The @ref push_back() and @ref operator+= member functions can only be executed for certain JSON types. -json.exception.type_error.309 | cannot use insert() with | The @ref insert() member functions can only be executed for certain JSON types. -json.exception.type_error.310 | cannot use swap() with number | The @ref swap() member functions can only be executed for certain JSON types. -json.exception.type_error.311 | cannot use emplace_back() with string | The @ref emplace_back() member function can only be executed for certain JSON types. -json.exception.type_error.312 | cannot use update() with string | The @ref update() member functions can only be executed for certain JSON types. -json.exception.type_error.313 | invalid value to unflatten | The @ref unflatten function converts an object whose keys are JSON Pointers back into an arbitrary nested JSON value. The JSON Pointers must not overlap, because then the resulting value would not be well defined. -json.exception.type_error.314 | only objects can be unflattened | The @ref unflatten function only works for an object whose keys are JSON Pointers. -json.exception.type_error.315 | values in object must be primitive | The @ref unflatten function only works for an object whose keys are JSON Pointers and whose values are primitive. -json.exception.type_error.316 | invalid UTF-8 byte at index 10: 0x7E | The @ref dump function only works with UTF-8 encoded strings; that is, if you assign a `std::string` to a JSON value, make sure it is UTF-8 encoded. | -json.exception.type_error.317 | JSON value cannot be serialized to requested format | The dynamic type of the object cannot be represented in the requested serialization format (e.g. a raw `true` or `null` JSON object cannot be serialized to BSON) | +template class Op, class... Args> +using detected_or_t = typename detected_or::type; -@liveexample{The following code shows how a `type_error` exception can be -caught.,type_error} +template class Op, class... Args> +using is_detected_exact = std::is_same>; -@sa - @ref exception for the base class of the library exceptions -@sa - @ref parse_error for exceptions indicating a parse error -@sa - @ref invalid_iterator for exceptions indicating errors with iterators -@sa - @ref out_of_range for exceptions indicating access out of the defined range -@sa - @ref other_error for exceptions indicating other library errors +template class Op, class... Args> +using is_detected_convertible = + std::is_convertible, To>; +} // namespace detail +} // namespace nlohmann -@since version 3.0.0 +// #include +#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_ +#define INCLUDE_NLOHMANN_JSON_FWD_HPP_ + +#include // int64_t, uint64_t +#include // map +#include // allocator +#include // string +#include // vector + +/*! +@brief namespace for Niels Lohmann +@see https://github.com/nlohmann +@since version 1.0.0 */ -class type_error : public exception +namespace nlohmann { - public: - template - static type_error create(int id_, const std::string& what_arg, const detail::diagnostics_t& diagnostics) - { - std::string w = exception::name("type_error", id_) + diagnostics.diagnostics() + what_arg; - return type_error(id_, w.c_str()); - } +/*! +@brief default JSONSerializer template argument - private: - JSON_HEDLEY_NON_NULL(3) - type_error(int id_, const char* what_arg) : exception(id_, what_arg) {} -}; +This serializer ignores the template arguments and uses ADL +([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl)) +for serialization. +*/ +template +struct adl_serializer; + +template class ObjectType = + std::map, + template class ArrayType = std::vector, + class StringType = std::string, class BooleanType = bool, + class NumberIntegerType = std::int64_t, + class NumberUnsignedType = std::uint64_t, + class NumberFloatType = double, + template class AllocatorType = std::allocator, + template class JSONSerializer = + adl_serializer, + class BinaryType = std::vector> +class basic_json; /*! -@brief exception indicating access out of the defined range +@brief JSON Pointer -This exception is thrown in case a library function is called on an input -parameter that exceeds the expected range, for instance in case of array -indices or nonexisting object keys. +A JSON pointer defines a string syntax for identifying a specific value +within a JSON document. It can be used with functions `at` and +`operator[]`. Furthermore, JSON pointers are the base for JSON patches. -Exceptions have ids 4xx. +@sa [RFC 6901](https://tools.ietf.org/html/rfc6901) -name / id | example message | description -------------------------------- | --------------- | ------------------------- -json.exception.out_of_range.401 | array index 3 is out of range | The provided array index @a i is larger than @a size-1. -json.exception.out_of_range.402 | array index '-' (3) is out of range | The special array index `-` in a JSON Pointer never describes a valid element of the array, but the index past the end. That is, it can only be used to add elements at this position, but not to read it. -json.exception.out_of_range.403 | key 'foo' not found | The provided key was not found in the JSON object. -json.exception.out_of_range.404 | unresolved reference token 'foo' | A reference token in a JSON Pointer could not be resolved. -json.exception.out_of_range.405 | JSON pointer has no parent | The JSON Patch operations 'remove' and 'add' can not be applied to the root element of the JSON value. -json.exception.out_of_range.406 | number overflow parsing '10E1000' | A parsed number could not be stored as without changing it to NaN or INF. -json.exception.out_of_range.407 | number overflow serializing '9223372036854775808' | UBJSON and BSON only support integer numbers up to 9223372036854775807. (until version 3.8.0) | -json.exception.out_of_range.408 | excessive array size: 8658170730974374167 | The size (following `#`) of an UBJSON array or object exceeds the maximal capacity. | -json.exception.out_of_range.409 | BSON key cannot contain code point U+0000 (at byte 2) | Key identifiers to be serialized to BSON cannot contain code point U+0000, since the key is stored as zero-terminated c-string | +@since version 2.0.0 +*/ +template +class json_pointer; -@liveexample{The following code shows how an `out_of_range` exception can be -caught.,out_of_range} +/*! +@brief default JSON class -@sa - @ref exception for the base class of the library exceptions -@sa - @ref parse_error for exceptions indicating a parse error -@sa - @ref invalid_iterator for exceptions indicating errors with iterators -@sa - @ref type_error for exceptions indicating executing a member function with - a wrong type -@sa - @ref other_error for exceptions indicating other library errors +This type is the default specialization of the @ref basic_json class which +uses the standard template types. -@since version 3.0.0 +@since version 1.0.0 */ -class out_of_range : public exception -{ - public: - template - static out_of_range create(int id_, const std::string& what_arg, const detail::diagnostics_t& diagnostics) - { - std::string w = exception::name("out_of_range", id_) + diagnostics.diagnostics() + what_arg; - return out_of_range(id_, w.c_str()); - } +using json = basic_json<>; - private: - JSON_HEDLEY_NON_NULL(3) - out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {} -}; +template +struct ordered_map; /*! -@brief exception indicating other library errors +@brief ordered JSON class -This exception is thrown in case of errors that cannot be classified with the -other exception types. +This type preserves the insertion order of object keys. -Exceptions have ids 5xx. +@since version 3.9.0 +*/ +using ordered_json = basic_json; -name / id | example message | description ------------------------------- | --------------- | ------------------------- -json.exception.other_error.501 | unsuccessful: {"op":"test","path":"/baz", "value":"bar"} | A JSON Patch operation 'test' failed. The unsuccessful operation is also printed. +} // namespace nlohmann -@sa - @ref exception for the base class of the library exceptions -@sa - @ref parse_error for exceptions indicating a parse error -@sa - @ref invalid_iterator for exceptions indicating errors with iterators -@sa - @ref type_error for exceptions indicating executing a member function with - a wrong type -@sa - @ref out_of_range for exceptions indicating access out of the defined range +#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_ -@liveexample{The following code shows how an `other_error` exception can be -caught.,other_error} -@since version 3.0.0 +namespace nlohmann +{ +/*! +@brief detail namespace with internal helper functions + +This namespace collects functions that should not be exposed, +implementations of some @ref basic_json methods, and meta-programming helpers. + +@since version 2.1.0 */ -class other_error : public exception +namespace detail { - public: - template - static other_error create(int id_, const std::string& what_arg, const detail::diagnostics_t& diagnostics) - { - std::string w = exception::name("other_error", id_) + diagnostics.diagnostics() + what_arg; - return other_error(id_, w.c_str()); - } +///////////// +// helpers // +///////////// - private: - JSON_HEDLEY_NON_NULL(3) - other_error(int id_, const char* what_arg) : exception(id_, what_arg) {} -}; -} // namespace detail -} // namespace nlohmann +// Note to maintainers: +// +// Every trait in this file expects a non CV-qualified type. +// The only exceptions are in the 'aliases for detected' section +// (i.e. those of the form: decltype(T::member_function(std::declval()))) +// +// In this case, T has to be properly CV-qualified to constraint the function arguments +// (e.g. to_json(BasicJsonType&, const T&)) -// #include +template struct is_basic_json : std::false_type {}; -// #include +NLOHMANN_BASIC_JSON_TPL_DECLARATION +struct is_basic_json : std::true_type {}; -// #include +////////////////////// +// json_ref helpers // +////////////////////// +template +class json_ref; -#include // size_t -#include // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type -#include // index_sequence, make_index_sequence, index_sequence_for +template +struct is_json_ref : std::false_type {}; -// #include +template +struct is_json_ref> : std::true_type {}; +////////////////////////// +// aliases for detected // +////////////////////////// -namespace nlohmann -{ -namespace detail -{ +template +using mapped_type_t = typename T::mapped_type; template -using uncvref_t = typename std::remove_cv::type>::type; +using key_type_t = typename T::key_type; -#ifdef JSON_HAS_CPP_14 +template +using value_type_t = typename T::value_type; -// the following utilities are natively available in C++14 -using std::enable_if_t; -using std::index_sequence; -using std::make_index_sequence; -using std::index_sequence_for; +template +using difference_type_t = typename T::difference_type; -#else +template +using pointer_t = typename T::pointer; -// alias templates to reduce boilerplate -template -using enable_if_t = typename std::enable_if::type; +template +using reference_t = typename T::reference; -// source: https://stackoverflow.com/a/32223343 -template -struct index_sequence +template +using iterator_category_t = typename T::iterator_category; + +template +using iterator_t = typename T::iterator; + +template +using to_json_function = decltype(T::to_json(std::declval()...)); + +template +using from_json_function = decltype(T::from_json(std::declval()...)); + +template +using get_template_function = decltype(std::declval().template get()); + +// trait checking if JSONSerializer::from_json(json const&, udt&) exists +template +struct has_from_json : std::false_type {}; + +// trait checking if j.get is valid +// use this trait instead of std::is_constructible or std::is_convertible, +// both rely on, or make use of implicit conversions, and thus fail when T +// has several constructors/operator= (see https://github.com/nlohmann/json/issues/958) +template +struct is_getable { - using type = index_sequence; - using value_type = std::size_t; - static constexpr std::size_t size() noexcept - { - return sizeof...(Ints); - } + static constexpr bool value = is_detected::value; }; -template -struct merge_and_renumber; +template +struct has_from_json < BasicJsonType, T, + enable_if_t < !is_basic_json::value >> +{ + using serializer = typename BasicJsonType::template json_serializer; -template -struct merge_and_renumber, index_sequence> - : index_sequence < I1..., (sizeof...(I1) + I2)... > {}; + static constexpr bool value = + is_detected_exact::value; +}; -template -struct make_index_sequence - : merge_and_renumber < typename make_index_sequence < N / 2 >::type, - typename make_index_sequence < N - N / 2 >::type > {}; +// This trait checks if JSONSerializer::from_json(json const&) exists +// this overload is used for non-default-constructible user-defined-types +template +struct has_non_default_from_json : std::false_type {}; -template<> struct make_index_sequence<0> : index_sequence<> {}; -template<> struct make_index_sequence<1> : index_sequence<0> {}; +template +struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> +{ + using serializer = typename BasicJsonType::template json_serializer; -template -using index_sequence_for = make_index_sequence; + static constexpr bool value = + is_detected_exact::value; +}; -#endif +// This trait checks if BasicJsonType::json_serializer::to_json exists +// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion. +template +struct has_to_json : std::false_type {}; -// dispatch utility (taken from ranges-v3) -template struct priority_tag : priority_tag < N - 1 > {}; -template<> struct priority_tag<0> {}; +template +struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> +{ + using serializer = typename BasicJsonType::template json_serializer; + + static constexpr bool value = + is_detected_exact::value; +}; + + +/////////////////// +// is_ functions // +/////////////////// + +template +struct is_iterator_traits : std::false_type {}; -// taken from ranges-v3 template -struct static_const +struct is_iterator_traits> { - static constexpr T value{}; + private: + using traits = iterator_traits; + + public: + static constexpr auto value = + is_detected::value && + is_detected::value && + is_detected::value && + is_detected::value && + is_detected::value; }; +// The following implementation of is_complete_type is taken from +// https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/ +// and is written by Xiang Fan who agreed to using it in this library. + +template +struct is_complete_type : std::false_type {}; + template -constexpr T static_const::value; +struct is_complete_type : std::true_type {}; -} // namespace detail -} // namespace nlohmann +template +struct is_compatible_object_type_impl : std::false_type {}; -// #include +template +struct is_compatible_object_type_impl < + BasicJsonType, CompatibleObjectType, + enable_if_t < is_detected::value&& + is_detected::value >> +{ + using object_t = typename BasicJsonType::object_t; + // macOS's is_constructible does not play well with nonesuch... + static constexpr bool value = + std::is_constructible::value && + std::is_constructible::value; +}; -#include // numeric_limits -#include // false_type, is_constructible, is_integral, is_same, true_type -#include // declval -#include // tuple +template +struct is_compatible_object_type + : is_compatible_object_type_impl {}; -// #include +template +struct is_constructible_object_type_impl : std::false_type {}; +template +struct is_constructible_object_type_impl < + BasicJsonType, ConstructibleObjectType, + enable_if_t < is_detected::value&& + is_detected::value >> +{ + using object_t = typename BasicJsonType::object_t; -#include // random_access_iterator_tag + static constexpr bool value = + (std::is_default_constructible::value && + (std::is_move_assignable::value || + std::is_copy_assignable::value) && + (std::is_constructible::value && + std::is_same < + typename object_t::mapped_type, + typename ConstructibleObjectType::mapped_type >::value)) || + (has_from_json::value || + has_non_default_from_json < + BasicJsonType, + typename ConstructibleObjectType::mapped_type >::value); +}; -// #include +template +struct is_constructible_object_type + : is_constructible_object_type_impl {}; +template +struct is_compatible_string_type_impl : std::false_type {}; -namespace nlohmann -{ -namespace detail -{ -template struct make_void +template +struct is_compatible_string_type_impl < + BasicJsonType, CompatibleStringType, + enable_if_t::value >> { - using type = void; + static constexpr auto value = + std::is_constructible::value; }; -template using void_t = typename make_void::type; -} // namespace detail -} // namespace nlohmann - -// #include +template +struct is_compatible_string_type + : is_compatible_string_type_impl {}; -namespace nlohmann -{ -namespace detail -{ -template -struct iterator_types {}; +template +struct is_constructible_string_type_impl : std::false_type {}; -template -struct iterator_types < - It, - void_t> +template +struct is_constructible_string_type_impl < + BasicJsonType, ConstructibleStringType, + enable_if_t::value >> { - using difference_type = typename It::difference_type; - using value_type = typename It::value_type; - using pointer = typename It::pointer; - using reference = typename It::reference; - using iterator_category = typename It::iterator_category; + static constexpr auto value = + std::is_constructible::value; }; -// This is required as some compilers implement std::iterator_traits in a way that -// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341. -template -struct iterator_traits -{ -}; +template +struct is_constructible_string_type + : is_constructible_string_type_impl {}; -template -struct iterator_traits < T, enable_if_t < !std::is_pointer::value >> - : iterator_types -{ -}; +template +struct is_compatible_array_type_impl : std::false_type {}; -template -struct iterator_traits::value>> +template +struct is_compatible_array_type_impl < + BasicJsonType, CompatibleArrayType, + enable_if_t < is_detected::value&& + is_detected::value&& +// This is needed because json_reverse_iterator has a ::iterator type... +// Therefore it is detected as a CompatibleArrayType. +// The real fix would be to have an Iterable concept. + !is_iterator_traits < + iterator_traits>::value >> { - using iterator_category = std::random_access_iterator_tag; - using value_type = T; - using difference_type = ptrdiff_t; - using pointer = T*; - using reference = T&; + static constexpr bool value = + std::is_constructible::value; }; -} // namespace detail -} // namespace nlohmann -// #include +template +struct is_compatible_array_type + : is_compatible_array_type_impl {}; -// #include +template +struct is_constructible_array_type_impl : std::false_type {}; -// #include +template +struct is_constructible_array_type_impl < + BasicJsonType, ConstructibleArrayType, + enable_if_t::value >> + : std::true_type {}; +template +struct is_constructible_array_type_impl < + BasicJsonType, ConstructibleArrayType, + enable_if_t < !std::is_same::value&& + std::is_default_constructible::value&& +(std::is_move_assignable::value || + std::is_copy_assignable::value)&& +is_detected::value&& +is_detected::value&& +is_complete_type < +detected_t>::value >> +{ + static constexpr bool value = + // This is needed because json_reverse_iterator has a ::iterator type, + // furthermore, std::back_insert_iterator (and other iterators) have a + // base class `iterator`... Therefore it is detected as a + // ConstructibleArrayType. The real fix would be to have an Iterable + // concept. + !is_iterator_traits>::value && -#include + (std::is_same::value || + has_from_json::value || + has_non_default_from_json < + BasicJsonType, typename ConstructibleArrayType::value_type >::value); +}; -// #include +template +struct is_constructible_array_type + : is_constructible_array_type_impl {}; +template +struct is_compatible_integer_type_impl : std::false_type {}; -// https://en.cppreference.com/w/cpp/experimental/is_detected -namespace nlohmann -{ -namespace detail -{ -struct nonesuch +template +struct is_compatible_integer_type_impl < + RealIntegerType, CompatibleNumberIntegerType, + enable_if_t < std::is_integral::value&& + std::is_integral::value&& + !std::is_same::value >> { - nonesuch() = delete; - ~nonesuch() = delete; - nonesuch(nonesuch const&) = delete; - nonesuch(nonesuch const&&) = delete; - void operator=(nonesuch const&) = delete; - void operator=(nonesuch&&) = delete; -}; + // is there an assert somewhere on overflows? + using RealLimits = std::numeric_limits; + using CompatibleLimits = std::numeric_limits; -template class Op, - class... Args> -struct detector -{ - using value_t = std::false_type; - using type = Default; + static constexpr auto value = + std::is_constructible::value && + CompatibleLimits::is_integer && + RealLimits::is_signed == CompatibleLimits::is_signed; }; -template class Op, class... Args> -struct detector>, Op, Args...> -{ - using value_t = std::true_type; - using type = Op; -}; +template +struct is_compatible_integer_type + : is_compatible_integer_type_impl {}; -template class Op, class... Args> -using is_detected = typename detector::value_t; +template +struct is_compatible_type_impl: std::false_type {}; -template class Op, class... Args> -using detected_t = typename detector::type; +template +struct is_compatible_type_impl < + BasicJsonType, CompatibleType, + enable_if_t::value >> +{ + static constexpr bool value = + has_to_json::value; +}; -template class Op, class... Args> -using detected_or = detector; +template +struct is_compatible_type + : is_compatible_type_impl {}; -template class Op, class... Args> -using detected_or_t = typename detected_or::type; +// https://en.cppreference.com/w/cpp/types/conjunction +template struct conjunction : std::true_type { }; +template struct conjunction : B1 { }; +template +struct conjunction +: std::conditional, B1>::type {}; -template class Op, class... Args> -using is_detected_exact = std::is_same>; +template +struct is_constructible_tuple : std::false_type {}; -template class Op, class... Args> -using is_detected_convertible = - std::is_convertible, To>; +template +struct is_constructible_tuple> : conjunction...> {}; } // namespace detail } // namespace nlohmann -// #include -#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_ -#define INCLUDE_NLOHMANN_JSON_FWD_HPP_ - -#include // int64_t, uint64_t -#include // map -#include // allocator -#include // string -#include // vector -/*! -@brief namespace for Niels Lohmann -@see https://github.com/nlohmann -@since version 1.0.0 -*/ namespace nlohmann { -/*! -@brief default JSONSerializer template argument +namespace detail +{ -This serializer ignores the template arguments and uses ADL -([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl)) -for serialization. -*/ -template -struct adl_serializer; +template +class diagnostics_t +{ + public: + diagnostics_t() noexcept = default; + diagnostics_t(const BasicJsonType& j) noexcept + : m_j(&j) + {} -template class ObjectType = - std::map, - template class ArrayType = std::vector, - class StringType = std::string, class BooleanType = bool, - class NumberIntegerType = std::int64_t, - class NumberUnsignedType = std::uint64_t, - class NumberFloatType = double, - template class AllocatorType = std::allocator, - template class JSONSerializer = - adl_serializer, - class BinaryType = std::vector> -class basic_json; + std::string diagnostics() const + { +#if JSON_DIAGNOSTICS + if (m_j == nullptr) + { + return ""; + } -/*! -@brief JSON Pointer + std::vector tokens; + for (const auto* current = m_j; current->m_parent != nullptr; current = current->m_parent) + { + switch (current->m_parent->type()) + { + case value_t::array: + { + for (std::size_t i = 0; i < current->m_parent->m_value.array->size(); ++i) + { + if (¤t->m_parent->m_value.array->operator[](i) == current) + { + tokens.emplace_back(std::to_string(i)); + break; + } + } + break; + } -A JSON pointer defines a string syntax for identifying a specific value -within a JSON document. It can be used with functions `at` and -`operator[]`. Furthermore, JSON pointers are the base for JSON patches. + case value_t::object: + { + for (const auto& element : *current->m_parent->m_value.object) + { + if (&element.second == current) + { + tokens.emplace_back(element.first.c_str()); + break; + } + } + break; + } -@sa [RFC 6901](https://tools.ietf.org/html/rfc6901) + default: // LCOV_EXCL_LINE + break; // LCOV_EXCL_LINE + } + } -@since version 2.0.0 -*/ -template -class json_pointer; + if (tokens.empty()) + { + return ""; // LCOV_EXCL_LINE + } -/*! -@brief default JSON class + return "(" + std::accumulate(tokens.rbegin(), tokens.rend(), std::string{}, + [](const std::string & a, const std::string & b) + { + return a + "/" + detail::escape(b); + }) + ") "; +#else + return ""; +#endif + } -This type is the default specialization of the @ref basic_json class which -uses the standard template types. + private: + const BasicJsonType* m_j = nullptr; +}; -@since version 1.0.0 -*/ -using json = basic_json<>; +template +std::string diagonstics_message(const DiagnosticsContext&) = delete; -template -struct ordered_map; +template +std::string diagnostics_message(const diagnostics_t& context) +{ + return context.diagnostics(); +} -/*! -@brief ordered JSON class +template +typename std::enable_if::value, std::string>::type +diagnostics_message(const BasicJsonType& context) +{ + return diagnostics_message(diagnostics_t(context)); +} -This type preserves the insertion order of object keys. +inline +std::string diagnostics_message(std::nullptr_t) +{ + return {}; +} -@since version 3.9.0 -*/ -using ordered_json = basic_json; +} // namespace detail +} // namespace nlohmann -} // namespace nlohmann +// #include -#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_ +#include // size_t namespace nlohmann { -/*! -@brief detail namespace with internal helper functions - -This namespace collects functions that should not be exposed, -implementations of some @ref basic_json methods, and meta-programming helpers. - -@since version 2.1.0 -*/ namespace detail { -///////////// -// helpers // -///////////// - -// Note to maintainers: -// -// Every trait in this file expects a non CV-qualified type. -// The only exceptions are in the 'aliases for detected' section -// (i.e. those of the form: decltype(T::member_function(std::declval()))) -// -// In this case, T has to be properly CV-qualified to constraint the function arguments -// (e.g. to_json(BasicJsonType&, const T&)) - -template struct is_basic_json : std::false_type {}; - -NLOHMANN_BASIC_JSON_TPL_DECLARATION -struct is_basic_json : std::true_type {}; - -////////////////////// -// json_ref helpers // -////////////////////// +/// struct to capture the start position of the current token +struct position_t +{ + /// the total number of characters read + std::size_t chars_read_total = 0; + /// the number of characters read in the current line + std::size_t chars_read_current_line = 0; + /// the number of lines read + std::size_t lines_read = 0; -template -class json_ref; + /// conversion to size_t to preserve SAX interface + constexpr operator size_t() const + { + return chars_read_total; + } +}; -template -struct is_json_ref : std::false_type {}; +} // namespace detail +} // namespace nlohmann -template -struct is_json_ref> : std::true_type {}; +// #include -////////////////////////// -// aliases for detected // -////////////////////////// -template -using mapped_type_t = typename T::mapped_type; +namespace nlohmann +{ +namespace detail +{ +//////////////// +// exceptions // +//////////////// -template -using key_type_t = typename T::key_type; +/*! +@brief general exception of the @ref basic_json class -template -using value_type_t = typename T::value_type; +This class is an extension of `std::exception` objects with a member @a id for +exception ids. It is used as the base class for all exceptions thrown by the +@ref basic_json class. This class can hence be used as "wildcard" to catch +exceptions. -template -using difference_type_t = typename T::difference_type; +Subclasses: +- @ref parse_error for exceptions indicating a parse error +- @ref invalid_iterator for exceptions indicating errors with iterators +- @ref type_error for exceptions indicating executing a member function with + a wrong type +- @ref out_of_range for exceptions indicating access out of the defined range +- @ref other_error for exceptions indicating other library errors -template -using pointer_t = typename T::pointer; +@internal +@note To have nothrow-copy-constructible exceptions, we internally use + `std::runtime_error` which can cope with arbitrary-length error messages. + Intermediate strings are built with static functions and then passed to + the actual constructor. +@endinternal -template -using reference_t = typename T::reference; +@liveexample{The following code shows how arbitrary library exceptions can be +caught.,exception} -template -using iterator_category_t = typename T::iterator_category; +@since version 3.0.0 +*/ +class exception : public std::exception +{ + public: + /// returns the explanatory string + JSON_HEDLEY_RETURNS_NON_NULL + const char* what() const noexcept override + { + return m.what(); + } -template -using iterator_t = typename T::iterator; + /// the id of the exception + const int id; -template -using to_json_function = decltype(T::to_json(std::declval()...)); + protected: + JSON_HEDLEY_NON_NULL(3) + exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} -template -using from_json_function = decltype(T::from_json(std::declval()...)); + static std::string name(const std::string& ename, int id_) + { + return "[json.exception." + ename + "." + std::to_string(id_) + "] "; + } -template -using get_template_function = decltype(std::declval().template get()); + private: + /// an exception object as storage for error messages + std::runtime_error m; +}; -// trait checking if JSONSerializer::from_json(json const&, udt&) exists -template -struct has_from_json : std::false_type {}; +/*! +@brief exception indicating a parse error -// trait checking if j.get is valid -// use this trait instead of std::is_constructible or std::is_convertible, -// both rely on, or make use of implicit conversions, and thus fail when T -// has several constructors/operator= (see https://github.com/nlohmann/json/issues/958) -template -struct is_getable -{ - static constexpr bool value = is_detected::value; -}; +This exception is thrown by the library when a parse error occurs. Parse errors +can occur during the deserialization of JSON text, CBOR, MessagePack, as well +as when using JSON Patch. -template -struct has_from_json < BasicJsonType, T, - enable_if_t < !is_basic_json::value >> -{ - using serializer = typename BasicJsonType::template json_serializer; +Member @a byte holds the byte index of the last read character in the input +file. - static constexpr bool value = - is_detected_exact::value; -}; +Exceptions have ids 1xx. -// This trait checks if JSONSerializer::from_json(json const&) exists -// this overload is used for non-default-constructible user-defined-types -template -struct has_non_default_from_json : std::false_type {}; +name / id | example message | description +------------------------------ | --------------- | ------------------------- +json.exception.parse_error.101 | parse error at 2: unexpected end of input; expected string literal | This error indicates a syntax error while deserializing a JSON text. The error message describes that an unexpected token (character) was encountered, and the member @a byte indicates the error position. +json.exception.parse_error.102 | parse error at 14: missing or wrong low surrogate | JSON uses the `\uxxxx` format to describe Unicode characters. Code points above above 0xFFFF are split into two `\uxxxx` entries ("surrogate pairs"). This error indicates that the surrogate pair is incomplete or contains an invalid code point. +json.exception.parse_error.103 | parse error: code points above 0x10FFFF are invalid | Unicode supports code points up to 0x10FFFF. Code points above 0x10FFFF are invalid. +json.exception.parse_error.104 | parse error: JSON patch must be an array of objects | [RFC 6902](https://tools.ietf.org/html/rfc6902) requires a JSON Patch document to be a JSON document that represents an array of objects. +json.exception.parse_error.105 | parse error: operation must have string member 'op' | An operation of a JSON Patch document must contain exactly one "op" member, whose value indicates the operation to perform. Its value must be one of "add", "remove", "replace", "move", "copy", or "test"; other values are errors. +json.exception.parse_error.106 | parse error: array index '01' must not begin with '0' | An array index in a JSON Pointer ([RFC 6901](https://tools.ietf.org/html/rfc6901)) may be `0` or any number without a leading `0`. +json.exception.parse_error.107 | parse error: JSON pointer must be empty or begin with '/' - was: 'foo' | A JSON Pointer must be a Unicode string containing a sequence of zero or more reference tokens, each prefixed by a `/` character. +json.exception.parse_error.108 | parse error: escape character '~' must be followed with '0' or '1' | In a JSON Pointer, only `~0` and `~1` are valid escape sequences. +json.exception.parse_error.109 | parse error: array index 'one' is not a number | A JSON Pointer array index must be a number. +json.exception.parse_error.110 | parse error at 1: cannot read 2 bytes from vector | When parsing CBOR or MessagePack, the byte vector ends before the complete value has been read. +json.exception.parse_error.112 | parse error at 1: error reading CBOR; last byte: 0xF8 | Not all types of CBOR or MessagePack are supported. This exception occurs if an unsupported byte was read. +json.exception.parse_error.113 | parse error at 2: expected a CBOR string; last byte: 0x98 | While parsing a map key, a value that is not a string has been read. +json.exception.parse_error.114 | parse error: Unsupported BSON record type 0x0F | The parsing of the corresponding BSON record type is not implemented (yet). +json.exception.parse_error.115 | parse error at byte 5: syntax error while parsing UBJSON high-precision number: invalid number text: 1A | A UBJSON high-precision number could not be parsed. -template -struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> -{ - using serializer = typename BasicJsonType::template json_serializer; +@note For an input with n bytes, 1 is the index of the first character and n+1 + is the index of the terminating null byte or the end of file. This also + holds true when reading a byte vector (CBOR or MessagePack). - static constexpr bool value = - is_detected_exact::value; -}; +@liveexample{The following code shows how a `parse_error` exception can be +caught.,parse_error} -// This trait checks if BasicJsonType::json_serializer::to_json exists -// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion. -template -struct has_to_json : std::false_type {}; +@sa - @ref exception for the base class of the library exceptions +@sa - @ref invalid_iterator for exceptions indicating errors with iterators +@sa - @ref type_error for exceptions indicating executing a member function with + a wrong type +@sa - @ref out_of_range for exceptions indicating access out of the defined range +@sa - @ref other_error for exceptions indicating other library errors -template -struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> +@since version 3.0.0 +*/ +class parse_error : public exception { - using serializer = typename BasicJsonType::template json_serializer; + public: + /*! + @brief create a parse error exception + @param[in] id_ the id of the exception + @param[in] pos the position where the error occurred (or with + chars_read_total=0 if the position cannot be + determined) + @param[in] what_arg the explanatory string + @return parse_error object + */ + template + static parse_error create(int id_, const position_t& pos, const std::string& what_arg, const DiagnosticsContext& context = nullptr) + { + std::string w = exception::name("parse_error", id_) + "parse error" + + position_string(pos) + ": " + diagnostics_message(context) + what_arg; + return parse_error(id_, pos.chars_read_total, w.c_str()); + } - static constexpr bool value = - is_detected_exact::value; -}; + template + static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, const DiagnosticsContext& context = nullptr) + { + std::string w = exception::name("parse_error", id_) + "parse error" + + (byte_ != 0 ? (" at byte " + std::to_string(byte_)) : "") + + ": " + diagnostics_message(context) + what_arg; + return parse_error(id_, byte_, w.c_str()); + } + /*! + @brief byte index of the parse error -/////////////////// -// is_ functions // -/////////////////// + The byte index of the last read character in the input file. -template -struct is_iterator_traits : std::false_type {}; + @note For an input with n bytes, 1 is the index of the first character and + n+1 is the index of the terminating null byte or the end of file. + This also holds true when reading a byte vector (CBOR or MessagePack). + */ + const std::size_t byte; -template -struct is_iterator_traits> -{ private: - using traits = iterator_traits; + parse_error(int id_, std::size_t byte_, const char* what_arg) + : exception(id_, what_arg), byte(byte_) {} - public: - static constexpr auto value = - is_detected::value && - is_detected::value && - is_detected::value && - is_detected::value && - is_detected::value; + static std::string position_string(const position_t& pos) + { + return " at line " + std::to_string(pos.lines_read + 1) + + ", column " + std::to_string(pos.chars_read_current_line); + } }; -// The following implementation of is_complete_type is taken from -// https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/ -// and is written by Xiang Fan who agreed to using it in this library. - -template -struct is_complete_type : std::false_type {}; - -template -struct is_complete_type : std::true_type {}; - -template -struct is_compatible_object_type_impl : std::false_type {}; +/*! +@brief exception indicating errors with iterators -template -struct is_compatible_object_type_impl < - BasicJsonType, CompatibleObjectType, - enable_if_t < is_detected::value&& - is_detected::value >> -{ - using object_t = typename BasicJsonType::object_t; +This exception is thrown if iterators passed to a library function do not match +the expected semantics. - // macOS's is_constructible does not play well with nonesuch... - static constexpr bool value = - std::is_constructible::value && - std::is_constructible::value; -}; +Exceptions have ids 2xx. -template -struct is_compatible_object_type - : is_compatible_object_type_impl {}; +name / id | example message | description +----------------------------------- | --------------- | ------------------------- +json.exception.invalid_iterator.201 | iterators are not compatible | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid. +json.exception.invalid_iterator.202 | iterator does not fit current value | In an erase or insert function, the passed iterator @a pos does not belong to the JSON value for which the function was called. It hence does not define a valid position for the deletion/insertion. +json.exception.invalid_iterator.203 | iterators do not fit current value | Either iterator passed to function @ref erase(IteratorType first, IteratorType last) does not belong to the JSON value from which values shall be erased. It hence does not define a valid range to delete values from. +json.exception.invalid_iterator.204 | iterators out of range | When an iterator range for a primitive type (number, boolean, or string) is passed to a constructor or an erase function, this range has to be exactly (@ref begin(), @ref end()), because this is the only way the single stored value is expressed. All other ranges are invalid. +json.exception.invalid_iterator.205 | iterator out of range | When an iterator for a primitive type (number, boolean, or string) is passed to an erase function, the iterator has to be the @ref begin() iterator, because it is the only way to address the stored value. All other iterators are invalid. +json.exception.invalid_iterator.206 | cannot construct with iterators from null | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) belong to a JSON null value and hence to not define a valid range. +json.exception.invalid_iterator.207 | cannot use key() for non-object iterators | The key() member function can only be used on iterators belonging to a JSON object, because other types do not have a concept of a key. +json.exception.invalid_iterator.208 | cannot use operator[] for object iterators | The operator[] to specify a concrete offset cannot be used on iterators belonging to a JSON object, because JSON objects are unordered. +json.exception.invalid_iterator.209 | cannot use offsets with object iterators | The offset operators (+, -, +=, -=) cannot be used on iterators belonging to a JSON object, because JSON objects are unordered. +json.exception.invalid_iterator.210 | iterators do not fit | The iterator range passed to the insert function are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid. +json.exception.invalid_iterator.211 | passed iterators may not belong to container | The iterator range passed to the insert function must not be a subrange of the container to insert to. +json.exception.invalid_iterator.212 | cannot compare iterators of different containers | When two iterators are compared, they must belong to the same container. +json.exception.invalid_iterator.213 | cannot compare order of object iterators | The order of object iterators cannot be compared, because JSON objects are unordered. +json.exception.invalid_iterator.214 | cannot get value | Cannot get value for iterator: Either the iterator belongs to a null value or it is an iterator to a primitive type (number, boolean, or string), but the iterator is different to @ref begin(). -template -struct is_constructible_object_type_impl : std::false_type {}; +@liveexample{The following code shows how an `invalid_iterator` exception can be +caught.,invalid_iterator} -template -struct is_constructible_object_type_impl < - BasicJsonType, ConstructibleObjectType, - enable_if_t < is_detected::value&& - is_detected::value >> -{ - using object_t = typename BasicJsonType::object_t; +@sa - @ref exception for the base class of the library exceptions +@sa - @ref parse_error for exceptions indicating a parse error +@sa - @ref type_error for exceptions indicating executing a member function with + a wrong type +@sa - @ref out_of_range for exceptions indicating access out of the defined range +@sa - @ref other_error for exceptions indicating other library errors - static constexpr bool value = - (std::is_default_constructible::value && - (std::is_move_assignable::value || - std::is_copy_assignable::value) && - (std::is_constructible::value && - std::is_same < - typename object_t::mapped_type, - typename ConstructibleObjectType::mapped_type >::value)) || - (has_from_json::value || - has_non_default_from_json < - BasicJsonType, - typename ConstructibleObjectType::mapped_type >::value); +@since version 3.0.0 +*/ +class invalid_iterator : public exception +{ + public: + template + static invalid_iterator create(int id_, const std::string& what_arg, const DiagnosticsContext& context = nullptr) + { + std::string w = exception::name("invalid_iterator", id_) + diagnostics_message(context) + what_arg; + return invalid_iterator(id_, w.c_str()); + } + + private: + JSON_HEDLEY_NON_NULL(3) + invalid_iterator(int id_, const char* what_arg) + : exception(id_, what_arg) {} }; -template -struct is_constructible_object_type - : is_constructible_object_type_impl {}; +/*! +@brief exception indicating executing a member function with a wrong type -template -struct is_compatible_string_type_impl : std::false_type {}; +This exception is thrown in case of a type error; that is, a library function is +executed on a JSON value whose type does not match the expected semantics. -template -struct is_compatible_string_type_impl < - BasicJsonType, CompatibleStringType, - enable_if_t::value >> -{ - static constexpr auto value = - std::is_constructible::value; -}; +Exceptions have ids 3xx. -template -struct is_compatible_string_type - : is_compatible_string_type_impl {}; +name / id | example message | description +----------------------------- | --------------- | ------------------------- +json.exception.type_error.301 | cannot create object from initializer list | To create an object from an initializer list, the initializer list must consist only of a list of pairs whose first element is a string. When this constraint is violated, an array is created instead. +json.exception.type_error.302 | type must be object, but is array | During implicit or explicit value conversion, the JSON type must be compatible to the target type. For instance, a JSON string can only be converted into string types, but not into numbers or boolean types. +json.exception.type_error.303 | incompatible ReferenceType for get_ref, actual type is object | To retrieve a reference to a value stored in a @ref basic_json object with @ref get_ref, the type of the reference must match the value type. For instance, for a JSON array, the @a ReferenceType must be @ref array_t &. +json.exception.type_error.304 | cannot use at() with string | The @ref at() member functions can only be executed for certain JSON types. +json.exception.type_error.305 | cannot use operator[] with string | The @ref operator[] member functions can only be executed for certain JSON types. +json.exception.type_error.306 | cannot use value() with string | The @ref value() member functions can only be executed for certain JSON types. +json.exception.type_error.307 | cannot use erase() with string | The @ref erase() member functions can only be executed for certain JSON types. +json.exception.type_error.308 | cannot use push_back() with string | The @ref push_back() and @ref operator+= member functions can only be executed for certain JSON types. +json.exception.type_error.309 | cannot use insert() with | The @ref insert() member functions can only be executed for certain JSON types. +json.exception.type_error.310 | cannot use swap() with number | The @ref swap() member functions can only be executed for certain JSON types. +json.exception.type_error.311 | cannot use emplace_back() with string | The @ref emplace_back() member function can only be executed for certain JSON types. +json.exception.type_error.312 | cannot use update() with string | The @ref update() member functions can only be executed for certain JSON types. +json.exception.type_error.313 | invalid value to unflatten | The @ref unflatten function converts an object whose keys are JSON Pointers back into an arbitrary nested JSON value. The JSON Pointers must not overlap, because then the resulting value would not be well defined. +json.exception.type_error.314 | only objects can be unflattened | The @ref unflatten function only works for an object whose keys are JSON Pointers. +json.exception.type_error.315 | values in object must be primitive | The @ref unflatten function only works for an object whose keys are JSON Pointers and whose values are primitive. +json.exception.type_error.316 | invalid UTF-8 byte at index 10: 0x7E | The @ref dump function only works with UTF-8 encoded strings; that is, if you assign a `std::string` to a JSON value, make sure it is UTF-8 encoded. | +json.exception.type_error.317 | JSON value cannot be serialized to requested format | The dynamic type of the object cannot be represented in the requested serialization format (e.g. a raw `true` or `null` JSON object cannot be serialized to BSON) | -template -struct is_constructible_string_type_impl : std::false_type {}; +@liveexample{The following code shows how a `type_error` exception can be +caught.,type_error} -template -struct is_constructible_string_type_impl < - BasicJsonType, ConstructibleStringType, - enable_if_t::value >> +@sa - @ref exception for the base class of the library exceptions +@sa - @ref parse_error for exceptions indicating a parse error +@sa - @ref invalid_iterator for exceptions indicating errors with iterators +@sa - @ref out_of_range for exceptions indicating access out of the defined range +@sa - @ref other_error for exceptions indicating other library errors + +@since version 3.0.0 +*/ +class type_error : public exception { - static constexpr auto value = - std::is_constructible::value; + public: + template + static type_error create(int id_, const std::string& what_arg, const DiagnosticsContext& context = nullptr) + { + std::string w = exception::name("type_error", id_) + diagnostics_message(context) + what_arg; + return type_error(id_, w.c_str()); + } + + private: + JSON_HEDLEY_NON_NULL(3) + type_error(int id_, const char* what_arg) : exception(id_, what_arg) {} }; -template -struct is_constructible_string_type - : is_constructible_string_type_impl {}; +/*! +@brief exception indicating access out of the defined range -template -struct is_compatible_array_type_impl : std::false_type {}; +This exception is thrown in case a library function is called on an input +parameter that exceeds the expected range, for instance in case of array +indices or nonexisting object keys. -template -struct is_compatible_array_type_impl < - BasicJsonType, CompatibleArrayType, - enable_if_t < is_detected::value&& - is_detected::value&& -// This is needed because json_reverse_iterator has a ::iterator type... -// Therefore it is detected as a CompatibleArrayType. -// The real fix would be to have an Iterable concept. - !is_iterator_traits < - iterator_traits>::value >> -{ - static constexpr bool value = - std::is_constructible::value; -}; +Exceptions have ids 4xx. -template -struct is_compatible_array_type - : is_compatible_array_type_impl {}; +name / id | example message | description +------------------------------- | --------------- | ------------------------- +json.exception.out_of_range.401 | array index 3 is out of range | The provided array index @a i is larger than @a size-1. +json.exception.out_of_range.402 | array index '-' (3) is out of range | The special array index `-` in a JSON Pointer never describes a valid element of the array, but the index past the end. That is, it can only be used to add elements at this position, but not to read it. +json.exception.out_of_range.403 | key 'foo' not found | The provided key was not found in the JSON object. +json.exception.out_of_range.404 | unresolved reference token 'foo' | A reference token in a JSON Pointer could not be resolved. +json.exception.out_of_range.405 | JSON pointer has no parent | The JSON Patch operations 'remove' and 'add' can not be applied to the root element of the JSON value. +json.exception.out_of_range.406 | number overflow parsing '10E1000' | A parsed number could not be stored as without changing it to NaN or INF. +json.exception.out_of_range.407 | number overflow serializing '9223372036854775808' | UBJSON and BSON only support integer numbers up to 9223372036854775807. (until version 3.8.0) | +json.exception.out_of_range.408 | excessive array size: 8658170730974374167 | The size (following `#`) of an UBJSON array or object exceeds the maximal capacity. | +json.exception.out_of_range.409 | BSON key cannot contain code point U+0000 (at byte 2) | Key identifiers to be serialized to BSON cannot contain code point U+0000, since the key is stored as zero-terminated c-string | -template -struct is_constructible_array_type_impl : std::false_type {}; +@liveexample{The following code shows how an `out_of_range` exception can be +caught.,out_of_range} -template -struct is_constructible_array_type_impl < - BasicJsonType, ConstructibleArrayType, - enable_if_t::value >> - : std::true_type {}; +@sa - @ref exception for the base class of the library exceptions +@sa - @ref parse_error for exceptions indicating a parse error +@sa - @ref invalid_iterator for exceptions indicating errors with iterators +@sa - @ref type_error for exceptions indicating executing a member function with + a wrong type +@sa - @ref other_error for exceptions indicating other library errors -template -struct is_constructible_array_type_impl < - BasicJsonType, ConstructibleArrayType, - enable_if_t < !std::is_same::value&& - std::is_default_constructible::value&& -(std::is_move_assignable::value || - std::is_copy_assignable::value)&& -is_detected::value&& -is_detected::value&& -is_complete_type < -detected_t>::value >> +@since version 3.0.0 +*/ +class out_of_range : public exception { - static constexpr bool value = - // This is needed because json_reverse_iterator has a ::iterator type, - // furthermore, std::back_insert_iterator (and other iterators) have a - // base class `iterator`... Therefore it is detected as a - // ConstructibleArrayType. The real fix would be to have an Iterable - // concept. - !is_iterator_traits>::value && + public: + template + static out_of_range create(int id_, const std::string& what_arg, const DiagnosticsContext& context = nullptr) + { + std::string w = exception::name("out_of_range", id_) + diagnostics_message(context) + what_arg; + return out_of_range(id_, w.c_str()); + } - (std::is_same::value || - has_from_json::value || - has_non_default_from_json < - BasicJsonType, typename ConstructibleArrayType::value_type >::value); + private: + JSON_HEDLEY_NON_NULL(3) + out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {} }; -template -struct is_constructible_array_type - : is_constructible_array_type_impl {}; +/*! +@brief exception indicating other library errors -template -struct is_compatible_integer_type_impl : std::false_type {}; +This exception is thrown in case of errors that cannot be classified with the +other exception types. -template -struct is_compatible_integer_type_impl < - RealIntegerType, CompatibleNumberIntegerType, - enable_if_t < std::is_integral::value&& - std::is_integral::value&& - !std::is_same::value >> -{ - // is there an assert somewhere on overflows? - using RealLimits = std::numeric_limits; - using CompatibleLimits = std::numeric_limits; +Exceptions have ids 5xx. - static constexpr auto value = - std::is_constructible::value && - CompatibleLimits::is_integer && - RealLimits::is_signed == CompatibleLimits::is_signed; -}; +name / id | example message | description +------------------------------ | --------------- | ------------------------- +json.exception.other_error.501 | unsuccessful: {"op":"test","path":"/baz", "value":"bar"} | A JSON Patch operation 'test' failed. The unsuccessful operation is also printed. -template -struct is_compatible_integer_type - : is_compatible_integer_type_impl {}; +@sa - @ref exception for the base class of the library exceptions +@sa - @ref parse_error for exceptions indicating a parse error +@sa - @ref invalid_iterator for exceptions indicating errors with iterators +@sa - @ref type_error for exceptions indicating executing a member function with + a wrong type +@sa - @ref out_of_range for exceptions indicating access out of the defined range -template -struct is_compatible_type_impl: std::false_type {}; +@liveexample{The following code shows how an `other_error` exception can be +caught.,other_error} -template -struct is_compatible_type_impl < - BasicJsonType, CompatibleType, - enable_if_t::value >> +@since version 3.0.0 +*/ +class other_error : public exception { - static constexpr bool value = - has_to_json::value; + public: + template + static other_error create(int id_, const std::string& what_arg, const DiagnosticsContext& context = nullptr) + { + std::string w = exception::name("other_error", id_) + diagnostics_message(context) + what_arg; + return other_error(id_, w.c_str()); + } + + private: + JSON_HEDLEY_NON_NULL(3) + other_error(int id_, const char* what_arg) : exception(id_, what_arg) {} }; +} // namespace detail +} // namespace nlohmann -template -struct is_compatible_type - : is_compatible_type_impl {}; +// #include -// https://en.cppreference.com/w/cpp/types/conjunction -template struct conjunction : std::true_type { }; -template struct conjunction : B1 { }; -template -struct conjunction -: std::conditional, B1>::type {}; +// #include -template -struct is_constructible_tuple : std::false_type {}; +// #include -template -struct is_constructible_tuple> : conjunction...> {}; -} // namespace detail -} // namespace nlohmann +// #include // #include From 985b21bec95f126bb3482e57c032508ca495a258 Mon Sep 17 00:00:00 2001 From: Alexander Karzhenkov Date: Sun, 24 Jan 2021 12:07:47 +0500 Subject: [PATCH 3/5] Revert headers that use empty diagnostics only --- .../nlohmann/detail/input/binary_reader.hpp | 38 ++++++++------- include/nlohmann/detail/output/serializer.hpp | 6 +-- single_include/nlohmann/json.hpp | 46 ++++++++----------- 3 files changed, 40 insertions(+), 50 deletions(-) diff --git a/include/nlohmann/detail/input/binary_reader.hpp b/include/nlohmann/detail/input/binary_reader.hpp index a896f15586..806e360306 100644 --- a/include/nlohmann/detail/input/binary_reader.hpp +++ b/include/nlohmann/detail/input/binary_reader.hpp @@ -13,7 +13,6 @@ #include // make_pair, move #include // vector -#include #include #include #include @@ -65,7 +64,6 @@ class binary_reader using json_sax_t = SAX; using char_type = typename InputAdapterType::char_type; using char_int_type = typename std::char_traits::int_type; - using diagnostics_t = detail::diagnostics_t; public: /*! @@ -139,7 +137,7 @@ class binary_reader if (JSON_HEDLEY_UNLIKELY(current != std::char_traits::eof())) { return sax->parse_error(chars_read, get_token_string(), - parse_error::create(110, chars_read, exception_message(format, "expected end of input; last byte: 0x" + get_token_string(), "value"), diagnostics_t())); + parse_error::create(110, chars_read, exception_message(format, "expected end of input; last byte: 0x" + get_token_string(), "value"))); } } @@ -215,7 +213,7 @@ class binary_reader if (JSON_HEDLEY_UNLIKELY(len < 1)) { auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::bson, "string length must be at least 1, is " + std::to_string(len), "string"), diagnostics_t())); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::bson, "string length must be at least 1, is " + std::to_string(len), "string"))); } return get_string(input_format_t::bson, len - static_cast(1), result) && get() != std::char_traits::eof(); @@ -236,7 +234,7 @@ class binary_reader if (JSON_HEDLEY_UNLIKELY(len < 0)) { auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::bson, "byte array length cannot be negative, is " + std::to_string(len), "binary"), diagnostics_t())); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::bson, "byte array length cannot be negative, is " + std::to_string(len), "binary"))); } // All BSON binary values have a subtype @@ -318,7 +316,7 @@ class binary_reader { std::array cr{{}}; (std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast(element_type)); - return sax->parse_error(element_type_parse_position, std::string(cr.data()), parse_error::create(114, element_type_parse_position, "Unsupported BSON record type 0x" + std::string(cr.data()), diagnostics_t())); + return sax->parse_error(element_type_parse_position, std::string(cr.data()), parse_error::create(114, element_type_parse_position, "Unsupported BSON record type 0x" + std::string(cr.data()))); } } } @@ -718,7 +716,7 @@ class binary_reader case cbor_tag_handler_t::error: { auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::cbor, "invalid byte: 0x" + last_token, "value"), diagnostics_t())); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::cbor, "invalid byte: 0x" + last_token, "value"))); } case cbor_tag_handler_t::ignore: @@ -833,7 +831,7 @@ class binary_reader default: // anything else (0xFF is handled inside the other types) { auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::cbor, "invalid byte: 0x" + last_token, "value"), diagnostics_t())); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::cbor, "invalid byte: 0x" + last_token, "value"))); } } } @@ -928,7 +926,7 @@ class binary_reader default: { auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::cbor, "expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x" + last_token, "string"), diagnostics_t())); + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::cbor, "expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x" + last_token, "string"))); } } } @@ -1027,7 +1025,7 @@ class binary_reader default: { auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::cbor, "expected length specification (0x40-0x5B) or indefinite binary array type (0x5F); last byte: 0x" + last_token, "binary"), diagnostics_t())); + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::cbor, "expected length specification (0x40-0x5B) or indefinite binary array type (0x5F); last byte: 0x" + last_token, "binary"))); } } } @@ -1494,7 +1492,7 @@ class binary_reader default: // anything else { auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::msgpack, "invalid byte: 0x" + last_token, "value"), diagnostics_t())); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::msgpack, "invalid byte: 0x" + last_token, "value"))); } } } @@ -1576,7 +1574,7 @@ class binary_reader default: { auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::msgpack, "expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x" + last_token, "string"), diagnostics_t())); + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::msgpack, "expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x" + last_token, "string"))); } } } @@ -1826,7 +1824,7 @@ class binary_reader default: auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token, "string"), diagnostics_t())); + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token, "string"))); } } @@ -1896,7 +1894,7 @@ class binary_reader default: { auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token, "size"), diagnostics_t())); + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token, "size"))); } } } @@ -1934,7 +1932,7 @@ class binary_reader return false; } auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, "expected '#' after type information; last byte: 0x" + last_token, "size"), diagnostics_t())); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, "expected '#' after type information; last byte: 0x" + last_token, "size"))); } return get_ubjson_size_value(result.first); @@ -2024,7 +2022,7 @@ class binary_reader if (JSON_HEDLEY_UNLIKELY(current > 127)) { auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "byte after 'C' must be in range 0x00..0x7F; last byte: 0x" + last_token, "char"), diagnostics_t())); + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "byte after 'C' must be in range 0x00..0x7F; last byte: 0x" + last_token, "char"))); } string_t s(1, static_cast(current)); return sax->string(s); @@ -2045,7 +2043,7 @@ class binary_reader default: // anything else { auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, "invalid byte: 0x" + last_token, "value"), diagnostics_t())); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, "invalid byte: 0x" + last_token, "value"))); } } } @@ -2223,7 +2221,7 @@ class binary_reader if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input)) { - return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, exception_message(input_format_t::ubjson, "invalid number text: " + number_lexer.get_token_string(), "high-precision number"), diagnostics_t())); + return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, exception_message(input_format_t::ubjson, "invalid number text: " + number_lexer.get_token_string(), "high-precision number"))); } switch (result_number) @@ -2235,7 +2233,7 @@ class binary_reader case token_type::value_float: return sax->number_float(number_lexer.get_number_float(), std::move(number_string)); default: - return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, exception_message(input_format_t::ubjson, "invalid number text: " + number_lexer.get_token_string(), "high-precision number"), diagnostics_t())); + return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, exception_message(input_format_t::ubjson, "invalid number text: " + number_lexer.get_token_string(), "high-precision number"))); } } @@ -2391,7 +2389,7 @@ class binary_reader if (JSON_HEDLEY_UNLIKELY(current == std::char_traits::eof())) { return sax->parse_error(chars_read, "", - parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), diagnostics_t())); + parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context))); } return true; } diff --git a/include/nlohmann/detail/output/serializer.hpp b/include/nlohmann/detail/output/serializer.hpp index 7c570f8cb7..0a34c8011e 100644 --- a/include/nlohmann/detail/output/serializer.hpp +++ b/include/nlohmann/detail/output/serializer.hpp @@ -13,7 +13,6 @@ #include // move #include -#include #include #include #include @@ -45,7 +44,6 @@ class serializer using number_integer_t = typename BasicJsonType::number_integer_t; using number_unsigned_t = typename BasicJsonType::number_unsigned_t; using binary_char_t = typename BasicJsonType::binary_t::value_type; - using diagnostics_t = detail::diagnostics_t; static constexpr std::uint8_t UTF8_ACCEPT = 0; static constexpr std::uint8_t UTF8_REJECT = 1; @@ -501,7 +499,7 @@ class serializer { std::string sn(3, '\0'); (std::snprintf)(&sn[0], sn.size(), "%.2X", byte); - JSON_THROW(type_error::create(316, "invalid UTF-8 byte at index " + std::to_string(i) + ": 0x" + sn, diagnostics_t())); + JSON_THROW(type_error::create(316, "invalid UTF-8 byte at index " + std::to_string(i) + ": 0x" + sn)); } case error_handler_t::ignore: @@ -595,7 +593,7 @@ class serializer { std::string sn(3, '\0'); (std::snprintf)(&sn[0], sn.size(), "%.2X", static_cast(s.back())); - JSON_THROW(type_error::create(316, "incomplete UTF-8 string; last byte: 0x" + sn, diagnostics_t())); + JSON_THROW(type_error::create(316, "incomplete UTF-8 string; last byte: 0x" + sn)); } case error_handler_t::ignore: diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index f07ebf2f0a..644fc32f57 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -5000,8 +5000,6 @@ std::size_t hash(const BasicJsonType& j) #include // make_pair, move #include // vector -// #include - // #include // #include @@ -8027,7 +8025,6 @@ class binary_reader using json_sax_t = SAX; using char_type = typename InputAdapterType::char_type; using char_int_type = typename std::char_traits::int_type; - using diagnostics_t = detail::diagnostics_t; public: /*! @@ -8101,7 +8098,7 @@ class binary_reader if (JSON_HEDLEY_UNLIKELY(current != std::char_traits::eof())) { return sax->parse_error(chars_read, get_token_string(), - parse_error::create(110, chars_read, exception_message(format, "expected end of input; last byte: 0x" + get_token_string(), "value"), diagnostics_t())); + parse_error::create(110, chars_read, exception_message(format, "expected end of input; last byte: 0x" + get_token_string(), "value"))); } } @@ -8177,7 +8174,7 @@ class binary_reader if (JSON_HEDLEY_UNLIKELY(len < 1)) { auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::bson, "string length must be at least 1, is " + std::to_string(len), "string"), diagnostics_t())); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::bson, "string length must be at least 1, is " + std::to_string(len), "string"))); } return get_string(input_format_t::bson, len - static_cast(1), result) && get() != std::char_traits::eof(); @@ -8198,7 +8195,7 @@ class binary_reader if (JSON_HEDLEY_UNLIKELY(len < 0)) { auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::bson, "byte array length cannot be negative, is " + std::to_string(len), "binary"), diagnostics_t())); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::bson, "byte array length cannot be negative, is " + std::to_string(len), "binary"))); } // All BSON binary values have a subtype @@ -8280,7 +8277,7 @@ class binary_reader { std::array cr{{}}; (std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast(element_type)); - return sax->parse_error(element_type_parse_position, std::string(cr.data()), parse_error::create(114, element_type_parse_position, "Unsupported BSON record type 0x" + std::string(cr.data()), diagnostics_t())); + return sax->parse_error(element_type_parse_position, std::string(cr.data()), parse_error::create(114, element_type_parse_position, "Unsupported BSON record type 0x" + std::string(cr.data()))); } } } @@ -8680,7 +8677,7 @@ class binary_reader case cbor_tag_handler_t::error: { auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::cbor, "invalid byte: 0x" + last_token, "value"), diagnostics_t())); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::cbor, "invalid byte: 0x" + last_token, "value"))); } case cbor_tag_handler_t::ignore: @@ -8795,7 +8792,7 @@ class binary_reader default: // anything else (0xFF is handled inside the other types) { auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::cbor, "invalid byte: 0x" + last_token, "value"), diagnostics_t())); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::cbor, "invalid byte: 0x" + last_token, "value"))); } } } @@ -8890,7 +8887,7 @@ class binary_reader default: { auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::cbor, "expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x" + last_token, "string"), diagnostics_t())); + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::cbor, "expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x" + last_token, "string"))); } } } @@ -8989,7 +8986,7 @@ class binary_reader default: { auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::cbor, "expected length specification (0x40-0x5B) or indefinite binary array type (0x5F); last byte: 0x" + last_token, "binary"), diagnostics_t())); + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::cbor, "expected length specification (0x40-0x5B) or indefinite binary array type (0x5F); last byte: 0x" + last_token, "binary"))); } } } @@ -9456,7 +9453,7 @@ class binary_reader default: // anything else { auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::msgpack, "invalid byte: 0x" + last_token, "value"), diagnostics_t())); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::msgpack, "invalid byte: 0x" + last_token, "value"))); } } } @@ -9538,7 +9535,7 @@ class binary_reader default: { auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::msgpack, "expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x" + last_token, "string"), diagnostics_t())); + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::msgpack, "expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x" + last_token, "string"))); } } } @@ -9788,7 +9785,7 @@ class binary_reader default: auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token, "string"), diagnostics_t())); + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token, "string"))); } } @@ -9858,7 +9855,7 @@ class binary_reader default: { auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token, "size"), diagnostics_t())); + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token, "size"))); } } } @@ -9896,7 +9893,7 @@ class binary_reader return false; } auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, "expected '#' after type information; last byte: 0x" + last_token, "size"), diagnostics_t())); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, "expected '#' after type information; last byte: 0x" + last_token, "size"))); } return get_ubjson_size_value(result.first); @@ -9986,7 +9983,7 @@ class binary_reader if (JSON_HEDLEY_UNLIKELY(current > 127)) { auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "byte after 'C' must be in range 0x00..0x7F; last byte: 0x" + last_token, "char"), diagnostics_t())); + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "byte after 'C' must be in range 0x00..0x7F; last byte: 0x" + last_token, "char"))); } string_t s(1, static_cast(current)); return sax->string(s); @@ -10007,7 +10004,7 @@ class binary_reader default: // anything else { auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, "invalid byte: 0x" + last_token, "value"), diagnostics_t())); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, "invalid byte: 0x" + last_token, "value"))); } } } @@ -10185,7 +10182,7 @@ class binary_reader if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input)) { - return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, exception_message(input_format_t::ubjson, "invalid number text: " + number_lexer.get_token_string(), "high-precision number"), diagnostics_t())); + return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, exception_message(input_format_t::ubjson, "invalid number text: " + number_lexer.get_token_string(), "high-precision number"))); } switch (result_number) @@ -10197,7 +10194,7 @@ class binary_reader case token_type::value_float: return sax->number_float(number_lexer.get_number_float(), std::move(number_string)); default: - return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, exception_message(input_format_t::ubjson, "invalid number text: " + number_lexer.get_token_string(), "high-precision number"), diagnostics_t())); + return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, exception_message(input_format_t::ubjson, "invalid number text: " + number_lexer.get_token_string(), "high-precision number"))); } } @@ -10353,7 +10350,7 @@ class binary_reader if (JSON_HEDLEY_UNLIKELY(current == std::char_traits::eof())) { return sax->parse_error(chars_read, "", - parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), diagnostics_t())); + parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context))); } return true; } @@ -15743,8 +15740,6 @@ char* to_chars(char* first, const char* last, FloatType value) } // namespace detail } // namespace nlohmann -// #include - // #include // #include @@ -15782,7 +15777,6 @@ class serializer using number_integer_t = typename BasicJsonType::number_integer_t; using number_unsigned_t = typename BasicJsonType::number_unsigned_t; using binary_char_t = typename BasicJsonType::binary_t::value_type; - using diagnostics_t = detail::diagnostics_t; static constexpr std::uint8_t UTF8_ACCEPT = 0; static constexpr std::uint8_t UTF8_REJECT = 1; @@ -16238,7 +16232,7 @@ class serializer { std::string sn(3, '\0'); (std::snprintf)(&sn[0], sn.size(), "%.2X", byte); - JSON_THROW(type_error::create(316, "invalid UTF-8 byte at index " + std::to_string(i) + ": 0x" + sn, diagnostics_t())); + JSON_THROW(type_error::create(316, "invalid UTF-8 byte at index " + std::to_string(i) + ": 0x" + sn)); } case error_handler_t::ignore: @@ -16332,7 +16326,7 @@ class serializer { std::string sn(3, '\0'); (std::snprintf)(&sn[0], sn.size(), "%.2X", static_cast(s.back())); - JSON_THROW(type_error::create(316, "incomplete UTF-8 string; last byte: 0x" + sn, diagnostics_t())); + JSON_THROW(type_error::create(316, "incomplete UTF-8 string; last byte: 0x" + sn)); } case error_handler_t::ignore: From 716f697a829625e9709c1d31c18c10e99b6f3ce2 Mon Sep 17 00:00:00 2001 From: Alexander Karzhenkov Date: Sun, 24 Jan 2021 12:37:42 +0500 Subject: [PATCH 4/5] Other cleanup related to empty diagnostics --- include/nlohmann/detail/input/parser.hpp | 26 +++++----- include/nlohmann/detail/json_pointer.hpp | 24 ++++++---- include/nlohmann/json.hpp | 10 ++-- single_include/nlohmann/json.hpp | 61 ++++++++++++------------ 4 files changed, 62 insertions(+), 59 deletions(-) diff --git a/include/nlohmann/detail/input/parser.hpp b/include/nlohmann/detail/input/parser.hpp index d9ac2b684c..264714ae5e 100644 --- a/include/nlohmann/detail/input/parser.hpp +++ b/include/nlohmann/detail/input/parser.hpp @@ -8,7 +8,6 @@ #include // vector #include -#include #include #include #include @@ -58,7 +57,6 @@ class parser using string_t = typename BasicJsonType::string_t; using lexer_t = lexer; using token_type = typename lexer_t::token_type; - using diagnostics_t = detail::diagnostics_t; public: /// a parser reading from an input adapter @@ -97,7 +95,7 @@ class parser sdp.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, "value"), diagnostics_t())); + exception_message(token_type::end_of_input, "value"))); } // in case of an error, return discarded value @@ -125,7 +123,7 @@ class parser sdp.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, "value"), diagnostics_t())); + exception_message(token_type::end_of_input, "value"))); } // in case of an error, return discarded value @@ -164,7 +162,7 @@ class parser 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, "value"), diagnostics_t())); + exception_message(token_type::end_of_input, "value"))); } return result; @@ -211,7 +209,7 @@ class parser 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::value_string, "object key"), diagnostics_t())); + exception_message(token_type::value_string, "object key"))); } if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string()))) { @@ -224,7 +222,7 @@ class parser 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::name_separator, "object separator"), diagnostics_t())); + exception_message(token_type::name_separator, "object separator"))); } // remember we are now inside an object @@ -267,7 +265,7 @@ class parser { return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), - out_of_range::create(406, "number overflow parsing '" + m_lexer.get_token_string() + "'", diagnostics_t())); + out_of_range::create(406, "number overflow parsing '" + m_lexer.get_token_string() + "'")); } if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string()))) @@ -338,7 +336,7 @@ class parser 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::uninitialized, "value"), diagnostics_t())); + exception_message(token_type::uninitialized, "value"))); } default: // the last token was unexpected @@ -346,7 +344,7 @@ class parser 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::literal_or_value, "value"), diagnostics_t())); + exception_message(token_type::literal_or_value, "value"))); } } } @@ -393,7 +391,7 @@ class parser 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_array, "array"), diagnostics_t())); + exception_message(token_type::end_array, "array"))); } else // object { @@ -406,7 +404,7 @@ class parser 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::value_string, "object key"), diagnostics_t())); + exception_message(token_type::value_string, "object key"))); } if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string()))) @@ -420,7 +418,7 @@ class parser 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::name_separator, "object separator"), diagnostics_t())); + exception_message(token_type::name_separator, "object separator"))); } // parse values @@ -449,7 +447,7 @@ class parser 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_object, "object"), diagnostics_t())); + exception_message(token_type::end_object, "object"))); } } } diff --git a/include/nlohmann/detail/json_pointer.hpp b/include/nlohmann/detail/json_pointer.hpp index 9fb7d0d22a..a241282f28 100644 --- a/include/nlohmann/detail/json_pointer.hpp +++ b/include/nlohmann/detail/json_pointer.hpp @@ -251,7 +251,7 @@ class json_pointer { if (JSON_HEDLEY_UNLIKELY(empty())) { - JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", diagnostics_t())); + JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent")); } reference_tokens.pop_back(); @@ -275,7 +275,7 @@ class json_pointer { if (JSON_HEDLEY_UNLIKELY(empty())) { - JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", diagnostics_t())); + JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent")); } return reference_tokens.back(); @@ -341,13 +341,15 @@ class json_pointer // error condition (cf. RFC 6901, Sect. 4) if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0')) { - JSON_THROW(detail::parse_error::create(106, 0, "array index '" + s + "' must not begin with '0'", diagnostics_t())); + JSON_THROW(detail::parse_error::create(106, 0, + "array index '" + s + + "' must not begin with '0'")); } // error condition (cf. RFC 6901, Sect. 4) if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9'))) { - JSON_THROW(detail::parse_error::create(109, 0, "array index '" + s + "' is not a number", diagnostics_t())); + JSON_THROW(detail::parse_error::create(109, 0, "array index '" + s + "' is not a number")); } std::size_t processed_chars = 0; @@ -358,20 +360,20 @@ class json_pointer } JSON_CATCH(std::out_of_range&) { - JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'", diagnostics_t())); + JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'")); } // check if the string was completely read if (JSON_HEDLEY_UNLIKELY(processed_chars != s.size())) { - JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'", diagnostics_t())); + JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'")); } // only triggered on special platforms (like 32bit), see also // https://github.com/nlohmann/json/pull/2203 if (res >= static_cast((std::numeric_limits::max)())) { - JSON_THROW(detail::out_of_range::create(410, "array index " + s + " exceeds size_type", diagnostics_t())); // LCOV_EXCL_LINE + JSON_THROW(detail::out_of_range::create(410, "array index " + s + " exceeds size_type")); // LCOV_EXCL_LINE } return static_cast(res); @@ -382,7 +384,7 @@ class json_pointer { if (JSON_HEDLEY_UNLIKELY(empty())) { - JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", diagnostics_t())); + JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent")); } json_pointer result = *this; @@ -752,7 +754,9 @@ class json_pointer // check if nonempty reference string begins with slash if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/')) { - JSON_THROW(detail::parse_error::create(107, 1, "JSON pointer must be empty or begin with '/' - was: '" + reference_string + "'", diagnostics_t())); + JSON_THROW(detail::parse_error::create(107, 1, + "JSON pointer must be empty or begin with '/' - was: '" + + reference_string + "'")); } // extract the reference tokens: @@ -787,7 +791,7 @@ class json_pointer (reference_token[pos + 1] != '0' && reference_token[pos + 1] != '1'))) { - JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'", diagnostics_t())); + JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'")); } } diff --git a/include/nlohmann/json.hpp b/include/nlohmann/json.hpp index b7fcc466a0..f424eec5f3 100644 --- a/include/nlohmann/json.hpp +++ b/include/nlohmann/json.hpp @@ -1066,7 +1066,7 @@ class basic_json object = nullptr; // silence warning, see #821 if (JSON_HEDLEY_UNLIKELY(t == value_t::null)) { - JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.9.1", diagnostics_t())); // LCOV_EXCL_LINE + JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.9.1")); // LCOV_EXCL_LINE } break; } @@ -1707,7 +1707,7 @@ class basic_json // if object is wanted but impossible, throw an exception if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object)) { - JSON_THROW(type_error::create(301, "cannot create object from initializer list", diagnostics_t())); + JSON_THROW(type_error::create(301, "cannot create object from initializer list")); } } @@ -2012,7 +2012,7 @@ class basic_json // make sure iterator fits the current value if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) { - JSON_THROW(invalid_iterator::create(201, "iterators are not compatible", diagnostics_t())); + JSON_THROW(invalid_iterator::create(201, "iterators are not compatible")); } // copy type from first iterator @@ -2030,7 +2030,7 @@ class basic_json if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin() || !last.m_it.primitive_iterator.is_end())) { - JSON_THROW(invalid_iterator::create(204, "iterators out of range", diagnostics_t())); + JSON_THROW(invalid_iterator::create(204, "iterators out of range")); } break; } @@ -2092,7 +2092,7 @@ class basic_json } default: - JSON_THROW(invalid_iterator::create(206, "cannot construct with iterators from " + std::string(first.m_object->type_name()), diagnostics_t())); + JSON_THROW(invalid_iterator::create(206, "cannot construct with iterators from " + std::string(first.m_object->type_name()))); } set_parents(); diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 644fc32f57..edd0587ffa 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -10437,8 +10437,6 @@ class binary_reader // #include -// #include - // #include // #include @@ -10494,7 +10492,6 @@ class parser using string_t = typename BasicJsonType::string_t; using lexer_t = lexer; using token_type = typename lexer_t::token_type; - using diagnostics_t = detail::diagnostics_t; public: /// a parser reading from an input adapter @@ -10533,7 +10530,7 @@ class parser sdp.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, "value"), diagnostics_t())); + exception_message(token_type::end_of_input, "value"))); } // in case of an error, return discarded value @@ -10561,7 +10558,7 @@ class parser sdp.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, "value"), diagnostics_t())); + exception_message(token_type::end_of_input, "value"))); } // in case of an error, return discarded value @@ -10600,7 +10597,7 @@ class parser 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, "value"), diagnostics_t())); + exception_message(token_type::end_of_input, "value"))); } return result; @@ -10647,7 +10644,7 @@ class parser 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::value_string, "object key"), diagnostics_t())); + exception_message(token_type::value_string, "object key"))); } if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string()))) { @@ -10660,7 +10657,7 @@ class parser 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::name_separator, "object separator"), diagnostics_t())); + exception_message(token_type::name_separator, "object separator"))); } // remember we are now inside an object @@ -10703,7 +10700,7 @@ class parser { return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), - out_of_range::create(406, "number overflow parsing '" + m_lexer.get_token_string() + "'", diagnostics_t())); + out_of_range::create(406, "number overflow parsing '" + m_lexer.get_token_string() + "'")); } if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string()))) @@ -10774,7 +10771,7 @@ class parser 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::uninitialized, "value"), diagnostics_t())); + exception_message(token_type::uninitialized, "value"))); } default: // the last token was unexpected @@ -10782,7 +10779,7 @@ class parser 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::literal_or_value, "value"), diagnostics_t())); + exception_message(token_type::literal_or_value, "value"))); } } } @@ -10829,7 +10826,7 @@ class parser 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_array, "array"), diagnostics_t())); + exception_message(token_type::end_array, "array"))); } else // object { @@ -10842,7 +10839,7 @@ class parser 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::value_string, "object key"), diagnostics_t())); + exception_message(token_type::value_string, "object key"))); } if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string()))) @@ -10856,7 +10853,7 @@ class parser 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::name_separator, "object separator"), diagnostics_t())); + exception_message(token_type::name_separator, "object separator"))); } // parse values @@ -10885,7 +10882,7 @@ class parser 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_object, "object"), diagnostics_t())); + exception_message(token_type::end_object, "object"))); } } } @@ -12127,7 +12124,7 @@ class json_pointer { if (JSON_HEDLEY_UNLIKELY(empty())) { - JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", diagnostics_t())); + JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent")); } reference_tokens.pop_back(); @@ -12151,7 +12148,7 @@ class json_pointer { if (JSON_HEDLEY_UNLIKELY(empty())) { - JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", diagnostics_t())); + JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent")); } return reference_tokens.back(); @@ -12217,13 +12214,15 @@ class json_pointer // error condition (cf. RFC 6901, Sect. 4) if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0')) { - JSON_THROW(detail::parse_error::create(106, 0, "array index '" + s + "' must not begin with '0'", diagnostics_t())); + JSON_THROW(detail::parse_error::create(106, 0, + "array index '" + s + + "' must not begin with '0'")); } // error condition (cf. RFC 6901, Sect. 4) if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9'))) { - JSON_THROW(detail::parse_error::create(109, 0, "array index '" + s + "' is not a number", diagnostics_t())); + JSON_THROW(detail::parse_error::create(109, 0, "array index '" + s + "' is not a number")); } std::size_t processed_chars = 0; @@ -12234,20 +12233,20 @@ class json_pointer } JSON_CATCH(std::out_of_range&) { - JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'", diagnostics_t())); + JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'")); } // check if the string was completely read if (JSON_HEDLEY_UNLIKELY(processed_chars != s.size())) { - JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'", diagnostics_t())); + JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'")); } // only triggered on special platforms (like 32bit), see also // https://github.com/nlohmann/json/pull/2203 if (res >= static_cast((std::numeric_limits::max)())) { - JSON_THROW(detail::out_of_range::create(410, "array index " + s + " exceeds size_type", diagnostics_t())); // LCOV_EXCL_LINE + JSON_THROW(detail::out_of_range::create(410, "array index " + s + " exceeds size_type")); // LCOV_EXCL_LINE } return static_cast(res); @@ -12258,7 +12257,7 @@ class json_pointer { if (JSON_HEDLEY_UNLIKELY(empty())) { - JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", diagnostics_t())); + JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent")); } json_pointer result = *this; @@ -12628,7 +12627,9 @@ class json_pointer // check if nonempty reference string begins with slash if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/')) { - JSON_THROW(detail::parse_error::create(107, 1, "JSON pointer must be empty or begin with '/' - was: '" + reference_string + "'", diagnostics_t())); + JSON_THROW(detail::parse_error::create(107, 1, + "JSON pointer must be empty or begin with '/' - was: '" + + reference_string + "'")); } // extract the reference tokens: @@ -12663,7 +12664,7 @@ class json_pointer (reference_token[pos + 1] != '0' && reference_token[pos + 1] != '1'))) { - JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'", diagnostics_t())); + JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'")); } } @@ -17867,7 +17868,7 @@ class basic_json object = nullptr; // silence warning, see #821 if (JSON_HEDLEY_UNLIKELY(t == value_t::null)) { - JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.9.1", diagnostics_t())); // LCOV_EXCL_LINE + JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.9.1")); // LCOV_EXCL_LINE } break; } @@ -18508,7 +18509,7 @@ class basic_json // if object is wanted but impossible, throw an exception if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object)) { - JSON_THROW(type_error::create(301, "cannot create object from initializer list", diagnostics_t())); + JSON_THROW(type_error::create(301, "cannot create object from initializer list")); } } @@ -18813,7 +18814,7 @@ class basic_json // make sure iterator fits the current value if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) { - JSON_THROW(invalid_iterator::create(201, "iterators are not compatible", diagnostics_t())); + JSON_THROW(invalid_iterator::create(201, "iterators are not compatible")); } // copy type from first iterator @@ -18831,7 +18832,7 @@ class basic_json if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin() || !last.m_it.primitive_iterator.is_end())) { - JSON_THROW(invalid_iterator::create(204, "iterators out of range", diagnostics_t())); + JSON_THROW(invalid_iterator::create(204, "iterators out of range")); } break; } @@ -18893,7 +18894,7 @@ class basic_json } default: - JSON_THROW(invalid_iterator::create(206, "cannot construct with iterators from " + std::string(first.m_object->type_name()), diagnostics_t())); + JSON_THROW(invalid_iterator::create(206, "cannot construct with iterators from " + std::string(first.m_object->type_name()))); } set_parents(); From c92418f9ccb746c0d018e0de7d74de18f8554614 Mon Sep 17 00:00:00 2001 From: Alexander Karzhenkov Date: Sun, 24 Jan 2021 13:17:53 +0500 Subject: [PATCH 5/5] Use json object as a diagnostics context --- .../nlohmann/detail/conversions/from_json.hpp | 31 ++- include/nlohmann/detail/input/json_sax.hpp | 11 +- .../nlohmann/detail/iterators/iter_impl.hpp | 26 +- include/nlohmann/detail/json_pointer.hpp | 23 +- .../nlohmann/detail/output/binary_writer.hpp | 8 +- include/nlohmann/json.hpp | 133 +++++----- single_include/nlohmann/json.hpp | 237 ++++++++---------- 7 files changed, 218 insertions(+), 251 deletions(-) diff --git a/include/nlohmann/detail/conversions/from_json.hpp b/include/nlohmann/detail/conversions/from_json.hpp index 2a8d7543e2..f03c018159 100644 --- a/include/nlohmann/detail/conversions/from_json.hpp +++ b/include/nlohmann/detail/conversions/from_json.hpp @@ -13,7 +13,6 @@ #include // valarray #include -#include #include #include #include @@ -28,7 +27,7 @@ void from_json(const BasicJsonType& j, typename std::nullptr_t& n) { if (JSON_HEDLEY_UNLIKELY(!j.is_null())) { - JSON_THROW(type_error::create(302, "type must be null, but is " + std::string(j.type_name()), detail::diagnostics_t(j))); + JSON_THROW(type_error::create(302, "type must be null, but is " + std::string(j.type_name()), j)); } n = nullptr; } @@ -59,7 +58,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()), detail::diagnostics_t(j))); + JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()), j)); } } @@ -68,7 +67,7 @@ void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b) { if (JSON_HEDLEY_UNLIKELY(!j.is_boolean())) { - JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(j.type_name()), detail::diagnostics_t(j))); + JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(j.type_name()), j)); } b = *j.template get_ptr(); } @@ -78,7 +77,7 @@ void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s) { if (JSON_HEDLEY_UNLIKELY(!j.is_string())) { - JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), detail::diagnostics_t(j))); + JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), j)); } s = *j.template get_ptr(); } @@ -94,7 +93,7 @@ void from_json(const BasicJsonType& j, ConstructibleStringType& s) { if (JSON_HEDLEY_UNLIKELY(!j.is_string())) { - JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), detail::diagnostics_t(j))); + JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), j)); } s = *j.template get_ptr(); @@ -134,7 +133,7 @@ void from_json(const BasicJsonType& j, std::forward_list& l) { if (JSON_HEDLEY_UNLIKELY(!j.is_array())) { - JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), detail::diagnostics_t(j))); + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j)); } l.clear(); std::transform(j.rbegin(), j.rend(), @@ -151,7 +150,7 @@ void from_json(const BasicJsonType& j, std::valarray& l) { if (JSON_HEDLEY_UNLIKELY(!j.is_array())) { - JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), detail::diagnostics_t(j))); + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j)); } l.resize(j.size()); std::transform(j.begin(), j.end(), std::begin(l), @@ -242,7 +241,7 @@ void()) { if (JSON_HEDLEY_UNLIKELY(!j.is_array())) { - JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), detail::diagnostics_t(j))); + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j)); } from_json_array_impl(j, arr, priority_tag<3> {}); @@ -253,7 +252,7 @@ void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin) { if (JSON_HEDLEY_UNLIKELY(!j.is_binary())) { - JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(j.type_name()), detail::diagnostics_t(j))); + JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(j.type_name()), j)); } bin = *j.template get_ptr(); @@ -265,7 +264,7 @@ void from_json(const BasicJsonType& j, ConstructibleObjectType& obj) { if (JSON_HEDLEY_UNLIKELY(!j.is_object())) { - JSON_THROW(type_error::create(302, "type must be object, but is " + std::string(j.type_name()), detail::diagnostics_t(j))); + JSON_THROW(type_error::create(302, "type must be object, but is " + std::string(j.type_name()), j)); } ConstructibleObjectType ret; @@ -319,7 +318,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()), detail::diagnostics_t(j))); + JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()), j)); } } @@ -348,14 +347,14 @@ void from_json(const BasicJsonType& j, std::map& { if (JSON_HEDLEY_UNLIKELY(!j.is_array())) { - JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), detail::diagnostics_t(j))); + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j)); } m.clear(); for (const auto& p : j) { if (JSON_HEDLEY_UNLIKELY(!p.is_array())) { - JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name()), detail::diagnostics_t(j))); + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name()), j)); } m.emplace(p.at(0).template get(), p.at(1).template get()); } @@ -368,14 +367,14 @@ void from_json(const BasicJsonType& j, std::unordered_map(j))); + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j)); } m.clear(); for (const auto& p : j) { if (JSON_HEDLEY_UNLIKELY(!p.is_array())) { - JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name()), detail::diagnostics_t(j))); + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name()), j)); } m.emplace(p.at(0).template get(), p.at(1).template get()); } diff --git a/include/nlohmann/detail/input/json_sax.hpp b/include/nlohmann/detail/input/json_sax.hpp index 4bd64c80e3..a4b7e6d086 100644 --- a/include/nlohmann/detail/input/json_sax.hpp +++ b/include/nlohmann/detail/input/json_sax.hpp @@ -5,7 +5,6 @@ #include // move #include // vector -#include #include #include @@ -155,7 +154,6 @@ class json_sax_dom_parser using number_float_t = typename BasicJsonType::number_float_t; using string_t = typename BasicJsonType::string_t; using binary_t = typename BasicJsonType::binary_t; - using diagnostics_t = detail::diagnostics_t; /*! @param[in, out] r reference to a JSON value that is manipulated while @@ -221,7 +219,7 @@ class json_sax_dom_parser if (JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size())) { - JSON_THROW(out_of_range::create(408, "excessive object size: " + std::to_string(len), diagnostics_t(*ref_stack.back()))); + JSON_THROW(out_of_range::create(408, "excessive object size: " + std::to_string(len), *ref_stack.back())); } return true; @@ -247,7 +245,7 @@ class json_sax_dom_parser if (JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size())) { - JSON_THROW(out_of_range::create(408, "excessive array size: " + std::to_string(len), diagnostics_t(*ref_stack.back()))); + JSON_THROW(out_of_range::create(408, "excessive array size: " + std::to_string(len), *ref_stack.back())); } return true; @@ -332,7 +330,6 @@ class json_sax_dom_callback_parser using binary_t = typename BasicJsonType::binary_t; using parser_callback_t = typename BasicJsonType::parser_callback_t; using parse_event_t = typename BasicJsonType::parse_event_t; - using diagnostics_t = detail::diagnostics_t; json_sax_dom_callback_parser(BasicJsonType& r, const parser_callback_t cb, @@ -403,7 +400,7 @@ class json_sax_dom_callback_parser // check object limit if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size())) { - JSON_THROW(out_of_range::create(408, "excessive object size: " + std::to_string(len), diagnostics_t(*ref_stack.back()))); + JSON_THROW(out_of_range::create(408, "excessive object size: " + std::to_string(len), *ref_stack.back())); } return true; @@ -473,7 +470,7 @@ class json_sax_dom_callback_parser // check array limit if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size())) { - JSON_THROW(out_of_range::create(408, "excessive array size: " + std::to_string(len), diagnostics_t(*ref_stack.back()))); + JSON_THROW(out_of_range::create(408, "excessive array size: " + std::to_string(len), *ref_stack.back())); } return true; diff --git a/include/nlohmann/detail/iterators/iter_impl.hpp b/include/nlohmann/detail/iterators/iter_impl.hpp index 565ac64d1a..118fef3f51 100644 --- a/include/nlohmann/detail/iterators/iter_impl.hpp +++ b/include/nlohmann/detail/iterators/iter_impl.hpp @@ -3,7 +3,6 @@ #include // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next #include // conditional, is_const, remove_const -#include #include #include #include @@ -52,7 +51,6 @@ class iter_impl // make sure BasicJsonType is basic_json or const basic_json static_assert(is_basic_json::type>::value, "iter_impl only accepts (const) basic_json"); - using diagnostics_t = detail::diagnostics_t; public: @@ -259,7 +257,7 @@ class iter_impl } case value_t::null: - JSON_THROW(invalid_iterator::create(214, "cannot get value", diagnostics_t(*m_object))); + JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object)); default: { @@ -268,7 +266,7 @@ class iter_impl return *m_object; } - JSON_THROW(invalid_iterator::create(214, "cannot get value", diagnostics_t(*m_object))); + JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object)); } } } @@ -302,7 +300,7 @@ class iter_impl return m_object; } - JSON_THROW(invalid_iterator::create(214, "cannot get value", diagnostics_t(*m_object))); + JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object)); } } } @@ -403,7 +401,7 @@ class iter_impl // if objects are not the same, the comparison is undefined if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object)) { - JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", diagnostics_t(*m_object))); + JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", *m_object)); } JSON_ASSERT(m_object != nullptr); @@ -440,7 +438,7 @@ class iter_impl // if objects are not the same, the comparison is undefined if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object)) { - JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", diagnostics_t(*m_object))); + JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", *m_object)); } JSON_ASSERT(m_object != nullptr); @@ -448,7 +446,7 @@ class iter_impl switch (m_object->m_type) { case value_t::object: - JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", diagnostics_t(*m_object))); + JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", *m_object)); case value_t::array: return (m_it.array_iterator < other.m_it.array_iterator); @@ -496,7 +494,7 @@ class iter_impl switch (m_object->m_type) { case value_t::object: - JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", diagnostics_t(*m_object))); + JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", *m_object)); case value_t::array: { @@ -567,7 +565,7 @@ class iter_impl switch (m_object->m_type) { case value_t::object: - JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", diagnostics_t(*m_object))); + JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", *m_object)); case value_t::array: return m_it.array_iterator - other.m_it.array_iterator; @@ -588,13 +586,13 @@ class iter_impl switch (m_object->m_type) { case value_t::object: - JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", diagnostics_t(*m_object))); + JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", *m_object)); 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", diagnostics_t(*m_object))); + JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object)); default: { @@ -603,7 +601,7 @@ class iter_impl return *m_object; } - JSON_THROW(invalid_iterator::create(214, "cannot get value", diagnostics_t(*m_object))); + JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object)); } } } @@ -621,7 +619,7 @@ class iter_impl return m_it.object_iterator->first; } - JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators", diagnostics_t(*m_object))); + JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators", *m_object)); } /*! diff --git a/include/nlohmann/detail/json_pointer.hpp b/include/nlohmann/detail/json_pointer.hpp index a241282f28..c924f7eb1e 100644 --- a/include/nlohmann/detail/json_pointer.hpp +++ b/include/nlohmann/detail/json_pointer.hpp @@ -8,7 +8,6 @@ #include // move #include // vector -#include #include #include #include @@ -23,8 +22,6 @@ class json_pointer NLOHMANN_BASIC_JSON_TPL_DECLARATION friend class basic_json; - using diagnostics_t = detail::diagnostics_t; - public: /*! @brief create JSON pointer @@ -447,7 +444,7 @@ class json_pointer single value; that is, with an empty list of reference tokens. */ default: - JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", diagnostics_t(j))); + JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", j)); } } @@ -519,7 +516,7 @@ class json_pointer } default: - JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", diagnostics_t(*ptr))); + JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr)); } } @@ -552,7 +549,7 @@ class json_pointer // "-" 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", diagnostics_t(*ptr))); + ") is out of range", *ptr)); } // note: at performs range check @@ -561,7 +558,7 @@ class json_pointer } default: - JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", diagnostics_t(*ptr))); + JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr)); } } @@ -599,7 +596,7 @@ class json_pointer if (JSON_HEDLEY_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", diagnostics_t(*ptr))); + JSON_THROW(detail::out_of_range::create(402, "array index '-' (" + std::to_string(ptr->m_value.array->size()) + ") is out of range", *ptr)); } // use unchecked array access @@ -608,7 +605,7 @@ class json_pointer } default: - JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", diagnostics_t(*ptr))); + JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr)); } } @@ -641,7 +638,7 @@ class json_pointer // "-" 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", diagnostics_t(*ptr))); + ") is out of range", *ptr)); } // note: at performs range check @@ -650,7 +647,7 @@ class json_pointer } default: - JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", diagnostics_t(*ptr))); + JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr)); } } @@ -878,7 +875,7 @@ class json_pointer { if (JSON_HEDLEY_UNLIKELY(!value.is_object())) { - JSON_THROW(detail::type_error::create(314, "only objects can be unflattened", diagnostics_t(value))); + JSON_THROW(detail::type_error::create(314, "only objects can be unflattened", value)); } BasicJsonType result; @@ -888,7 +885,7 @@ class json_pointer { if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive())) { - JSON_THROW(detail::type_error::create(315, "values in object must be primitive", diagnostics_t(element.second))); + JSON_THROW(detail::type_error::create(315, "values in object must be primitive", element.second)); } // assign value to reference pointed to by JSON pointer; Note that if diff --git a/include/nlohmann/detail/output/binary_writer.hpp b/include/nlohmann/detail/output/binary_writer.hpp index b8314402cc..27215f193e 100644 --- a/include/nlohmann/detail/output/binary_writer.hpp +++ b/include/nlohmann/detail/output/binary_writer.hpp @@ -8,7 +8,6 @@ #include // string #include // isnan, isinf -#include #include #include #include @@ -30,7 +29,6 @@ class binary_writer using string_t = typename BasicJsonType::string_t; using binary_t = typename BasicJsonType::binary_t; using number_float_t = typename BasicJsonType::number_float_t; - using diagnostics_t = detail::diagnostics_t; public: /*! @@ -59,7 +57,7 @@ class binary_writer default: { - JSON_THROW(type_error::create(317, "to serialize to BSON, top-level type must be object, but is " + std::string(j.type_name()), diagnostics_t(j)));; + JSON_THROW(type_error::create(317, "to serialize to BSON, top-level type must be object, but is " + std::string(j.type_name()), j));; } } } @@ -908,7 +906,7 @@ class binary_writer const auto it = name.find(static_cast(0)); if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos)) { - JSON_THROW(out_of_range::create(409, "BSON key cannot contain code point U+0000 (at byte " + std::to_string(it) + ")", diagnostics_t(j))); + JSON_THROW(out_of_range::create(409, "BSON key cannot contain code point U+0000 (at byte " + std::to_string(it) + ")", j)); } return /*id*/ 1ul + name.size() + /*zero-terminator*/1u; @@ -1032,7 +1030,7 @@ class binary_writer } else { - JSON_THROW(out_of_range::create(407, "integer number " + std::to_string(j.m_value.number_unsigned) + " cannot be represented by BSON as it does not fit int64", diagnostics_t(j))); + JSON_THROW(out_of_range::create(407, "integer number " + std::to_string(j.m_value.number_unsigned) + " cannot be represented by BSON as it does not fit int64", j)); } } diff --git a/include/nlohmann/json.hpp b/include/nlohmann/json.hpp index f424eec5f3..e21643b764 100644 --- a/include/nlohmann/json.hpp +++ b/include/nlohmann/json.hpp @@ -196,9 +196,6 @@ class basic_json /// workaround type for MSVC using basic_json_t = NLOHMANN_BASIC_JSON_TPL; - /// shortcut - using diagnostics_t = ::nlohmann::detail::diagnostics_t; - JSON_PRIVATE_UNLESS_TESTED: // convenience aliases for types residing in namespace detail; using lexer = ::nlohmann::detail::lexer_base; @@ -2791,7 +2788,7 @@ class basic_json return m_value.boolean; } - JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(type_name()), *this)); } /// get a pointer to the value (object) @@ -2912,7 +2909,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()), diagnostics_t(obj))); + JSON_THROW(type_error::create(303, "incompatible ReferenceType for get_ref, actual type is " + std::string(obj.type_name()), obj)); } public: @@ -3340,7 +3337,7 @@ class basic_json { if (!is_binary()) { - JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(type_name()), *this)); } return *get_ptr(); @@ -3351,7 +3348,7 @@ class basic_json { if (!is_binary()) { - JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(type_name()), *this)); } return *get_ptr(); @@ -3406,12 +3403,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", diagnostics_t(*this))); + JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", *this)); } } else { - JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this)); } } @@ -3453,12 +3450,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", diagnostics_t(*this))); + JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", *this)); } } else { - JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this)); } } @@ -3504,12 +3501,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", diagnostics_t(*this))); + JSON_THROW(out_of_range::create(403, "key '" + key + "' not found", *this)); } } else { - JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this)); } } @@ -3555,12 +3552,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", diagnostics_t(*this))); + JSON_THROW(out_of_range::create(403, "key '" + key + "' not found", *this)); } } else { - JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this)); } } @@ -3620,7 +3617,7 @@ class basic_json return m_value.array->operator[](idx); } - JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name()), *this)); } /*! @@ -3650,7 +3647,7 @@ class basic_json return m_value.array->operator[](idx); } - JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name()), *this)); } /*! @@ -3696,7 +3693,7 @@ class basic_json return set_parent(m_value.object->operator[](key)); } - JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this)); } /*! @@ -3738,7 +3735,7 @@ class basic_json return m_value.object->find(key)->second; } - JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this)); } /*! @@ -3786,7 +3783,7 @@ class basic_json return set_parent(m_value.object->operator[](key)); } - JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this)); } /*! @@ -3830,7 +3827,7 @@ class basic_json return m_value.object->find(key)->second; } - JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this)); } /*! @@ -3902,7 +3899,7 @@ class basic_json return default_value; } - JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name()), *this)); } /*! @@ -3975,7 +3972,7 @@ class basic_json } } - JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name()), *this)); } /*! @@ -4129,7 +4126,7 @@ class basic_json // make sure iterator fits the current value if (JSON_HEDLEY_UNLIKELY(this != pos.m_object)) { - JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", diagnostics_t(*this))); + JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this)); } IteratorType result = end(); @@ -4145,7 +4142,7 @@ class basic_json { if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin())) { - JSON_THROW(invalid_iterator::create(205, "iterator out of range", diagnostics_t(*this))); + JSON_THROW(invalid_iterator::create(205, "iterator out of range", *this)); } if (is_string()) @@ -4181,7 +4178,7 @@ class basic_json } default: - JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this)); } return result; @@ -4242,7 +4239,7 @@ class basic_json // make sure iterator fits the current value if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object)) { - JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value", diagnostics_t(*this))); + JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value", *this)); } IteratorType result = end(); @@ -4259,7 +4256,7 @@ class basic_json if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin() || !last.m_it.primitive_iterator.is_end())) { - JSON_THROW(invalid_iterator::create(204, "iterators out of range", diagnostics_t(*this))); + JSON_THROW(invalid_iterator::create(204, "iterators out of range", *this)); } if (is_string()) @@ -4297,7 +4294,7 @@ class basic_json } default: - JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this)); } return result; @@ -4340,7 +4337,7 @@ class basic_json return m_value.object->erase(key); } - JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this)); } /*! @@ -4374,14 +4371,14 @@ class basic_json { if (JSON_HEDLEY_UNLIKELY(idx >= size())) { - JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", diagnostics_t(*this))); + JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", *this)); } 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()), diagnostics_t(*this))); + JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this)); } } @@ -5326,7 +5323,7 @@ class basic_json // push_back only works for null objects or arrays if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array()))) { - JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()), *this)); } // transform null object into an array @@ -5362,7 +5359,7 @@ class basic_json // push_back only works for null objects or arrays if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array()))) { - JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()), *this)); } // transform null object into an array @@ -5413,7 +5410,7 @@ class basic_json // push_back only works for null objects or objects if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object()))) { - JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()), *this)); } // transform null object into an object @@ -5517,7 +5514,7 @@ class basic_json // emplace_back only works for null objects or arrays if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array()))) { - JSON_THROW(type_error::create(311, "cannot use emplace_back() with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(311, "cannot use emplace_back() with " + std::string(type_name()), *this)); } // transform null object into an array @@ -5570,7 +5567,7 @@ class basic_json // emplace only works for null objects or arrays if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object()))) { - JSON_THROW(type_error::create(311, "cannot use emplace() with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(311, "cannot use emplace() with " + std::string(type_name()), *this)); } // transform null object into an object @@ -5643,14 +5640,14 @@ class basic_json // check if iterator pos fits to this JSON value if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) { - JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", diagnostics_t(*this))); + JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this)); } // insert to array and return iterator return set_parents(insert_iterator(pos, val), static_cast(1)); } - JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this)); } /*! @@ -5694,14 +5691,14 @@ class basic_json // check if iterator pos fits to this JSON value if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) { - JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", diagnostics_t(*this))); + JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this)); } // insert to array and return iterator return set_parents(insert_iterator(pos, cnt, val), static_cast(cnt)); } - JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this)); } /*! @@ -5739,24 +5736,24 @@ class basic_json // insert only works for arrays if (JSON_HEDLEY_UNLIKELY(!is_array())) { - JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this)); } // check if iterator pos fits to this JSON value if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) { - JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", diagnostics_t(*this))); + JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this)); } // check if range iterators belong to the same JSON object if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) { - JSON_THROW(invalid_iterator::create(210, "iterators do not fit", diagnostics_t(*this))); + JSON_THROW(invalid_iterator::create(210, "iterators do not fit", *this)); } if (JSON_HEDLEY_UNLIKELY(first.m_object == this)) { - JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container", diagnostics_t(*this))); + JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container", *this)); } // insert to array and return iterator @@ -5792,13 +5789,13 @@ class basic_json // insert only works for arrays if (JSON_HEDLEY_UNLIKELY(!is_array())) { - JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this)); } // check if iterator pos fits to this JSON value if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) { - JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", diagnostics_t(*this))); + JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this)); } // insert to array and return iterator @@ -5833,19 +5830,19 @@ class basic_json // insert only works for objects if (JSON_HEDLEY_UNLIKELY(!is_object())) { - JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this)); } // check if range iterators belong to the same JSON object if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) { - JSON_THROW(invalid_iterator::create(210, "iterators do not fit", diagnostics_t(*this))); + JSON_THROW(invalid_iterator::create(210, "iterators do not fit", *this)); } // passed iterators must belong to objects if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object())) { - JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", diagnostics_t(*this))); + JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", *this)); } m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator); @@ -5882,11 +5879,11 @@ class basic_json if (JSON_HEDLEY_UNLIKELY(!is_object())) { - JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name()), *this)); } if (JSON_HEDLEY_UNLIKELY(!j.is_object())) { - JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(j.type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(j.type_name()), *this)); } for (auto it = j.cbegin(); it != j.cend(); ++it) @@ -5933,20 +5930,20 @@ class basic_json if (JSON_HEDLEY_UNLIKELY(!is_object())) { - JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name()), *this)); } // check if range iterators belong to the same JSON object if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) { - JSON_THROW(invalid_iterator::create(210, "iterators do not fit", diagnostics_t(*this))); + JSON_THROW(invalid_iterator::create(210, "iterators do not fit", *this)); } // passed iterators must belong to objects if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object() || !last.m_object->is_object())) { - JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", diagnostics_t(*this))); + JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", *this)); } for (auto it = first; it != last; ++it) @@ -6044,7 +6041,7 @@ class basic_json } else { - JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this)); } } @@ -6077,7 +6074,7 @@ class basic_json } else { - JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this)); } } @@ -6110,7 +6107,7 @@ class basic_json } else { - JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this)); } } @@ -6143,7 +6140,7 @@ class basic_json } else { - JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this)); } } @@ -6157,7 +6154,7 @@ class basic_json } else { - JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this)); } } @@ -8366,7 +8363,7 @@ class basic_json if (JSON_HEDLEY_UNLIKELY(idx > parent.size())) { // avoid undefined behavior - JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", diagnostics_t(parent))); + JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", parent)); } // default case: insert add offset @@ -8400,7 +8397,7 @@ class basic_json } else { - JSON_THROW(out_of_range::create(403, "key '" + last_path + "' not found", diagnostics_t(*this))); + JSON_THROW(out_of_range::create(403, "key '" + last_path + "' not found", *this)); } } else if (parent.is_array()) @@ -8413,7 +8410,7 @@ class basic_json // type check: top level value must be an array if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array())) { - JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", diagnostics_t(json_patch))); + JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", json_patch)); } // iterate and apply the operations @@ -8433,13 +8430,13 @@ class basic_json // check if desired value is present if (JSON_HEDLEY_UNLIKELY(it == val.m_value.object->end())) { - JSON_THROW(parse_error::create(105, 0, error_msg + " must have member '" + member + "'", diagnostics_t(val))); + JSON_THROW(parse_error::create(105, 0, error_msg + " must have member '" + member + "'", val)); } // check if result is of type string if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string())) { - JSON_THROW(parse_error::create(105, 0, error_msg + " must have string member '" + member + "'", diagnostics_t(val))); + JSON_THROW(parse_error::create(105, 0, error_msg + " must have string member '" + member + "'", val)); } // no error: return value @@ -8449,7 +8446,7 @@ class basic_json // type check: every element of the array must be an object if (JSON_HEDLEY_UNLIKELY(!val.is_object())) { - JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", diagnostics_t(val))); + JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", val)); } // collect mandatory members @@ -8527,7 +8524,7 @@ class basic_json // throw an exception if test fails if (JSON_HEDLEY_UNLIKELY(!success)) { - JSON_THROW(other_error::create(501, "unsuccessful: " + val.dump(), diagnostics_t(val))); + JSON_THROW(other_error::create(501, "unsuccessful: " + val.dump(), val)); } break; @@ -8537,7 +8534,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", diagnostics_t(val))); + JSON_THROW(parse_error::create(105, 0, "operation value '" + op + "' is invalid", val)); } } } diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index edd0587ffa..004c70c052 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -3679,8 +3679,6 @@ class other_error : public exception } // namespace detail } // namespace nlohmann -// #include - // #include // #include @@ -3699,7 +3697,7 @@ void from_json(const BasicJsonType& j, typename std::nullptr_t& n) { if (JSON_HEDLEY_UNLIKELY(!j.is_null())) { - JSON_THROW(type_error::create(302, "type must be null, but is " + std::string(j.type_name()), detail::diagnostics_t(j))); + JSON_THROW(type_error::create(302, "type must be null, but is " + std::string(j.type_name()), j)); } n = nullptr; } @@ -3730,7 +3728,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()), detail::diagnostics_t(j))); + JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()), j)); } } @@ -3739,7 +3737,7 @@ void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b) { if (JSON_HEDLEY_UNLIKELY(!j.is_boolean())) { - JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(j.type_name()), detail::diagnostics_t(j))); + JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(j.type_name()), j)); } b = *j.template get_ptr(); } @@ -3749,7 +3747,7 @@ void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s) { if (JSON_HEDLEY_UNLIKELY(!j.is_string())) { - JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), detail::diagnostics_t(j))); + JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), j)); } s = *j.template get_ptr(); } @@ -3765,7 +3763,7 @@ void from_json(const BasicJsonType& j, ConstructibleStringType& s) { if (JSON_HEDLEY_UNLIKELY(!j.is_string())) { - JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), detail::diagnostics_t(j))); + JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()), j)); } s = *j.template get_ptr(); @@ -3805,7 +3803,7 @@ void from_json(const BasicJsonType& j, std::forward_list& l) { if (JSON_HEDLEY_UNLIKELY(!j.is_array())) { - JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), detail::diagnostics_t(j))); + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j)); } l.clear(); std::transform(j.rbegin(), j.rend(), @@ -3822,7 +3820,7 @@ void from_json(const BasicJsonType& j, std::valarray& l) { if (JSON_HEDLEY_UNLIKELY(!j.is_array())) { - JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), detail::diagnostics_t(j))); + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j)); } l.resize(j.size()); std::transform(j.begin(), j.end(), std::begin(l), @@ -3913,7 +3911,7 @@ void()) { if (JSON_HEDLEY_UNLIKELY(!j.is_array())) { - JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), detail::diagnostics_t(j))); + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j)); } from_json_array_impl(j, arr, priority_tag<3> {}); @@ -3924,7 +3922,7 @@ void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin) { if (JSON_HEDLEY_UNLIKELY(!j.is_binary())) { - JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(j.type_name()), detail::diagnostics_t(j))); + JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(j.type_name()), j)); } bin = *j.template get_ptr(); @@ -3936,7 +3934,7 @@ void from_json(const BasicJsonType& j, ConstructibleObjectType& obj) { if (JSON_HEDLEY_UNLIKELY(!j.is_object())) { - JSON_THROW(type_error::create(302, "type must be object, but is " + std::string(j.type_name()), detail::diagnostics_t(j))); + JSON_THROW(type_error::create(302, "type must be object, but is " + std::string(j.type_name()), j)); } ConstructibleObjectType ret; @@ -3990,7 +3988,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()), detail::diagnostics_t(j))); + JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()), j)); } } @@ -4019,14 +4017,14 @@ void from_json(const BasicJsonType& j, std::map& { if (JSON_HEDLEY_UNLIKELY(!j.is_array())) { - JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), detail::diagnostics_t(j))); + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j)); } m.clear(); for (const auto& p : j) { if (JSON_HEDLEY_UNLIKELY(!p.is_array())) { - JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name()), detail::diagnostics_t(j))); + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name()), j)); } m.emplace(p.at(0).template get(), p.at(1).template get()); } @@ -4039,14 +4037,14 @@ void from_json(const BasicJsonType& j, std::unordered_map(j))); + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()), j)); } m.clear(); for (const auto& p : j) { if (JSON_HEDLEY_UNLIKELY(!p.is_array())) { - JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name()), detail::diagnostics_t(j))); + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name()), j)); } m.emplace(p.at(0).template get(), p.at(1).template get()); } @@ -5490,8 +5488,6 @@ class span_input_adapter #include // move #include // vector -// #include - // #include // #include @@ -5643,7 +5639,6 @@ class json_sax_dom_parser using number_float_t = typename BasicJsonType::number_float_t; using string_t = typename BasicJsonType::string_t; using binary_t = typename BasicJsonType::binary_t; - using diagnostics_t = detail::diagnostics_t; /*! @param[in, out] r reference to a JSON value that is manipulated while @@ -5709,7 +5704,7 @@ class json_sax_dom_parser if (JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size())) { - JSON_THROW(out_of_range::create(408, "excessive object size: " + std::to_string(len), diagnostics_t(*ref_stack.back()))); + JSON_THROW(out_of_range::create(408, "excessive object size: " + std::to_string(len), *ref_stack.back())); } return true; @@ -5735,7 +5730,7 @@ class json_sax_dom_parser if (JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size())) { - JSON_THROW(out_of_range::create(408, "excessive array size: " + std::to_string(len), diagnostics_t(*ref_stack.back()))); + JSON_THROW(out_of_range::create(408, "excessive array size: " + std::to_string(len), *ref_stack.back())); } return true; @@ -5820,7 +5815,6 @@ class json_sax_dom_callback_parser using binary_t = typename BasicJsonType::binary_t; using parser_callback_t = typename BasicJsonType::parser_callback_t; using parse_event_t = typename BasicJsonType::parse_event_t; - using diagnostics_t = detail::diagnostics_t; json_sax_dom_callback_parser(BasicJsonType& r, const parser_callback_t cb, @@ -5891,7 +5885,7 @@ class json_sax_dom_callback_parser // check object limit if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size())) { - JSON_THROW(out_of_range::create(408, "excessive object size: " + std::to_string(len), diagnostics_t(*ref_stack.back()))); + JSON_THROW(out_of_range::create(408, "excessive object size: " + std::to_string(len), *ref_stack.back())); } return true; @@ -5961,7 +5955,7 @@ class json_sax_dom_callback_parser // check array limit if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size())) { - JSON_THROW(out_of_range::create(408, "excessive array size: " + std::to_string(len), diagnostics_t(*ref_stack.back()))); + JSON_THROW(out_of_range::create(408, "excessive array size: " + std::to_string(len), *ref_stack.back())); } return true; @@ -11093,8 +11087,6 @@ template struct internal_iterator #include // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next #include // conditional, is_const, remove_const -// #include - // #include // #include @@ -11150,7 +11142,6 @@ class iter_impl // make sure BasicJsonType is basic_json or const basic_json static_assert(is_basic_json::type>::value, "iter_impl only accepts (const) basic_json"); - using diagnostics_t = detail::diagnostics_t; public: @@ -11357,7 +11348,7 @@ class iter_impl } case value_t::null: - JSON_THROW(invalid_iterator::create(214, "cannot get value", diagnostics_t(*m_object))); + JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object)); default: { @@ -11366,7 +11357,7 @@ class iter_impl return *m_object; } - JSON_THROW(invalid_iterator::create(214, "cannot get value", diagnostics_t(*m_object))); + JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object)); } } } @@ -11400,7 +11391,7 @@ class iter_impl return m_object; } - JSON_THROW(invalid_iterator::create(214, "cannot get value", diagnostics_t(*m_object))); + JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object)); } } } @@ -11501,7 +11492,7 @@ class iter_impl // if objects are not the same, the comparison is undefined if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object)) { - JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", diagnostics_t(*m_object))); + JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", *m_object)); } JSON_ASSERT(m_object != nullptr); @@ -11538,7 +11529,7 @@ class iter_impl // if objects are not the same, the comparison is undefined if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object)) { - JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", diagnostics_t(*m_object))); + JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", *m_object)); } JSON_ASSERT(m_object != nullptr); @@ -11546,7 +11537,7 @@ class iter_impl switch (m_object->m_type) { case value_t::object: - JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", diagnostics_t(*m_object))); + JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", *m_object)); case value_t::array: return (m_it.array_iterator < other.m_it.array_iterator); @@ -11594,7 +11585,7 @@ class iter_impl switch (m_object->m_type) { case value_t::object: - JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", diagnostics_t(*m_object))); + JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", *m_object)); case value_t::array: { @@ -11665,7 +11656,7 @@ class iter_impl switch (m_object->m_type) { case value_t::object: - JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", diagnostics_t(*m_object))); + JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", *m_object)); case value_t::array: return m_it.array_iterator - other.m_it.array_iterator; @@ -11686,13 +11677,13 @@ class iter_impl switch (m_object->m_type) { case value_t::object: - JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", diagnostics_t(*m_object))); + JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", *m_object)); 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", diagnostics_t(*m_object))); + JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object)); default: { @@ -11701,7 +11692,7 @@ class iter_impl return *m_object; } - JSON_THROW(invalid_iterator::create(214, "cannot get value", diagnostics_t(*m_object))); + JSON_THROW(invalid_iterator::create(214, "cannot get value", *m_object)); } } } @@ -11719,7 +11710,7 @@ class iter_impl return m_it.object_iterator->first; } - JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators", diagnostics_t(*m_object))); + JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators", *m_object)); } /*! @@ -11876,8 +11867,6 @@ class json_reverse_iterator : public std::reverse_iterator #include // move #include // vector -// #include - // #include // #include @@ -11896,8 +11885,6 @@ class json_pointer NLOHMANN_BASIC_JSON_TPL_DECLARATION friend class basic_json; - using diagnostics_t = detail::diagnostics_t; - public: /*! @brief create JSON pointer @@ -12320,7 +12307,7 @@ class json_pointer single value; that is, with an empty list of reference tokens. */ default: - JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", diagnostics_t(j))); + JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", j)); } } @@ -12392,7 +12379,7 @@ class json_pointer } default: - JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", diagnostics_t(*ptr))); + JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr)); } } @@ -12425,7 +12412,7 @@ class json_pointer // "-" 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", diagnostics_t(*ptr))); + ") is out of range", *ptr)); } // note: at performs range check @@ -12434,7 +12421,7 @@ class json_pointer } default: - JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", diagnostics_t(*ptr))); + JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr)); } } @@ -12472,7 +12459,7 @@ class json_pointer if (JSON_HEDLEY_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", diagnostics_t(*ptr))); + JSON_THROW(detail::out_of_range::create(402, "array index '-' (" + std::to_string(ptr->m_value.array->size()) + ") is out of range", *ptr)); } // use unchecked array access @@ -12481,7 +12468,7 @@ class json_pointer } default: - JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", diagnostics_t(*ptr))); + JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr)); } } @@ -12514,7 +12501,7 @@ class json_pointer // "-" 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", diagnostics_t(*ptr))); + ") is out of range", *ptr)); } // note: at performs range check @@ -12523,7 +12510,7 @@ class json_pointer } default: - JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", diagnostics_t(*ptr))); + JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'", *ptr)); } } @@ -12751,7 +12738,7 @@ class json_pointer { if (JSON_HEDLEY_UNLIKELY(!value.is_object())) { - JSON_THROW(detail::type_error::create(314, "only objects can be unflattened", diagnostics_t(value))); + JSON_THROW(detail::type_error::create(314, "only objects can be unflattened", value)); } BasicJsonType result; @@ -12761,7 +12748,7 @@ class json_pointer { if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive())) { - JSON_THROW(detail::type_error::create(315, "values in object must be primitive", diagnostics_t(element.second))); + JSON_THROW(detail::type_error::create(315, "values in object must be primitive", element.second)); } // assign value to reference pointed to by JSON pointer; Note that if @@ -12901,8 +12888,6 @@ class json_ref #include // string #include // isnan, isinf -// #include - // #include // #include @@ -13051,7 +13036,6 @@ class binary_writer using string_t = typename BasicJsonType::string_t; using binary_t = typename BasicJsonType::binary_t; using number_float_t = typename BasicJsonType::number_float_t; - using diagnostics_t = detail::diagnostics_t; public: /*! @@ -13080,7 +13064,7 @@ class binary_writer default: { - JSON_THROW(type_error::create(317, "to serialize to BSON, top-level type must be object, but is " + std::string(j.type_name()), diagnostics_t(j)));; + JSON_THROW(type_error::create(317, "to serialize to BSON, top-level type must be object, but is " + std::string(j.type_name()), j));; } } } @@ -13929,7 +13913,7 @@ class binary_writer const auto it = name.find(static_cast(0)); if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos)) { - JSON_THROW(out_of_range::create(409, "BSON key cannot contain code point U+0000 (at byte " + std::to_string(it) + ")", diagnostics_t(j))); + JSON_THROW(out_of_range::create(409, "BSON key cannot contain code point U+0000 (at byte " + std::to_string(it) + ")", j)); } return /*id*/ 1ul + name.size() + /*zero-terminator*/1u; @@ -14053,7 +14037,7 @@ class binary_writer } else { - JSON_THROW(out_of_range::create(407, "integer number " + std::to_string(j.m_value.number_unsigned) + " cannot be represented by BSON as it does not fit int64", diagnostics_t(j))); + JSON_THROW(out_of_range::create(407, "integer number " + std::to_string(j.m_value.number_unsigned) + " cannot be represented by BSON as it does not fit int64", j)); } } @@ -16998,9 +16982,6 @@ class basic_json /// workaround type for MSVC using basic_json_t = NLOHMANN_BASIC_JSON_TPL; - /// shortcut - using diagnostics_t = ::nlohmann::detail::diagnostics_t; - JSON_PRIVATE_UNLESS_TESTED: // convenience aliases for types residing in namespace detail; using lexer = ::nlohmann::detail::lexer_base; @@ -19593,7 +19574,7 @@ class basic_json return m_value.boolean; } - JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(type_name()), *this)); } /// get a pointer to the value (object) @@ -19714,7 +19695,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()), diagnostics_t(obj))); + JSON_THROW(type_error::create(303, "incompatible ReferenceType for get_ref, actual type is " + std::string(obj.type_name()), obj)); } public: @@ -20142,7 +20123,7 @@ class basic_json { if (!is_binary()) { - JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(type_name()), *this)); } return *get_ptr(); @@ -20153,7 +20134,7 @@ class basic_json { if (!is_binary()) { - JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(type_name()), *this)); } return *get_ptr(); @@ -20208,12 +20189,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", diagnostics_t(*this))); + JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", *this)); } } else { - JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this)); } } @@ -20255,12 +20236,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", diagnostics_t(*this))); + JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", *this)); } } else { - JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this)); } } @@ -20306,12 +20287,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", diagnostics_t(*this))); + JSON_THROW(out_of_range::create(403, "key '" + key + "' not found", *this)); } } else { - JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this)); } } @@ -20357,12 +20338,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", diagnostics_t(*this))); + JSON_THROW(out_of_range::create(403, "key '" + key + "' not found", *this)); } } else { - JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()), *this)); } } @@ -20422,7 +20403,7 @@ class basic_json return m_value.array->operator[](idx); } - JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name()), *this)); } /*! @@ -20452,7 +20433,7 @@ class basic_json return m_value.array->operator[](idx); } - JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name()), *this)); } /*! @@ -20498,7 +20479,7 @@ class basic_json return set_parent(m_value.object->operator[](key)); } - JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this)); } /*! @@ -20540,7 +20521,7 @@ class basic_json return m_value.object->find(key)->second; } - JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this)); } /*! @@ -20588,7 +20569,7 @@ class basic_json return set_parent(m_value.object->operator[](key)); } - JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this)); } /*! @@ -20632,7 +20613,7 @@ class basic_json return m_value.object->find(key)->second; } - JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()), *this)); } /*! @@ -20704,7 +20685,7 @@ class basic_json return default_value; } - JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name()), *this)); } /*! @@ -20777,7 +20758,7 @@ class basic_json } } - JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name()), *this)); } /*! @@ -20931,7 +20912,7 @@ class basic_json // make sure iterator fits the current value if (JSON_HEDLEY_UNLIKELY(this != pos.m_object)) { - JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", diagnostics_t(*this))); + JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this)); } IteratorType result = end(); @@ -20947,7 +20928,7 @@ class basic_json { if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin())) { - JSON_THROW(invalid_iterator::create(205, "iterator out of range", diagnostics_t(*this))); + JSON_THROW(invalid_iterator::create(205, "iterator out of range", *this)); } if (is_string()) @@ -20983,7 +20964,7 @@ class basic_json } default: - JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this)); } return result; @@ -21044,7 +21025,7 @@ class basic_json // make sure iterator fits the current value if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object)) { - JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value", diagnostics_t(*this))); + JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value", *this)); } IteratorType result = end(); @@ -21061,7 +21042,7 @@ class basic_json if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin() || !last.m_it.primitive_iterator.is_end())) { - JSON_THROW(invalid_iterator::create(204, "iterators out of range", diagnostics_t(*this))); + JSON_THROW(invalid_iterator::create(204, "iterators out of range", *this)); } if (is_string()) @@ -21099,7 +21080,7 @@ class basic_json } default: - JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this)); } return result; @@ -21142,7 +21123,7 @@ class basic_json return m_value.object->erase(key); } - JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this)); } /*! @@ -21176,14 +21157,14 @@ class basic_json { if (JSON_HEDLEY_UNLIKELY(idx >= size())) { - JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", diagnostics_t(*this))); + JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", *this)); } 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()), diagnostics_t(*this))); + JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()), *this)); } } @@ -22128,7 +22109,7 @@ class basic_json // push_back only works for null objects or arrays if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array()))) { - JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()), *this)); } // transform null object into an array @@ -22164,7 +22145,7 @@ class basic_json // push_back only works for null objects or arrays if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array()))) { - JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()), *this)); } // transform null object into an array @@ -22215,7 +22196,7 @@ class basic_json // push_back only works for null objects or objects if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object()))) { - JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()), *this)); } // transform null object into an object @@ -22319,7 +22300,7 @@ class basic_json // emplace_back only works for null objects or arrays if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array()))) { - JSON_THROW(type_error::create(311, "cannot use emplace_back() with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(311, "cannot use emplace_back() with " + std::string(type_name()), *this)); } // transform null object into an array @@ -22372,7 +22353,7 @@ class basic_json // emplace only works for null objects or arrays if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object()))) { - JSON_THROW(type_error::create(311, "cannot use emplace() with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(311, "cannot use emplace() with " + std::string(type_name()), *this)); } // transform null object into an object @@ -22445,14 +22426,14 @@ class basic_json // check if iterator pos fits to this JSON value if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) { - JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", diagnostics_t(*this))); + JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this)); } // insert to array and return iterator return set_parents(insert_iterator(pos, val), static_cast(1)); } - JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this)); } /*! @@ -22496,14 +22477,14 @@ class basic_json // check if iterator pos fits to this JSON value if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) { - JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", diagnostics_t(*this))); + JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this)); } // insert to array and return iterator return set_parents(insert_iterator(pos, cnt, val), static_cast(cnt)); } - JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this)); } /*! @@ -22541,24 +22522,24 @@ class basic_json // insert only works for arrays if (JSON_HEDLEY_UNLIKELY(!is_array())) { - JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this)); } // check if iterator pos fits to this JSON value if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) { - JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", diagnostics_t(*this))); + JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this)); } // check if range iterators belong to the same JSON object if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) { - JSON_THROW(invalid_iterator::create(210, "iterators do not fit", diagnostics_t(*this))); + JSON_THROW(invalid_iterator::create(210, "iterators do not fit", *this)); } if (JSON_HEDLEY_UNLIKELY(first.m_object == this)) { - JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container", diagnostics_t(*this))); + JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container", *this)); } // insert to array and return iterator @@ -22594,13 +22575,13 @@ class basic_json // insert only works for arrays if (JSON_HEDLEY_UNLIKELY(!is_array())) { - JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this)); } // check if iterator pos fits to this JSON value if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) { - JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", diagnostics_t(*this))); + JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", *this)); } // insert to array and return iterator @@ -22635,19 +22616,19 @@ class basic_json // insert only works for objects if (JSON_HEDLEY_UNLIKELY(!is_object())) { - JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()), *this)); } // check if range iterators belong to the same JSON object if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) { - JSON_THROW(invalid_iterator::create(210, "iterators do not fit", diagnostics_t(*this))); + JSON_THROW(invalid_iterator::create(210, "iterators do not fit", *this)); } // passed iterators must belong to objects if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object())) { - JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", diagnostics_t(*this))); + JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", *this)); } m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator); @@ -22684,11 +22665,11 @@ class basic_json if (JSON_HEDLEY_UNLIKELY(!is_object())) { - JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name()), *this)); } if (JSON_HEDLEY_UNLIKELY(!j.is_object())) { - JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(j.type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(j.type_name()), *this)); } for (auto it = j.cbegin(); it != j.cend(); ++it) @@ -22735,20 +22716,20 @@ class basic_json if (JSON_HEDLEY_UNLIKELY(!is_object())) { - JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name()), *this)); } // check if range iterators belong to the same JSON object if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) { - JSON_THROW(invalid_iterator::create(210, "iterators do not fit", diagnostics_t(*this))); + JSON_THROW(invalid_iterator::create(210, "iterators do not fit", *this)); } // passed iterators must belong to objects if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object() || !last.m_object->is_object())) { - JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", diagnostics_t(*this))); + JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", *this)); } for (auto it = first; it != last; ++it) @@ -22846,7 +22827,7 @@ class basic_json } else { - JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this)); } } @@ -22879,7 +22860,7 @@ class basic_json } else { - JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this)); } } @@ -22912,7 +22893,7 @@ class basic_json } else { - JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this)); } } @@ -22945,7 +22926,7 @@ class basic_json } else { - JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this)); } } @@ -22959,7 +22940,7 @@ class basic_json } else { - JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), diagnostics_t(*this))); + JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()), *this)); } } @@ -25168,7 +25149,7 @@ class basic_json if (JSON_HEDLEY_UNLIKELY(idx > parent.size())) { // avoid undefined behavior - JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", diagnostics_t(parent))); + JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range", parent)); } // default case: insert add offset @@ -25202,7 +25183,7 @@ class basic_json } else { - JSON_THROW(out_of_range::create(403, "key '" + last_path + "' not found", diagnostics_t(*this))); + JSON_THROW(out_of_range::create(403, "key '" + last_path + "' not found", *this)); } } else if (parent.is_array()) @@ -25215,7 +25196,7 @@ class basic_json // type check: top level value must be an array if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array())) { - JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", diagnostics_t(json_patch))); + JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", json_patch)); } // iterate and apply the operations @@ -25235,13 +25216,13 @@ class basic_json // check if desired value is present if (JSON_HEDLEY_UNLIKELY(it == val.m_value.object->end())) { - JSON_THROW(parse_error::create(105, 0, error_msg + " must have member '" + member + "'", diagnostics_t(val))); + JSON_THROW(parse_error::create(105, 0, error_msg + " must have member '" + member + "'", val)); } // check if result is of type string if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string())) { - JSON_THROW(parse_error::create(105, 0, error_msg + " must have string member '" + member + "'", diagnostics_t(val))); + JSON_THROW(parse_error::create(105, 0, error_msg + " must have string member '" + member + "'", val)); } // no error: return value @@ -25251,7 +25232,7 @@ class basic_json // type check: every element of the array must be an object if (JSON_HEDLEY_UNLIKELY(!val.is_object())) { - JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", diagnostics_t(val))); + JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", val)); } // collect mandatory members @@ -25329,7 +25310,7 @@ class basic_json // throw an exception if test fails if (JSON_HEDLEY_UNLIKELY(!success)) { - JSON_THROW(other_error::create(501, "unsuccessful: " + val.dump(), diagnostics_t(val))); + JSON_THROW(other_error::create(501, "unsuccessful: " + val.dump(), val)); } break; @@ -25339,7 +25320,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", diagnostics_t(val))); + JSON_THROW(parse_error::create(105, 0, "operation value '" + op + "' is invalid", val)); } } }