Merge branch 'develop' into feature/userdefined_exceptions
diff --git a/README.md b/README.md index c0bb61b..6b6b6f9 100644 --- a/README.md +++ b/README.md
@@ -486,6 +486,7 @@ - [Mário Feroldi](https://github.com/thelostt) fixed a small typo. - [duncanwerner](https://github.com/duncanwerner) found a really embarrassing performance regression in the 2.0.0 release. - [Damien](https://github.com/dtoma) fixed one of the last conversion warnings. +- [Muri Nicanor](https://github.com/murinicanor) made the Makefile more portable by choosing the correct version of sed. Thanks a lot for helping out! @@ -505,7 +506,7 @@ $ ./json_unit "*" =============================================================================== -All tests passed (8905012 assertions in 32 test cases) +All tests passed (8905087 assertions in 32 test cases) ``` For more information, have a look at the file [.travis.yml](https://github.com/nlohmann/json/blob/master/.travis.yml).
diff --git a/doc/examples/is_number_signed.cpp b/doc/examples/is_number_signed.cpp new file mode 100644 index 0000000..dd0214f --- /dev/null +++ b/doc/examples/is_number_signed.cpp
@@ -0,0 +1,27 @@ +#include <json.hpp> + +using json = nlohmann::json; + +int main() +{ + // create JSON values + json j_null; + json j_boolean = true; + json j_number_integer = 17; + json j_number_unsigned_integer = 12345678987654321u; + json j_number_float = 23.42; + json j_object = {{"one", 1}, {"two", 2}}; + json j_array = {1, 2, 4, 8, 16}; + json j_string = "Hello, world"; + + // call is_number_signed() + std::cout << std::boolalpha; + std::cout << j_null.is_number_signed() << '\n'; + std::cout << j_boolean.is_number_signed() << '\n'; + std::cout << j_number_integer.is_number_signed() << '\n'; + std::cout << j_number_unsigned_integer.is_number_signed() << '\n'; + std::cout << j_number_float.is_number_signed() << '\n'; + std::cout << j_object.is_number_signed() << '\n'; + std::cout << j_array.is_number_signed() << '\n'; + std::cout << j_string.is_number_signed() << '\n'; +}
diff --git a/doc/examples/is_number_signed.link b/doc/examples/is_number_signed.link new file mode 100644 index 0000000..920b7b0 --- /dev/null +++ b/doc/examples/is_number_signed.link
@@ -0,0 +1 @@ +<a target="_blank" href="http://melpon.org/wandbox/permlink/i2UvvUEA0oZ3JeQZ"><b>online</b></a> \ No newline at end of file
diff --git a/doc/examples/is_number_signed.output b/doc/examples/is_number_signed.output new file mode 100644 index 0000000..d126b27 --- /dev/null +++ b/doc/examples/is_number_signed.output
@@ -0,0 +1,8 @@ +false +false +true +false +false +false +false +false
diff --git a/src/json.hpp b/src/json.hpp index 878fb89..a95717c 100644 --- a/src/json.hpp +++ b/src/json.hpp
@@ -272,6 +272,100 @@ /// @} + public: + ///////////////////////////// + // user-defined exceptions // + ///////////////////////////// + + /// @name exception types + /// Classes for exceptions used by the library functions. + /// @{ + + /*! + @brief a user-defined exception class + + To implement user-defined exceptions for the library, this class is used + as subclass for different exception types. Compared to `std::exception`, + the class also contains an error code to better reference and document + exceptions. + + error code | exception type | message | description + ---------- | -------------- | ------- | ----------- + 101 | @ref invalid_iterator | "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. + 102 | @ref invalid_iterator | "iterators do not fit current value" | Either iterator passed to function @ref erase(InteratorType first, InteratorType 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. + 103 | @ref invalid_iterator | "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. + 104 | @ref invalid_iterator | "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. + 105 | @ref invalid_iterator | "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. + 106 | @ref invalid_iterator | "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. + 107 | @ref invalid_iterator | "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. + 108 | @ref invalid_iterator | "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. + 109 | @ref invalid_iterator | "cannot use offsets with object iterators" | The offset operators (+, -, +=, -=) cannot be used on iterators belonging to a JSON object, because JSON objects are unordered. + 110 | @ref invalid_iterator | "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. + 111 | @ref invalid_iterator | "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. + 112 | @ref invalid_iterator | "cannot compare iterators of different containers" | When two iterators are compared, they must belong to the same container. + 113 | @ref invalid_iterator | "cannot compare order of object iterators" | The order of object iterators cannot be compated, because JSON objects are unordered. + 114 | @ref invalid_iterator | "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(). + */ + class exception : public std::exception + { + public: + /*! + @brief create a user-defined exception with description and error code + + @param[in] error_code a code for the exception + @param[in] what_arg a description for the exception + */ + exception(int error_code, const std::string& what_arg) + : std::exception(), + message("[except." + std::to_string(error_code) + "] " + what_arg), + ecode(error_code) + {} + + /// returns the explanatory string + const char* what() const noexcept + { + return message.c_str(); + } + + /// returns the error code + int error_code() const noexcept + { + return ecode; + } + + private: + /// the explanatory string for the exception + const std::string message {}; + /// the error code of the exception + const int ecode = -1; + }; + + /// class for iterator-related exceptions (error code 1xx) + class invalid_iterator : public exception + { + using exception::exception; + }; + + /// class for parser-related exceptions (error code 2xx) + class parse_error : public exception + { + using exception::exception; + }; + + /// class for type-related exceptions (error code 3xx) + class type_error : public exception + { + using exception::exception; + }; + + /// class for extension-related exceptions (error code 4xx) + class extension_error : public exception + { + using exception::exception; + }; + + /// @} + /*! @brief returns the allocator associated with the container @@ -1654,7 +1748,7 @@ value_t::array and @ref value_t::object are valid); when @a type_deduction is set to `true`, this parameter has no effect - @throw std::domain_error if @a type_deduction is `false`, @a manual_type + @throw type_error (301) if @a type_deduction is `false`, @a manual_type is `value_t::object`, but @a init contains an element which is not a pair whose first element is a string; example: `"cannot create object from initializer list"` @@ -1695,7 +1789,7 @@ // if object is wanted but impossible, throw an exception if (manual_type == value_t::object and not is_an_object) { - throw std::domain_error("cannot create object from initializer list"); + throw type_error(301, "cannot create object from initializer list"); } } @@ -1778,7 +1872,7 @@ @return JSON object value - @throw std::domain_error if @a init is not a pair whose first elements are + @throw type_error (301) if @a init is not a pair whose first elements are strings; thrown by @ref basic_json(std::initializer_list<basic_json>, bool, value_t) @@ -1845,14 +1939,15 @@ @pre Iterators @a first and @a last must be initialized. - @throw std::domain_error if iterators are not compatible; that is, do not - belong to the same JSON value; example: `"iterators are not compatible"` - @throw std::out_of_range if iterators are for a primitive type (number, - boolean, or string) where an out of range error can be detected easily; - example: `"iterators out of range"` + @throw invalid_iterator (101) if iterators are not compatible; that is, do + not belong to the same JSON value; example: `"iterators are not + compatible"` + @throw invalid_iterator (104) if iterators are for a primitive type + (number, boolean, or string) where an out of range error can be detected + easily; example: `"iterators out of range"` @throw std::bad_alloc if allocation for object, array, or string fails - @throw std::domain_error if called with a null value; example: `"cannot - use construct with iterators from null"` + @throw invalid_iterator (106) if called with a null value; example: `"cannot + construct with iterators from null"` @complexity Linear in distance between @a first and @a last. @@ -1875,7 +1970,7 @@ // make sure iterator fits the current value if (first.m_object != last.m_object) { - throw std::domain_error("iterators are not compatible"); + throw invalid_iterator(101, "iterators are not compatible"); } // copy type from first iterator @@ -1892,7 +1987,7 @@ { if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end()) { - throw std::out_of_range("iterators out of range"); + throw invalid_iterator(104, "iterators out of range"); } break; } @@ -1949,7 +2044,9 @@ default: { - throw std::domain_error("cannot use construct with iterators from " + first.m_object->type_name()); + assert(first.m_object != nullptr); + throw invalid_iterator(106, "cannot use construct with iterators from " + + first.m_object->type_name()); } } @@ -2435,6 +2532,34 @@ } /*! + @brief return whether value is a signed integer number + + This function returns true iff the JSON value is a signed integer + number. This excludes floating-point and (unsigned) integer values. + + @return `true` if type is a signed integer number, `false` otherwise. + + @complexity Constant. + + @exceptionsafety No-throw guarantee: this member function never throws + exceptions. + + @liveexample{The following code exemplifies `is_number_signed()` for all + JSON types.,is_number_signed} + + @sa @ref is_number() -- check if value is a number + @sa @ref is_number_integer() -- check if value is an integer or unsigned + integer number + @sa @ref is_number_float() -- check if value is a floating-point number + + @since version 3.0.0 + */ + constexpr bool is_number_signed() const noexcept + { + return m_type == value_t::number_integer; + } + + /*! @brief return whether value is an unsigned integer number This function returns true iff the JSON value is an unsigned integer @@ -2627,7 +2752,7 @@ } else { - throw std::domain_error("type must be object, but is " + type_name()); + throw type_error(302, "type must be object, but is " + type_name()); } } @@ -2640,7 +2765,7 @@ } else { - throw std::domain_error("type must be object, but is " + type_name()); + throw type_error(302, "type must be object, but is " + type_name()); } } @@ -2667,7 +2792,7 @@ } else { - throw std::domain_error("type must be array, but is " + type_name()); + throw type_error(302, "type must be array, but is " + type_name()); } } @@ -2692,7 +2817,7 @@ } else { - throw std::domain_error("type must be array, but is " + type_name()); + throw type_error(302, "type must be array, but is " + type_name()); } } @@ -2710,7 +2835,7 @@ } else { - throw std::domain_error("type must be array, but is " + type_name()); + throw type_error(302, "type must be array, but is " + type_name()); } } @@ -2723,7 +2848,7 @@ } else { - throw std::domain_error("type must be array, but is " + type_name()); + throw type_error(302, "type must be array, but is " + type_name()); } } @@ -2740,7 +2865,7 @@ } else { - throw std::domain_error("type must be string, but is " + type_name()); + throw type_error(302, "type must be string, but is " + type_name()); } } @@ -2770,7 +2895,7 @@ default: { - throw std::domain_error("type must be number, but is " + type_name()); + throw type_error(302, "type must be number, but is " + type_name()); } } } @@ -2780,7 +2905,7 @@ { return is_boolean() ? m_value.boolean - : throw std::domain_error("type must be boolean, but is " + type_name()); + : throw type_error(302, "type must be boolean, but is " + type_name()); } /// get a pointer to the value (object) @@ -2834,13 +2959,13 @@ /// get a pointer to the value (integer number) number_integer_t* get_impl_ptr(number_integer_t*) noexcept { - return is_number_integer() ? &m_value.number_integer : nullptr; + return is_number_signed() ? &m_value.number_integer : nullptr; } /// get a pointer to the value (integer number) constexpr const number_integer_t* get_impl_ptr(const number_integer_t*) const noexcept { - return is_number_integer() ? &m_value.number_integer : nullptr; + return is_number_signed() ? &m_value.number_integer : nullptr; } /// get a pointer to the value (unsigned number) @@ -2875,8 +3000,9 @@ @tparam ThisType will be deduced as `basic_json` or `const basic_json` - @throw std::domain_error if ReferenceType does not match underlying value - type of the current JSON + @throw type_error (310) if ReferenceType does not match underlying value + type of the current JSON; example: `"incompatible ReferenceType for + get_ref, actual type is object"` */ template<typename ReferenceType, typename ThisType> static ReferenceType get_ref_impl(ThisType& obj) @@ -2893,8 +3019,8 @@ } else { - throw std::domain_error("incompatible ReferenceType for get_ref, actual type is " + - obj.type_name()); + throw type_error(310, "incompatible ReferenceType for get_ref, actual type is " + + obj.type_name()); } } @@ -2915,7 +3041,7 @@ @return copy of the JSON value, converted to type @a ValueType - @throw std::domain_error in case passed type @a ValueType is incompatible + @throw type_error (302) in case passed type @a ValueType is incompatible to JSON; example: `"type must be object, but is null"` @complexity Linear in the size of the JSON value. @@ -3095,7 +3221,7 @@ reference type @a ReferenceType fits to the JSON value; throws std::domain_error otherwise - @throw std::domain_error in case passed type @a ReferenceType is + @throw type_error (310) in case passed type @a ReferenceType is incompatible with the stored JSON value @complexity Constant. @@ -3143,7 +3269,7 @@ @return copy of the JSON value, converted to type @a ValueType - @throw std::domain_error in case passed type @a ValueType is incompatible + @throw type_error (310) in case passed type @a ValueType is incompatible to JSON, thrown by @ref get() const @complexity Linear in the size of the JSON value. @@ -3192,7 +3318,7 @@ @return reference to the element at index @a idx - @throw std::domain_error if the JSON value is not an array; example: + @throw type_error (303) if the JSON value is not an array; example: `"cannot use at() with string"` @throw std::out_of_range if the index @a idx is out of range of the array; that is, `idx >= size()`; example: `"array index 7 is out of range"` @@ -3221,7 +3347,7 @@ } else { - throw std::domain_error("cannot use at() with " + type_name()); + throw type_error(303, "cannot use at() with " + type_name()); } } @@ -3235,7 +3361,7 @@ @return const reference to the element at index @a idx - @throw std::domain_error if the JSON value is not an array; example: + @throw type_error (303) if the JSON value is not an array; example: `"cannot use at() with string"` @throw std::out_of_range if the index @a idx is out of range of the array; that is, `idx >= size()`; example: `"array index 7 is out of range"` @@ -3264,7 +3390,7 @@ } else { - throw std::domain_error("cannot use at() with " + type_name()); + throw type_error(303, "cannot use at() with " + type_name()); } } @@ -3278,7 +3404,7 @@ @return reference to the element at key @a key - @throw std::domain_error if the JSON value is not an object; example: + @throw type_error (303) if the JSON value is not an object; example: `"cannot use at() with boolean"` @throw std::out_of_range if the key @a key is is not stored in the object; that is, `find(key) == end()`; example: `"key "the fast" not found"` @@ -3311,7 +3437,7 @@ } else { - throw std::domain_error("cannot use at() with " + type_name()); + throw type_error(303, "cannot use at() with " + type_name()); } } @@ -3325,7 +3451,7 @@ @return const reference to the element at key @a key - @throw std::domain_error if the JSON value is not an object; example: + @throw type_error (303) if the JSON value is not an object; example: `"cannot use at() with boolean"` @throw std::out_of_range if the key @a key is is not stored in the object; that is, `find(key) == end()`; example: `"key "the fast" not found"` @@ -3358,7 +3484,7 @@ } else { - throw std::domain_error("cannot use at() with " + type_name()); + throw type_error(303, "cannot use at() with " + type_name()); } } @@ -3375,7 +3501,7 @@ @return reference to the element at index @a idx - @throw std::domain_error if JSON is not an array or null; example: + @throw type_error (304) if JSON is not an array or null; example: `"cannot use operator[] with string"` @complexity Constant if @a idx is in the range of the array. Otherwise @@ -3412,7 +3538,7 @@ } else { - throw std::domain_error("cannot use operator[] with " + type_name()); + throw type_error(304, "cannot use operator[] with " + type_name()); } } @@ -3425,7 +3551,7 @@ @return const reference to the element at index @a idx - @throw std::domain_error if JSON is not an array; example: `"cannot use + @throw type_error (304) if JSON is not an array; example: `"cannot use operator[] with null"` @complexity Constant. @@ -3444,7 +3570,7 @@ } else { - throw std::domain_error("cannot use operator[] with " + type_name()); + throw type_error(304, "cannot use operator[] with " + type_name()); } } @@ -3461,7 +3587,7 @@ @return reference to the element at key @a key - @throw std::domain_error if JSON is not an object or null; example: + @throw type_error (304) if JSON is not an object or null; example: `"cannot use operator[] with string"` @complexity Logarithmic in the size of the container. @@ -3492,7 +3618,7 @@ } else { - throw std::domain_error("cannot use operator[] with " + type_name()); + throw type_error(304, "cannot use operator[] with " + type_name()); } } @@ -3509,7 +3635,7 @@ @return const reference to the element at key @a key - @throw std::domain_error if JSON is not an object; example: `"cannot use + @throw type_error (304) if JSON is not an object; example: `"cannot use operator[] with null"` @complexity Logarithmic in the size of the container. @@ -3533,7 +3659,7 @@ } else { - throw std::domain_error("cannot use operator[] with " + type_name()); + throw type_error(304, "cannot use operator[] with " + type_name()); } } @@ -3550,7 +3676,7 @@ @return reference to the element at key @a key - @throw std::domain_error if JSON is not an object or null; example: + @throw type_error (304) if JSON is not an object or null; example: `"cannot use operator[] with string"` @complexity Logarithmic in the size of the container. @@ -3585,7 +3711,7 @@ @return const reference to the element at key @a key - @throw std::domain_error if JSON is not an object; example: `"cannot use + @throw type_error (304) if JSON is not an object; example: `"cannot use operator[] with null"` @complexity Logarithmic in the size of the container. @@ -3618,7 +3744,7 @@ @return reference to the element at key @a key - @throw std::domain_error if JSON is not an object or null; example: + @throw type_error (304) if JSON is not an object or null; example: `"cannot use operator[] with string"` @complexity Logarithmic in the size of the container. @@ -3650,7 +3776,7 @@ } else { - throw std::domain_error("cannot use operator[] with " + type_name()); + throw type_error(304, "cannot use operator[] with " + type_name()); } } @@ -3667,7 +3793,7 @@ @return const reference to the element at key @a key - @throw std::domain_error if JSON is not an object; example: `"cannot use + @throw type_error (304) if JSON is not an object; example: `"cannot use operator[] with null"` @complexity Logarithmic in the size of the container. @@ -3692,7 +3818,7 @@ } else { - throw std::domain_error("cannot use operator[] with " + type_name()); + throw type_error(304, "cannot use operator[] with " + type_name()); } } @@ -3729,7 +3855,7 @@ @return copy of the element at key @a key or @a default_value if @a key is not found - @throw std::domain_error if JSON is not an object; example: `"cannot use + @throw type_error (305) if JSON is not an object; example: `"cannot use value() with null"` @complexity Logarithmic in the size of the container. @@ -3766,7 +3892,7 @@ } else { - throw std::domain_error("cannot use value() with " + type_name()); + throw type_error(305, "cannot use value() with " + type_name()); } } @@ -3808,7 +3934,7 @@ @return copy of the element at key @a key or @a default_value if @a key is not found - @throw std::domain_error if JSON is not an object; example: `"cannot use + @throw type_error (305) if JSON is not an object; example: `"cannot use value() with null"` @complexity Logarithmic in the size of the container. @@ -3841,7 +3967,7 @@ } else { - throw std::domain_error("cannot use value() with " + type_name()); + throw type_error(305, "cannot use value() with " + type_name()); } } @@ -3870,7 +3996,7 @@ or an empty array or object (undefined behavior, guarded by assertions). @post The JSON value remains unchanged. - @throw std::out_of_range when called on `null` value + @throw invalid_iterator (114) when called on `null` value @liveexample{The following code shows an example for `front()`.,front} @@ -3912,7 +4038,7 @@ or an empty array or object (undefined behavior, guarded by assertions). @post The JSON value remains unchanged. - @throw std::out_of_range when called on `null` value. + @throw invalid_iterator (114) when called on `null` value @liveexample{The following code shows an example for `back()`.,back} @@ -3956,11 +4082,12 @@ @post Invalidates iterators and references at or after the point of the erase, including the `end()` iterator. - @throw std::domain_error if called on a `null` value; example: `"cannot + @throw type_error (306) if called on a `null` value; example: `"cannot use erase() with null"` - @throw std::domain_error if called on an iterator which does not belong to - the current JSON value; example: `"iterator does not fit current value"` - @throw std::out_of_range if called on a primitive type with invalid + @throw invalid_iterator (103) if called on an iterator which does not belong + to the current JSON value; example: `"iterator does not fit current + value"` + @throw invalid_iterator (105) if called on a primitive type with invalid iterator (i.e., any iterator which is not `begin()`); example: `"iterator out of range"` @@ -3993,7 +4120,7 @@ // make sure iterator fits the current value if (this != pos.m_object) { - throw std::domain_error("iterator does not fit current value"); + throw invalid_iterator(103, "iterator does not fit current value"); } InteratorType result = end(); @@ -4008,7 +4135,7 @@ { if (not pos.m_it.primitive_iterator.is_begin()) { - throw std::out_of_range("iterator out of range"); + throw invalid_iterator(105, "iterator out of range"); } if (is_string()) @@ -4038,7 +4165,7 @@ default: { - throw std::domain_error("cannot use erase() with " + type_name()); + throw type_error(306, "cannot use erase() with " + type_name()); } } @@ -4065,11 +4192,11 @@ @post Invalidates iterators and references at or after the point of the erase, including the `end()` iterator. - @throw std::domain_error if called on a `null` value; example: `"cannot + @throw type_error (306) if called on a `null` value; example: `"cannot use erase() with null"` - @throw std::domain_error if called on iterators which does not belong to - the current JSON value; example: `"iterators do not fit current value"` - @throw std::out_of_range if called on a primitive type with invalid + @throw invalid_iterator (102) if called on iterators which does not belong + to the current JSON value; example: `"iterators do not fit current value"` + @throw invalid_iterator (104) if called on a primitive type with invalid iterators (i.e., if `first != begin()` and `last != end()`); example: `"iterators out of range"` @@ -4102,7 +4229,7 @@ // make sure iterator fits the current value if (this != first.m_object or this != last.m_object) { - throw std::domain_error("iterators do not fit current value"); + throw invalid_iterator(102, "iterators do not fit current value"); } InteratorType result = end(); @@ -4117,7 +4244,7 @@ { if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end()) { - throw std::out_of_range("iterators out of range"); + throw invalid_iterator(104, "iterators out of range"); } if (is_string()) @@ -4149,7 +4276,7 @@ default: { - throw std::domain_error("cannot use erase() with " + type_name()); + throw type_error(306, "cannot use erase() with " + type_name()); } } @@ -4170,7 +4297,7 @@ @post References and iterators to the erased elements are invalidated. Other references and iterators are not affected. - @throw std::domain_error when called on a type other than JSON object; + @throw type_error (306) when called on a type other than JSON object; example: `"cannot use erase() with null"` @complexity `log(size()) + count(key)` @@ -4194,7 +4321,7 @@ } else { - throw std::domain_error("cannot use erase() with " + type_name()); + throw type_error(306, "cannot use erase() with " + type_name()); } } @@ -4205,7 +4332,7 @@ @param[in] idx index of the element to remove - @throw std::domain_error when called on a type other than JSON array; + @throw type_error (306) when called on a type other than JSON array; example: `"cannot use erase() with null"` @throw std::out_of_range when `idx >= size()`; example: `"array index 17 is out of range"` @@ -4236,7 +4363,7 @@ } else { - throw std::domain_error("cannot use erase() with " + type_name()); + throw type_error(306, "cannot use erase() with " + type_name()); } } @@ -4934,7 +5061,7 @@ @param[in] val the value to add to the JSON array - @throw std::domain_error when called on a type other than JSON array or + @throw type_error (307) when called on a type other than JSON array or null; example: `"cannot use push_back() with number"` @complexity Amortized constant. @@ -4950,7 +5077,7 @@ // push_back only works for null objects or arrays if (not(is_null() or is_array())) { - throw std::domain_error("cannot use push_back() with " + type_name()); + throw type_error(307, "cannot use push_back() with " + type_name()); } // transform null object into an array @@ -4986,7 +5113,7 @@ // push_back only works for null objects or arrays if (not(is_null() or is_array())) { - throw std::domain_error("cannot use push_back() with " + type_name()); + throw type_error(307, "cannot use push_back() with " + type_name()); } // transform null object into an array @@ -5020,7 +5147,7 @@ @param[in] val the value to add to the JSON object - @throw std::domain_error when called on a type other than JSON object or + @throw type_error (307) when called on a type other than JSON object or null; example: `"cannot use push_back() with number"` @complexity Logarithmic in the size of the container, O(log(`size()`)). @@ -5036,7 +5163,7 @@ // push_back only works for null objects or objects if (not(is_null() or is_object())) { - throw std::domain_error("cannot use push_back() with " + type_name()); + throw type_error(307, "cannot use push_back() with " + type_name()); } // transform null object into an object @@ -5119,10 +5246,10 @@ @param[in] val element to insert @return iterator pointing to the inserted @a val. - @throw std::domain_error if called on JSON values other than arrays; + @throw type_error (309) if called on JSON values other than arrays; example: `"cannot use insert() with string"` - @throw std::domain_error if @a pos is not an iterator of *this; example: - `"iterator does not fit current value"` + @throw invalid_iterator (103) if @a pos is not an iterator of *this; + example: `"iterator does not fit current value"` @complexity Constant plus linear in the distance between pos and end of the container. @@ -5139,7 +5266,7 @@ // check if iterator pos fits to this JSON value if (pos.m_object != this) { - throw std::domain_error("iterator does not fit current value"); + throw invalid_iterator(103, "iterator does not fit current value"); } // insert to array and return iterator @@ -5149,7 +5276,7 @@ } else { - throw std::domain_error("cannot use insert() with " + type_name()); + throw type_error(309, "cannot use insert() with " + type_name()); } } @@ -5174,10 +5301,10 @@ @return iterator pointing to the first element inserted, or @a pos if `cnt==0` - @throw std::domain_error if called on JSON values other than arrays; + @throw type_error (309) if called on JSON values other than arrays; example: `"cannot use insert() with string"` - @throw std::domain_error if @a pos is not an iterator of *this; example: - `"iterator does not fit current value"` + @throw invalid_iterator (103) if @a pos is not an iterator of *this; + example: `"iterator does not fit current value"` @complexity Linear in @a cnt plus linear in the distance between @a pos and end of the container. @@ -5194,7 +5321,7 @@ // check if iterator pos fits to this JSON value if (pos.m_object != this) { - throw std::domain_error("iterator does not fit current value"); + throw invalid_iterator(103, "iterator does not fit current value"); } // insert to array and return iterator @@ -5204,7 +5331,7 @@ } else { - throw std::domain_error("cannot use insert() with " + type_name()); + throw type_error(309, "cannot use insert() with " + type_name()); } } @@ -5218,13 +5345,13 @@ @param[in] first begin of the range of elements to insert @param[in] last end of the range of elements to insert - @throw std::domain_error if called on JSON values other than arrays; + @throw type_error (309) if called on JSON values other than arrays; example: `"cannot use insert() with string"` - @throw std::domain_error if @a pos is not an iterator of *this; example: - `"iterator does not fit current value"` - @throw std::domain_error if @a first and @a last do not belong to the same - JSON value; example: `"iterators do not fit"` - @throw std::domain_error if @a first or @a last are iterators into + @throw invalid_iterator (103) if @a pos is not an iterator of *this; + example: `"iterator does not fit current value"` + @throw invalid_iterator (110) if @a first and @a last do not belong to the + same JSON value; example: `"iterators do not fit"` + @throw invalid_iterator (111) if @a first or @a last are iterators into container for which insert is called; example: `"passed iterators may not belong to container"` @@ -5243,24 +5370,25 @@ // insert only works for arrays if (not is_array()) { - throw std::domain_error("cannot use insert() with " + type_name()); + throw type_error(309, "cannot use insert() with " + type_name()); } // check if iterator pos fits to this JSON value if (pos.m_object != this) { - throw std::domain_error("iterator does not fit current value"); + throw invalid_iterator(103, "iterator does not fit current value"); } // check if range iterators belong to the same JSON object if (first.m_object != last.m_object) { - throw std::domain_error("iterators do not fit"); + throw invalid_iterator(110, "iterators do not fit"); } + // first and last iterator must not belong to this container if (first.m_object == this or last.m_object == this) { - throw std::domain_error("passed iterators may not belong to container"); + throw invalid_iterator(111, "passed iterators may not belong to container"); } // insert to array and return iterator @@ -5281,10 +5409,10 @@ the end() iterator @param[in] ilist initializer list to insert the values from - @throw std::domain_error if called on JSON values other than arrays; + @throw type_error (309) if called on JSON values other than arrays; example: `"cannot use insert() with string"` - @throw std::domain_error if @a pos is not an iterator of *this; example: - `"iterator does not fit current value"` + @throw invalid_iterator (103) if @a pos is not an iterator of *this; + example: `"iterator does not fit current value"` @return iterator pointing to the first element inserted, or @a pos if `ilist` is empty @@ -5301,13 +5429,13 @@ // insert only works for arrays if (not is_array()) { - throw std::domain_error("cannot use insert() with " + type_name()); + throw type_error(309, "cannot use insert() with " + type_name()); } // check if iterator pos fits to this JSON value if (pos.m_object != this) { - throw std::domain_error("iterator does not fit current value"); + throw invalid_iterator(103, "iterator does not fit current value"); } // insert to array and return iterator @@ -5355,8 +5483,8 @@ @param[in,out] other array to exchange the contents with - @throw std::domain_error when JSON value is not an array; example: `"cannot - use swap() with string"` + @throw type_error (308) when JSON value is not an array; example: + `"cannot use swap() with string"` @complexity Constant. @@ -5374,7 +5502,7 @@ } else { - throw std::domain_error("cannot use swap() with " + type_name()); + throw type_error(308, "cannot use swap() with " + type_name()); } } @@ -5388,7 +5516,7 @@ @param[in,out] other object to exchange the contents with - @throw std::domain_error when JSON value is not an object; example: + @throw type_error (308) when JSON value is not an object; example: `"cannot use swap() with string"` @complexity Constant. @@ -5407,7 +5535,7 @@ } else { - throw std::domain_error("cannot use swap() with " + type_name()); + throw type_error(308, "cannot use swap() with " + type_name()); } } @@ -5421,7 +5549,7 @@ @param[in,out] other string to exchange the contents with - @throw std::domain_error when JSON value is not a string; example: `"cannot + @throw type_error (308) when JSON value is not a string; example: `"cannot use swap() with boolean"` @complexity Constant. @@ -5440,7 +5568,7 @@ } else { - throw std::domain_error("cannot use swap() with " + type_name()); + throw type_error(308, "cannot use swap() with " + type_name()); } } @@ -5932,6 +6060,8 @@ @return result of the deserialization + @throw parse_error (2xx) in case of parse errors + @complexity Linear in the length of the input. The parser is a predictive LL(1) parser. The complexity can be higher if the parser callback function @a cb has a super-linear complexity. @@ -5960,6 +6090,8 @@ which is used to control the deserialization by filtering unwanted values (optional) + @throw parse_error (2xx) in case of parse errors + @return result of the deserialization @complexity Linear in the length of the input. The parser is a predictive @@ -5999,7 +6131,7 @@ @param[in,out] i input stream to read a serialized JSON value from @param[in,out] j JSON value to write the deserialized input to - @throw std::invalid_argument in case of parse errors + @throw parse_error (2xx) in case of parse errors @complexity Linear in the length of the input. The parser is a predictive LL(1) parser. @@ -6807,7 +6939,7 @@ case basic_json::value_t::null: { - throw std::out_of_range("cannot get value"); + throw invalid_iterator(114, "cannot get value"); } default: @@ -6818,7 +6950,7 @@ } else { - throw std::out_of_range("cannot get value"); + throw invalid_iterator(114, "cannot get value"); } } } @@ -6854,7 +6986,7 @@ } else { - throw std::out_of_range("cannot get value"); + throw invalid_iterator(114, "cannot get value"); } } } @@ -6955,7 +7087,7 @@ // if objects are not the same, the comparison is undefined if (m_object != other.m_object) { - throw std::domain_error("cannot compare iterators of different containers"); + throw invalid_iterator(112, "cannot compare iterators of different containers"); } assert(m_object != nullptr); @@ -6997,7 +7129,7 @@ // if objects are not the same, the comparison is undefined if (m_object != other.m_object) { - throw std::domain_error("cannot compare iterators of different containers"); + throw invalid_iterator(112, "cannot compare iterators of different containers"); } assert(m_object != nullptr); @@ -7006,7 +7138,7 @@ { case basic_json::value_t::object: { - throw std::domain_error("cannot compare order of object iterators"); + throw invalid_iterator(113, "cannot compare order of object iterators"); } case basic_json::value_t::array: @@ -7060,7 +7192,7 @@ { case basic_json::value_t::object: { - throw std::domain_error("cannot use offsets with object iterators"); + throw invalid_iterator(109, "cannot use offsets with object iterators"); } case basic_json::value_t::array: @@ -7122,7 +7254,7 @@ { case basic_json::value_t::object: { - throw std::domain_error("cannot use offsets with object iterators"); + throw invalid_iterator(109, "cannot use offsets with object iterators"); } case basic_json::value_t::array: @@ -7149,7 +7281,7 @@ { case basic_json::value_t::object: { - throw std::domain_error("cannot use operator[] for object iterators"); + throw invalid_iterator(108, "cannot use operator[] for object iterators"); } case basic_json::value_t::array: @@ -7159,7 +7291,7 @@ case basic_json::value_t::null: { - throw std::out_of_range("cannot get value"); + throw invalid_iterator(114, "cannot get value"); } default: @@ -7170,7 +7302,7 @@ } else { - throw std::out_of_range("cannot get value"); + throw invalid_iterator(114, "cannot get value"); } } } @@ -7190,7 +7322,7 @@ } else { - throw std::domain_error("cannot use key() for non-object iterators"); + throw invalid_iterator(107, "cannot use key() for non-object iterators"); } } @@ -7501,7 +7633,7 @@ { m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str()); assert(m_content != nullptr); - m_start = m_cursor = m_content; + m_buffer_start = m_start = m_cursor = m_content; m_limit = m_content + s.size(); } @@ -7513,7 +7645,7 @@ std::getline(*m_stream, m_buffer); m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str()); assert(m_content != nullptr); - m_start = m_cursor = m_content; + m_buffer_start = m_start = m_cursor = m_content; m_limit = m_content + m_buffer.size(); } @@ -7538,17 +7670,17 @@ @return string representation of the code point; the length of the result string is between 1 and 4 characters. - @throw std::out_of_range if code point is > 0x10ffff; example: `"code + @throw parse_error (203) if code point is > 0x10ffff; example: `"code points above 0x10FFFF are invalid"` - @throw std::invalid_argument if the low surrogate is invalid; example: - `""missing or wrong low surrogate""` + @throw parse_error (202) if the low surrogate is invalid; example: + `"missing or wrong low surrogate"` @complexity Constant. @see <http://en.wikipedia.org/wiki/UTF-8#Sample_code> */ - static string_t to_unicode(const std::size_t codepoint1, - const std::size_t codepoint2 = 0) + string_t to_unicode(const std::size_t codepoint1, + const std::size_t codepoint2 = 0) const { // calculate the code point from the given code points std::size_t codepoint = codepoint1; @@ -7571,7 +7703,8 @@ } else { - throw std::invalid_argument("missing or wrong low surrogate"); + const std::string error_msg = error_message() + "; missing or wrong low surrogate"; + throw parse_error(202, error_msg); } } @@ -7605,7 +7738,8 @@ } else { - throw std::out_of_range("code points above 0x10FFFF are invalid"); + const std::string error_msg = error_message() + "; code points above 0x10FFFF are invalid"; + throw parse_error(203, error_msg); } return result; @@ -8458,7 +8592,8 @@ /// append data from the stream to the internal buffer void yyfill() noexcept { - if (m_stream == nullptr or not * m_stream) + // yyfill has no effect if we do not have a ready stream + if (m_stream == nullptr or m_stream->fail()) { return; } @@ -8467,20 +8602,56 @@ const auto offset_marker = m_marker - m_start; const auto offset_cursor = m_cursor - m_start; - m_buffer.erase(0, static_cast<size_t>(offset_start)); + // get the size of the previous buffer + const auto last_buffer_size = static_cast<size_t>(offset_start); + // remmeber all buffer sizes so far + m_previous_buffer_sizes += last_buffer_size; + + // delete previous buffer + m_buffer.erase(0, last_buffer_size); + + // read line from stream to buffer std::string line; assert(m_stream != nullptr); std::getline(*m_stream, line); m_buffer += "\n" + line; // add line with newline symbol + // set the pointers accordingly m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str()); assert(m_content != nullptr); - m_start = m_content; + m_buffer_start = m_start = m_content; m_marker = m_start + offset_marker; m_cursor = m_start + offset_cursor; m_limit = m_start + m_buffer.size() - 1; } + /// return the location of the end of the last token + size_t last_token_location() const noexcept + { + // m_buffer_start points to the first byte of the current buffer + // m_cursor points to the byte behind the current token + // m_previous_buffer_sizes contains the size the previous buffers + return static_cast<size_t>(m_cursor - m_buffer_start) + m_previous_buffer_sizes; + } + + /// returns an error message for parse errors + std::string error_message() const + { + const std::string last_token(reinterpret_cast<typename std::string::const_pointer>(m_start), + static_cast<size_t>(m_cursor - m_start)); + std::string result = "parse error: unexpected "; + if (last_token_type == token_type::end_of_input) + { + result += token_type_name(token_type::end_of_input); + } + else + { + result += "'" + last_token + "'"; + } + result += " at byte " + std::to_string(last_token_location() - last_token.size() + 1); + return result; + } + /// return string representation of last read token string_t get_token_string() const { @@ -8544,7 +8715,9 @@ @return string value of current token without opening and closing quotes - @throw std::out_of_range if to_unicode fails + + @throw parse_error (202,203) if to_unicode fails + @throw parse_error (204) if low surrogate is missing */ string_t get_string() const { @@ -8619,7 +8792,8 @@ // make sure there is a subsequent unicode if ((i + 6 >= m_limit) or * (i + 5) != '\\' or * (i + 6) != 'u') { - throw std::invalid_argument("missing low surrogate"); + std::string error_msg = error_message() + "; missing low surrogate"; + throw parse_error(204, error_msg); } // get code yyyy from uxxxx\uyyyy @@ -8832,6 +9006,10 @@ const lexer_char_t* m_cursor = nullptr; /// pointer to the end of the buffer const lexer_char_t* m_limit = nullptr; + /// pointer to the beginning of the buffer + const lexer_char_t* m_buffer_start = nullptr; + /// the size of the last buffer (before yyfill was called) + size_t m_previous_buffer_sizes = 0; /// the last token type token_type last_token_type = token_type::end_of_input; }; @@ -9077,12 +9255,9 @@ { if (t != last_token) { - std::string error_msg = "parse error - unexpected "; - error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token_string() + - "'") : - lexer::token_type_name(last_token)); + std::string error_msg = m_lexer.error_message(); error_msg += "; expected " + lexer::token_type_name(t); - throw std::invalid_argument(error_msg); + throw parse_error(201, error_msg); } } @@ -9090,11 +9265,9 @@ { if (t == last_token) { - std::string error_msg = "parse error - unexpected "; - error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token_string() + - "'") : - lexer::token_type_name(last_token)); - throw std::invalid_argument(error_msg); + std::string error_msg = m_lexer.error_message(); + error_msg += "; expected JSON value"; + throw parse_error(201, error_msg); } } @@ -9137,10 +9310,10 @@ empty string is assumed which references the whole JSON value - @throw std::domain_error if reference token is nonempty and does not - begin with a slash (`/`); example: `"JSON pointer must be empty or + @throw extension_error (403) if reference token is nonempty and does + not begin with a slash (`/`); example: `"JSON pointer must be empty or begin with /"` - @throw std::domain_error if a tilde (`~`) is not followed by `0` + @throw extension_error (404) if a tilde (`~`) is not followed by `0` (representing `~`) or `1` (representing `/`); example: `"escape error: ~ must be followed with 0 or 1"` @@ -9190,7 +9363,7 @@ { if (is_root()) { - throw std::domain_error("JSON pointer has no parent"); + throw extension_error(401, "JSON pointer has no parent"); } auto last = reference_tokens.back(); @@ -9208,7 +9381,7 @@ { if (is_root()) { - throw std::domain_error("JSON pointer has no parent"); + throw extension_error(401, "JSON pointer has no parent"); } json_pointer result = *this; @@ -9269,7 +9442,7 @@ */ default: { - throw std::domain_error("invalid value to unflatten"); + throw extension_error(411, "invalid value to unflatten"); } } } @@ -9287,8 +9460,10 @@ @complexity Linear in the length of the JSON pointer. @throw std::out_of_range if the JSON pointer can not be resolved - @throw std::domain_error if an array index begins with '0' - @throw std::invalid_argument if an array index was not a number + @throw extension_error (402) if an array index begins with '0' or is + not a number + @throw extension_error (405) if the reference token could not be + resolved */ reference get_unchecked(pointer ptr) const { @@ -9308,7 +9483,7 @@ // error condition (cf. RFC 6901, Sect. 4) if (reference_token.size() > 1 and reference_token[0] == '0') { - throw std::domain_error("array index must not begin with '0'"); + throw extension_error(402, "array index must not begin with '0'"); } if (reference_token == "-") @@ -9319,14 +9494,24 @@ else { // convert array index to number; unchecked access - ptr = &ptr->operator[](static_cast<size_type>(std::stoi(reference_token))); + try + { + ptr = &ptr->operator[](static_cast<size_type>(std::stoi(reference_token))); + } + catch (std::invalid_argument&) + { + // std::stoi throws std::invalid_argument if + // no conversion could be performed; we catch + // it for better diagnosis + throw extension_error(402, "array index is '" + reference_token + "', but must be a number"); + } } break; } default: { - throw std::out_of_range("unresolved reference token '" + reference_token + "'"); + throw extension_error(405, "unresolved reference token '" + reference_token + "'"); } } } @@ -9352,15 +9537,15 @@ if (reference_token == "-") { // "-" always fails the range check - throw std::out_of_range("array index '-' (" + - std::to_string(ptr->m_value.array->size()) + - ") is out of range"); + throw extension_error(406, "array index '-' (" + + std::to_string(ptr->m_value.array->size()) + + ") is out of range"); } // error condition (cf. RFC 6901, Sect. 4) if (reference_token.size() > 1 and reference_token[0] == '0') { - throw std::domain_error("array index must not begin with '0'"); + throw extension_error(402, "array index must not begin with '0'"); } // note: at performs range check @@ -9370,7 +9555,7 @@ default: { - throw std::out_of_range("unresolved reference token '" + reference_token + "'"); + throw extension_error(405, "unresolved reference token '" + reference_token + "'"); } } } @@ -9404,15 +9589,15 @@ if (reference_token == "-") { // "-" cannot be used for const access - throw std::out_of_range("array index '-' (" + - std::to_string(ptr->m_value.array->size()) + - ") is out of range"); + throw extension_error(406, "array index '-' (" + + std::to_string(ptr->m_value.array->size()) + + ") is out of range"); } // error condition (cf. RFC 6901, Sect. 4) if (reference_token.size() > 1 and reference_token[0] == '0') { - throw std::domain_error("array index must not begin with '0'"); + throw extension_error(402, "array index must not begin with '0'"); } // use unchecked array access @@ -9422,7 +9607,7 @@ default: { - throw std::out_of_range("unresolved reference token '" + reference_token + "'"); + throw extension_error(405, "unresolved reference token '" + reference_token + "'"); } } } @@ -9448,15 +9633,15 @@ if (reference_token == "-") { // "-" always fails the range check - throw std::out_of_range("array index '-' (" + - std::to_string(ptr->m_value.array->size()) + - ") is out of range"); + throw extension_error(406, "array index '-' (" + + std::to_string(ptr->m_value.array->size()) + + ") is out of range"); } // error condition (cf. RFC 6901, Sect. 4) if (reference_token.size() > 1 and reference_token[0] == '0') { - throw std::domain_error("array index must not begin with '0'"); + throw extension_error(402, "array index must not begin with '0'"); } // note: at performs range check @@ -9466,7 +9651,7 @@ default: { - throw std::out_of_range("unresolved reference token '" + reference_token + "'"); + throw extension_error(405, "unresolved reference token '" + reference_token + "'"); } } } @@ -9488,7 +9673,7 @@ // check if nonempty reference string begins with slash if (reference_string[0] != '/') { - throw std::domain_error("JSON pointer must be empty or begin with '/'"); + throw extension_error(403, "JSON pointer must be empty or begin with '/'"); } // extract the reference tokens: @@ -9523,13 +9708,13 @@ (reference_token[pos + 1] != '0' and reference_token[pos + 1] != '1')) { - throw std::domain_error("escape error: '~' must be followed with '0' or '1'"); + throw extension_error(404, "escape error: '~' must be followed with '0' or '1'"); } } // finally, store the reference token unescape(reference_token); - result.push_back(reference_token); + result.emplace_back(reference_token); } return result; @@ -9651,7 +9836,7 @@ { if (not value.is_object()) { - throw std::domain_error("only objects can be unflattened"); + throw extension_error(412, "only objects can be unflattened"); } basic_json result; @@ -9661,7 +9846,7 @@ { if (not element.second.is_primitive()) { - throw std::domain_error("values in object must be primitive"); + throw extension_error(413, "values in object must be primitive"); } // assign value to reference pointed to by JSON pointer; Note @@ -9713,8 +9898,8 @@ @complexity Constant. @throw std::out_of_range if the JSON pointer can not be resolved - @throw std::domain_error if an array index begins with '0' - @throw std::invalid_argument if an array index was not a number + @throw extension_error (402) if an array index begins with '0' or is not + a number @liveexample{The behavior is shown in the example.,operatorjson_pointer} @@ -9740,8 +9925,8 @@ @complexity Constant. @throw std::out_of_range if the JSON pointer can not be resolved - @throw std::domain_error if an array index begins with '0' - @throw std::invalid_argument if an array index was not a number + @throw extension_error (402) if an array index begins with '0' or is not + a number @liveexample{The behavior is shown in the example.,operatorjson_pointer_const} @@ -9765,8 +9950,8 @@ @complexity Constant. @throw std::out_of_range if the JSON pointer can not be resolved - @throw std::domain_error if an array index begins with '0' - @throw std::invalid_argument if an array index was not a number + @throw extension_error (402) if an array index begins with '0' or is not + a number @liveexample{The behavior is shown in the example.,at_json_pointer} @@ -9790,8 +9975,8 @@ @complexity Constant. @throw std::out_of_range if the JSON pointer can not be resolved - @throw std::domain_error if an array index begins with '0' - @throw std::invalid_argument if an array index was not a number + @throw extension_error (402) if an array index begins with '0' or is not + a number @liveexample{The behavior is shown in the example.,at_json_pointer_const} @@ -9891,8 +10076,11 @@ @throw std::out_of_range if a JSON pointer inside the patch could not be resolved successfully in the current JSON value; example: `"key baz not found"` - @throw invalid_argument if the JSON patch is malformed (e.g., mandatory - attributes are missing); example: `"operation add must have member path"` + @throw extension_error (408) if the JSON patch is malformed (e.g., + mandatory attributes are missing); example: `"operation add must have + string member path"` + @throw extension_error (407) if the JSON patch is malformed; example: + `"JSON patch must be an array of objects"` @complexity Linear in the size of the JSON value and the length of the JSON patch. As usually only a fraction of the JSON value is affected by @@ -9990,7 +10178,7 @@ if (static_cast<size_type>(idx) > parent.size()) { // avoid undefined behavior - throw std::out_of_range("array index " + std::to_string(idx) + " is out of range"); + throw extension_error(406, "array index " + std::to_string(idx) + " is out of range"); } else { @@ -10042,7 +10230,7 @@ if (not json_patch.is_array()) { // a JSON patch must be an array of objects - throw std::invalid_argument("JSON patch must be an array of objects"); + throw extension_error(407, "JSON patch must be an array of objects"); } // iterate and apply th eoperations @@ -10062,13 +10250,13 @@ // check if desired value is present if (it == val.m_value.object->end()) { - throw std::invalid_argument(error_msg + " must have member '" + member + "'"); + throw extension_error(408, error_msg + " must have string member '" + member + "'"); } // check if result is of type string if (string_type and not it->second.is_string()) { - throw std::invalid_argument(error_msg + " must have string member '" + member + "'"); + throw extension_error(408, error_msg + " must have string member '" + member + "'"); } // no error: return value @@ -10078,7 +10266,7 @@ // type check if (not val.is_object()) { - throw std::invalid_argument("JSON patch must be an array of objects"); + throw extension_error(407, "JSON patch must be an array of objects"); } // collect mandatory members @@ -10151,7 +10339,7 @@ // throw an exception if test fails if (not success) { - throw std::domain_error("unsuccessful: " + val.dump()); + throw extension_error(410, "unsuccessful: " + val.dump()); } break; @@ -10161,7 +10349,7 @@ { // op must be "add", "remove", "replace", "move", "copy", or // "test" - throw std::invalid_argument("operation value '" + op + "' is invalid"); + throw extension_error(409, "operation value '" + op + "' is invalid"); } } }
diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 32482ea..e8949d6 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c
@@ -272,6 +272,100 @@ /// @} + public: + ///////////////////////////// + // user-defined exceptions // + ///////////////////////////// + + /// @name exception types + /// Classes for exceptions used by the library functions. + /// @{ + + /*! + @brief a user-defined exception class + + To implement user-defined exceptions for the library, this class is used + as subclass for different exception types. Compared to `std::exception`, + the class also contains an error code to better reference and document + exceptions. + + error code | exception type | message | description + ---------- | -------------- | ------- | ----------- + 101 | @ref invalid_iterator | "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. + 102 | @ref invalid_iterator | "iterators do not fit current value" | Either iterator passed to function @ref erase(InteratorType first, InteratorType 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. + 103 | @ref invalid_iterator | "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. + 104 | @ref invalid_iterator | "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. + 105 | @ref invalid_iterator | "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. + 106 | @ref invalid_iterator | "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. + 107 | @ref invalid_iterator | "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. + 108 | @ref invalid_iterator | "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. + 109 | @ref invalid_iterator | "cannot use offsets with object iterators" | The offset operators (+, -, +=, -=) cannot be used on iterators belonging to a JSON object, because JSON objects are unordered. + 110 | @ref invalid_iterator | "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. + 111 | @ref invalid_iterator | "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. + 112 | @ref invalid_iterator | "cannot compare iterators of different containers" | When two iterators are compared, they must belong to the same container. + 113 | @ref invalid_iterator | "cannot compare order of object iterators" | The order of object iterators cannot be compated, because JSON objects are unordered. + 114 | @ref invalid_iterator | "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(). + */ + class exception : public std::exception + { + public: + /*! + @brief create a user-defined exception with description and error code + + @param[in] error_code a code for the exception + @param[in] what_arg a description for the exception + */ + exception(int error_code, const std::string& what_arg) + : std::exception(), + message("[except." + std::to_string(error_code) + "] " + what_arg), + ecode(error_code) + {} + + /// returns the explanatory string + const char* what() const noexcept + { + return message.c_str(); + } + + /// returns the error code + int error_code() const noexcept + { + return ecode; + } + + private: + /// the explanatory string for the exception + const std::string message {}; + /// the error code of the exception + const int ecode = -1; + }; + + /// class for iterator-related exceptions (error code 1xx) + class invalid_iterator : public exception + { + using exception::exception; + }; + + /// class for parser-related exceptions (error code 2xx) + class parse_error : public exception + { + using exception::exception; + }; + + /// class for type-related exceptions (error code 3xx) + class type_error : public exception + { + using exception::exception; + }; + + /// class for extension-related exceptions (error code 4xx) + class extension_error : public exception + { + using exception::exception; + }; + + /// @} + /*! @brief returns the allocator associated with the container @@ -1654,7 +1748,7 @@ value_t::array and @ref value_t::object are valid); when @a type_deduction is set to `true`, this parameter has no effect - @throw std::domain_error if @a type_deduction is `false`, @a manual_type + @throw type_error (301) if @a type_deduction is `false`, @a manual_type is `value_t::object`, but @a init contains an element which is not a pair whose first element is a string; example: `"cannot create object from initializer list"` @@ -1695,7 +1789,7 @@ // if object is wanted but impossible, throw an exception if (manual_type == value_t::object and not is_an_object) { - throw std::domain_error("cannot create object from initializer list"); + throw type_error(301, "cannot create object from initializer list"); } } @@ -1778,7 +1872,7 @@ @return JSON object value - @throw std::domain_error if @a init is not a pair whose first elements are + @throw type_error (301) if @a init is not a pair whose first elements are strings; thrown by @ref basic_json(std::initializer_list<basic_json>, bool, value_t) @@ -1845,14 +1939,15 @@ @pre Iterators @a first and @a last must be initialized. - @throw std::domain_error if iterators are not compatible; that is, do not - belong to the same JSON value; example: `"iterators are not compatible"` - @throw std::out_of_range if iterators are for a primitive type (number, - boolean, or string) where an out of range error can be detected easily; - example: `"iterators out of range"` + @throw invalid_iterator (101) if iterators are not compatible; that is, do + not belong to the same JSON value; example: `"iterators are not + compatible"` + @throw invalid_iterator (104) if iterators are for a primitive type + (number, boolean, or string) where an out of range error can be detected + easily; example: `"iterators out of range"` @throw std::bad_alloc if allocation for object, array, or string fails - @throw std::domain_error if called with a null value; example: `"cannot - use construct with iterators from null"` + @throw invalid_iterator (106) if called with a null value; example: `"cannot + construct with iterators from null"` @complexity Linear in distance between @a first and @a last. @@ -1875,7 +1970,7 @@ // make sure iterator fits the current value if (first.m_object != last.m_object) { - throw std::domain_error("iterators are not compatible"); + throw invalid_iterator(101, "iterators are not compatible"); } // copy type from first iterator @@ -1892,7 +1987,7 @@ { if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end()) { - throw std::out_of_range("iterators out of range"); + throw invalid_iterator(104, "iterators out of range"); } break; } @@ -1949,7 +2044,9 @@ default: { - throw std::domain_error("cannot use construct with iterators from " + first.m_object->type_name()); + assert(first.m_object != nullptr); + throw invalid_iterator(106, "cannot use construct with iterators from " + + first.m_object->type_name()); } } @@ -2435,6 +2532,34 @@ } /*! + @brief return whether value is a signed integer number + + This function returns true iff the JSON value is a signed integer + number. This excludes floating-point and (unsigned) integer values. + + @return `true` if type is a signed integer number, `false` otherwise. + + @complexity Constant. + + @exceptionsafety No-throw guarantee: this member function never throws + exceptions. + + @liveexample{The following code exemplifies `is_number_signed()` for all + JSON types.,is_number_signed} + + @sa @ref is_number() -- check if value is a number + @sa @ref is_number_integer() -- check if value is an integer or unsigned + integer number + @sa @ref is_number_float() -- check if value is a floating-point number + + @since version 3.0.0 + */ + constexpr bool is_number_signed() const noexcept + { + return m_type == value_t::number_integer; + } + + /*! @brief return whether value is an unsigned integer number This function returns true iff the JSON value is an unsigned integer @@ -2627,7 +2752,7 @@ } else { - throw std::domain_error("type must be object, but is " + type_name()); + throw type_error(302, "type must be object, but is " + type_name()); } } @@ -2640,7 +2765,7 @@ } else { - throw std::domain_error("type must be object, but is " + type_name()); + throw type_error(302, "type must be object, but is " + type_name()); } } @@ -2667,7 +2792,7 @@ } else { - throw std::domain_error("type must be array, but is " + type_name()); + throw type_error(302, "type must be array, but is " + type_name()); } } @@ -2692,7 +2817,7 @@ } else { - throw std::domain_error("type must be array, but is " + type_name()); + throw type_error(302, "type must be array, but is " + type_name()); } } @@ -2710,7 +2835,7 @@ } else { - throw std::domain_error("type must be array, but is " + type_name()); + throw type_error(302, "type must be array, but is " + type_name()); } } @@ -2723,7 +2848,7 @@ } else { - throw std::domain_error("type must be array, but is " + type_name()); + throw type_error(302, "type must be array, but is " + type_name()); } } @@ -2740,7 +2865,7 @@ } else { - throw std::domain_error("type must be string, but is " + type_name()); + throw type_error(302, "type must be string, but is " + type_name()); } } @@ -2770,7 +2895,7 @@ default: { - throw std::domain_error("type must be number, but is " + type_name()); + throw type_error(302, "type must be number, but is " + type_name()); } } } @@ -2780,7 +2905,7 @@ { return is_boolean() ? m_value.boolean - : throw std::domain_error("type must be boolean, but is " + type_name()); + : throw type_error(302, "type must be boolean, but is " + type_name()); } /// get a pointer to the value (object) @@ -2834,13 +2959,13 @@ /// get a pointer to the value (integer number) number_integer_t* get_impl_ptr(number_integer_t*) noexcept { - return is_number_integer() ? &m_value.number_integer : nullptr; + return is_number_signed() ? &m_value.number_integer : nullptr; } /// get a pointer to the value (integer number) constexpr const number_integer_t* get_impl_ptr(const number_integer_t*) const noexcept { - return is_number_integer() ? &m_value.number_integer : nullptr; + return is_number_signed() ? &m_value.number_integer : nullptr; } /// get a pointer to the value (unsigned number) @@ -2875,8 +3000,9 @@ @tparam ThisType will be deduced as `basic_json` or `const basic_json` - @throw std::domain_error if ReferenceType does not match underlying value - type of the current JSON + @throw type_error (310) if ReferenceType does not match underlying value + type of the current JSON; example: `"incompatible ReferenceType for + get_ref, actual type is object"` */ template<typename ReferenceType, typename ThisType> static ReferenceType get_ref_impl(ThisType& obj) @@ -2893,8 +3019,8 @@ } else { - throw std::domain_error("incompatible ReferenceType for get_ref, actual type is " + - obj.type_name()); + throw type_error(310, "incompatible ReferenceType for get_ref, actual type is " + + obj.type_name()); } } @@ -2915,7 +3041,7 @@ @return copy of the JSON value, converted to type @a ValueType - @throw std::domain_error in case passed type @a ValueType is incompatible + @throw type_error (302) in case passed type @a ValueType is incompatible to JSON; example: `"type must be object, but is null"` @complexity Linear in the size of the JSON value. @@ -3095,7 +3221,7 @@ reference type @a ReferenceType fits to the JSON value; throws std::domain_error otherwise - @throw std::domain_error in case passed type @a ReferenceType is + @throw type_error (310) in case passed type @a ReferenceType is incompatible with the stored JSON value @complexity Constant. @@ -3143,7 +3269,7 @@ @return copy of the JSON value, converted to type @a ValueType - @throw std::domain_error in case passed type @a ValueType is incompatible + @throw type_error (310) in case passed type @a ValueType is incompatible to JSON, thrown by @ref get() const @complexity Linear in the size of the JSON value. @@ -3192,7 +3318,7 @@ @return reference to the element at index @a idx - @throw std::domain_error if the JSON value is not an array; example: + @throw type_error (303) if the JSON value is not an array; example: `"cannot use at() with string"` @throw std::out_of_range if the index @a idx is out of range of the array; that is, `idx >= size()`; example: `"array index 7 is out of range"` @@ -3221,7 +3347,7 @@ } else { - throw std::domain_error("cannot use at() with " + type_name()); + throw type_error(303, "cannot use at() with " + type_name()); } } @@ -3235,7 +3361,7 @@ @return const reference to the element at index @a idx - @throw std::domain_error if the JSON value is not an array; example: + @throw type_error (303) if the JSON value is not an array; example: `"cannot use at() with string"` @throw std::out_of_range if the index @a idx is out of range of the array; that is, `idx >= size()`; example: `"array index 7 is out of range"` @@ -3264,7 +3390,7 @@ } else { - throw std::domain_error("cannot use at() with " + type_name()); + throw type_error(303, "cannot use at() with " + type_name()); } } @@ -3278,7 +3404,7 @@ @return reference to the element at key @a key - @throw std::domain_error if the JSON value is not an object; example: + @throw type_error (303) if the JSON value is not an object; example: `"cannot use at() with boolean"` @throw std::out_of_range if the key @a key is is not stored in the object; that is, `find(key) == end()`; example: `"key "the fast" not found"` @@ -3311,7 +3437,7 @@ } else { - throw std::domain_error("cannot use at() with " + type_name()); + throw type_error(303, "cannot use at() with " + type_name()); } } @@ -3325,7 +3451,7 @@ @return const reference to the element at key @a key - @throw std::domain_error if the JSON value is not an object; example: + @throw type_error (303) if the JSON value is not an object; example: `"cannot use at() with boolean"` @throw std::out_of_range if the key @a key is is not stored in the object; that is, `find(key) == end()`; example: `"key "the fast" not found"` @@ -3358,7 +3484,7 @@ } else { - throw std::domain_error("cannot use at() with " + type_name()); + throw type_error(303, "cannot use at() with " + type_name()); } } @@ -3375,7 +3501,7 @@ @return reference to the element at index @a idx - @throw std::domain_error if JSON is not an array or null; example: + @throw type_error (304) if JSON is not an array or null; example: `"cannot use operator[] with string"` @complexity Constant if @a idx is in the range of the array. Otherwise @@ -3412,7 +3538,7 @@ } else { - throw std::domain_error("cannot use operator[] with " + type_name()); + throw type_error(304, "cannot use operator[] with " + type_name()); } } @@ -3425,7 +3551,7 @@ @return const reference to the element at index @a idx - @throw std::domain_error if JSON is not an array; example: `"cannot use + @throw type_error (304) if JSON is not an array; example: `"cannot use operator[] with null"` @complexity Constant. @@ -3444,7 +3570,7 @@ } else { - throw std::domain_error("cannot use operator[] with " + type_name()); + throw type_error(304, "cannot use operator[] with " + type_name()); } } @@ -3461,7 +3587,7 @@ @return reference to the element at key @a key - @throw std::domain_error if JSON is not an object or null; example: + @throw type_error (304) if JSON is not an object or null; example: `"cannot use operator[] with string"` @complexity Logarithmic in the size of the container. @@ -3492,7 +3618,7 @@ } else { - throw std::domain_error("cannot use operator[] with " + type_name()); + throw type_error(304, "cannot use operator[] with " + type_name()); } } @@ -3509,7 +3635,7 @@ @return const reference to the element at key @a key - @throw std::domain_error if JSON is not an object; example: `"cannot use + @throw type_error (304) if JSON is not an object; example: `"cannot use operator[] with null"` @complexity Logarithmic in the size of the container. @@ -3533,7 +3659,7 @@ } else { - throw std::domain_error("cannot use operator[] with " + type_name()); + throw type_error(304, "cannot use operator[] with " + type_name()); } } @@ -3550,7 +3676,7 @@ @return reference to the element at key @a key - @throw std::domain_error if JSON is not an object or null; example: + @throw type_error (304) if JSON is not an object or null; example: `"cannot use operator[] with string"` @complexity Logarithmic in the size of the container. @@ -3585,7 +3711,7 @@ @return const reference to the element at key @a key - @throw std::domain_error if JSON is not an object; example: `"cannot use + @throw type_error (304) if JSON is not an object; example: `"cannot use operator[] with null"` @complexity Logarithmic in the size of the container. @@ -3618,7 +3744,7 @@ @return reference to the element at key @a key - @throw std::domain_error if JSON is not an object or null; example: + @throw type_error (304) if JSON is not an object or null; example: `"cannot use operator[] with string"` @complexity Logarithmic in the size of the container. @@ -3650,7 +3776,7 @@ } else { - throw std::domain_error("cannot use operator[] with " + type_name()); + throw type_error(304, "cannot use operator[] with " + type_name()); } } @@ -3667,7 +3793,7 @@ @return const reference to the element at key @a key - @throw std::domain_error if JSON is not an object; example: `"cannot use + @throw type_error (304) if JSON is not an object; example: `"cannot use operator[] with null"` @complexity Logarithmic in the size of the container. @@ -3692,7 +3818,7 @@ } else { - throw std::domain_error("cannot use operator[] with " + type_name()); + throw type_error(304, "cannot use operator[] with " + type_name()); } } @@ -3729,7 +3855,7 @@ @return copy of the element at key @a key or @a default_value if @a key is not found - @throw std::domain_error if JSON is not an object; example: `"cannot use + @throw type_error (305) if JSON is not an object; example: `"cannot use value() with null"` @complexity Logarithmic in the size of the container. @@ -3766,7 +3892,7 @@ } else { - throw std::domain_error("cannot use value() with " + type_name()); + throw type_error(305, "cannot use value() with " + type_name()); } } @@ -3808,7 +3934,7 @@ @return copy of the element at key @a key or @a default_value if @a key is not found - @throw std::domain_error if JSON is not an object; example: `"cannot use + @throw type_error (305) if JSON is not an object; example: `"cannot use value() with null"` @complexity Logarithmic in the size of the container. @@ -3841,7 +3967,7 @@ } else { - throw std::domain_error("cannot use value() with " + type_name()); + throw type_error(305, "cannot use value() with " + type_name()); } } @@ -3870,7 +3996,7 @@ or an empty array or object (undefined behavior, guarded by assertions). @post The JSON value remains unchanged. - @throw std::out_of_range when called on `null` value + @throw invalid_iterator (114) when called on `null` value @liveexample{The following code shows an example for `front()`.,front} @@ -3912,7 +4038,7 @@ or an empty array or object (undefined behavior, guarded by assertions). @post The JSON value remains unchanged. - @throw std::out_of_range when called on `null` value. + @throw invalid_iterator (114) when called on `null` value @liveexample{The following code shows an example for `back()`.,back} @@ -3956,11 +4082,12 @@ @post Invalidates iterators and references at or after the point of the erase, including the `end()` iterator. - @throw std::domain_error if called on a `null` value; example: `"cannot + @throw type_error (306) if called on a `null` value; example: `"cannot use erase() with null"` - @throw std::domain_error if called on an iterator which does not belong to - the current JSON value; example: `"iterator does not fit current value"` - @throw std::out_of_range if called on a primitive type with invalid + @throw invalid_iterator (103) if called on an iterator which does not belong + to the current JSON value; example: `"iterator does not fit current + value"` + @throw invalid_iterator (105) if called on a primitive type with invalid iterator (i.e., any iterator which is not `begin()`); example: `"iterator out of range"` @@ -3993,7 +4120,7 @@ // make sure iterator fits the current value if (this != pos.m_object) { - throw std::domain_error("iterator does not fit current value"); + throw invalid_iterator(103, "iterator does not fit current value"); } InteratorType result = end(); @@ -4008,7 +4135,7 @@ { if (not pos.m_it.primitive_iterator.is_begin()) { - throw std::out_of_range("iterator out of range"); + throw invalid_iterator(105, "iterator out of range"); } if (is_string()) @@ -4038,7 +4165,7 @@ default: { - throw std::domain_error("cannot use erase() with " + type_name()); + throw type_error(306, "cannot use erase() with " + type_name()); } } @@ -4065,11 +4192,11 @@ @post Invalidates iterators and references at or after the point of the erase, including the `end()` iterator. - @throw std::domain_error if called on a `null` value; example: `"cannot + @throw type_error (306) if called on a `null` value; example: `"cannot use erase() with null"` - @throw std::domain_error if called on iterators which does not belong to - the current JSON value; example: `"iterators do not fit current value"` - @throw std::out_of_range if called on a primitive type with invalid + @throw invalid_iterator (102) if called on iterators which does not belong + to the current JSON value; example: `"iterators do not fit current value"` + @throw invalid_iterator (104) if called on a primitive type with invalid iterators (i.e., if `first != begin()` and `last != end()`); example: `"iterators out of range"` @@ -4102,7 +4229,7 @@ // make sure iterator fits the current value if (this != first.m_object or this != last.m_object) { - throw std::domain_error("iterators do not fit current value"); + throw invalid_iterator(102, "iterators do not fit current value"); } InteratorType result = end(); @@ -4117,7 +4244,7 @@ { if (not first.m_it.primitive_iterator.is_begin() or not last.m_it.primitive_iterator.is_end()) { - throw std::out_of_range("iterators out of range"); + throw invalid_iterator(104, "iterators out of range"); } if (is_string()) @@ -4149,7 +4276,7 @@ default: { - throw std::domain_error("cannot use erase() with " + type_name()); + throw type_error(306, "cannot use erase() with " + type_name()); } } @@ -4170,7 +4297,7 @@ @post References and iterators to the erased elements are invalidated. Other references and iterators are not affected. - @throw std::domain_error when called on a type other than JSON object; + @throw type_error (306) when called on a type other than JSON object; example: `"cannot use erase() with null"` @complexity `log(size()) + count(key)` @@ -4194,7 +4321,7 @@ } else { - throw std::domain_error("cannot use erase() with " + type_name()); + throw type_error(306, "cannot use erase() with " + type_name()); } } @@ -4205,7 +4332,7 @@ @param[in] idx index of the element to remove - @throw std::domain_error when called on a type other than JSON array; + @throw type_error (306) when called on a type other than JSON array; example: `"cannot use erase() with null"` @throw std::out_of_range when `idx >= size()`; example: `"array index 17 is out of range"` @@ -4236,7 +4363,7 @@ } else { - throw std::domain_error("cannot use erase() with " + type_name()); + throw type_error(306, "cannot use erase() with " + type_name()); } } @@ -4934,7 +5061,7 @@ @param[in] val the value to add to the JSON array - @throw std::domain_error when called on a type other than JSON array or + @throw type_error (307) when called on a type other than JSON array or null; example: `"cannot use push_back() with number"` @complexity Amortized constant. @@ -4950,7 +5077,7 @@ // push_back only works for null objects or arrays if (not(is_null() or is_array())) { - throw std::domain_error("cannot use push_back() with " + type_name()); + throw type_error(307, "cannot use push_back() with " + type_name()); } // transform null object into an array @@ -4986,7 +5113,7 @@ // push_back only works for null objects or arrays if (not(is_null() or is_array())) { - throw std::domain_error("cannot use push_back() with " + type_name()); + throw type_error(307, "cannot use push_back() with " + type_name()); } // transform null object into an array @@ -5020,7 +5147,7 @@ @param[in] val the value to add to the JSON object - @throw std::domain_error when called on a type other than JSON object or + @throw type_error (307) when called on a type other than JSON object or null; example: `"cannot use push_back() with number"` @complexity Logarithmic in the size of the container, O(log(`size()`)). @@ -5036,7 +5163,7 @@ // push_back only works for null objects or objects if (not(is_null() or is_object())) { - throw std::domain_error("cannot use push_back() with " + type_name()); + throw type_error(307, "cannot use push_back() with " + type_name()); } // transform null object into an object @@ -5119,10 +5246,10 @@ @param[in] val element to insert @return iterator pointing to the inserted @a val. - @throw std::domain_error if called on JSON values other than arrays; + @throw type_error (309) if called on JSON values other than arrays; example: `"cannot use insert() with string"` - @throw std::domain_error if @a pos is not an iterator of *this; example: - `"iterator does not fit current value"` + @throw invalid_iterator (103) if @a pos is not an iterator of *this; + example: `"iterator does not fit current value"` @complexity Constant plus linear in the distance between pos and end of the container. @@ -5139,7 +5266,7 @@ // check if iterator pos fits to this JSON value if (pos.m_object != this) { - throw std::domain_error("iterator does not fit current value"); + throw invalid_iterator(103, "iterator does not fit current value"); } // insert to array and return iterator @@ -5149,7 +5276,7 @@ } else { - throw std::domain_error("cannot use insert() with " + type_name()); + throw type_error(309, "cannot use insert() with " + type_name()); } } @@ -5174,10 +5301,10 @@ @return iterator pointing to the first element inserted, or @a pos if `cnt==0` - @throw std::domain_error if called on JSON values other than arrays; + @throw type_error (309) if called on JSON values other than arrays; example: `"cannot use insert() with string"` - @throw std::domain_error if @a pos is not an iterator of *this; example: - `"iterator does not fit current value"` + @throw invalid_iterator (103) if @a pos is not an iterator of *this; + example: `"iterator does not fit current value"` @complexity Linear in @a cnt plus linear in the distance between @a pos and end of the container. @@ -5194,7 +5321,7 @@ // check if iterator pos fits to this JSON value if (pos.m_object != this) { - throw std::domain_error("iterator does not fit current value"); + throw invalid_iterator(103, "iterator does not fit current value"); } // insert to array and return iterator @@ -5204,7 +5331,7 @@ } else { - throw std::domain_error("cannot use insert() with " + type_name()); + throw type_error(309, "cannot use insert() with " + type_name()); } } @@ -5218,13 +5345,13 @@ @param[in] first begin of the range of elements to insert @param[in] last end of the range of elements to insert - @throw std::domain_error if called on JSON values other than arrays; + @throw type_error (309) if called on JSON values other than arrays; example: `"cannot use insert() with string"` - @throw std::domain_error if @a pos is not an iterator of *this; example: - `"iterator does not fit current value"` - @throw std::domain_error if @a first and @a last do not belong to the same - JSON value; example: `"iterators do not fit"` - @throw std::domain_error if @a first or @a last are iterators into + @throw invalid_iterator (103) if @a pos is not an iterator of *this; + example: `"iterator does not fit current value"` + @throw invalid_iterator (110) if @a first and @a last do not belong to the + same JSON value; example: `"iterators do not fit"` + @throw invalid_iterator (111) if @a first or @a last are iterators into container for which insert is called; example: `"passed iterators may not belong to container"` @@ -5243,24 +5370,25 @@ // insert only works for arrays if (not is_array()) { - throw std::domain_error("cannot use insert() with " + type_name()); + throw type_error(309, "cannot use insert() with " + type_name()); } // check if iterator pos fits to this JSON value if (pos.m_object != this) { - throw std::domain_error("iterator does not fit current value"); + throw invalid_iterator(103, "iterator does not fit current value"); } // check if range iterators belong to the same JSON object if (first.m_object != last.m_object) { - throw std::domain_error("iterators do not fit"); + throw invalid_iterator(110, "iterators do not fit"); } + // first and last iterator must not belong to this container if (first.m_object == this or last.m_object == this) { - throw std::domain_error("passed iterators may not belong to container"); + throw invalid_iterator(111, "passed iterators may not belong to container"); } // insert to array and return iterator @@ -5281,10 +5409,10 @@ the end() iterator @param[in] ilist initializer list to insert the values from - @throw std::domain_error if called on JSON values other than arrays; + @throw type_error (309) if called on JSON values other than arrays; example: `"cannot use insert() with string"` - @throw std::domain_error if @a pos is not an iterator of *this; example: - `"iterator does not fit current value"` + @throw invalid_iterator (103) if @a pos is not an iterator of *this; + example: `"iterator does not fit current value"` @return iterator pointing to the first element inserted, or @a pos if `ilist` is empty @@ -5301,13 +5429,13 @@ // insert only works for arrays if (not is_array()) { - throw std::domain_error("cannot use insert() with " + type_name()); + throw type_error(309, "cannot use insert() with " + type_name()); } // check if iterator pos fits to this JSON value if (pos.m_object != this) { - throw std::domain_error("iterator does not fit current value"); + throw invalid_iterator(103, "iterator does not fit current value"); } // insert to array and return iterator @@ -5355,8 +5483,8 @@ @param[in,out] other array to exchange the contents with - @throw std::domain_error when JSON value is not an array; example: `"cannot - use swap() with string"` + @throw type_error (308) when JSON value is not an array; example: + `"cannot use swap() with string"` @complexity Constant. @@ -5374,7 +5502,7 @@ } else { - throw std::domain_error("cannot use swap() with " + type_name()); + throw type_error(308, "cannot use swap() with " + type_name()); } } @@ -5388,7 +5516,7 @@ @param[in,out] other object to exchange the contents with - @throw std::domain_error when JSON value is not an object; example: + @throw type_error (308) when JSON value is not an object; example: `"cannot use swap() with string"` @complexity Constant. @@ -5407,7 +5535,7 @@ } else { - throw std::domain_error("cannot use swap() with " + type_name()); + throw type_error(308, "cannot use swap() with " + type_name()); } } @@ -5421,7 +5549,7 @@ @param[in,out] other string to exchange the contents with - @throw std::domain_error when JSON value is not a string; example: `"cannot + @throw type_error (308) when JSON value is not a string; example: `"cannot use swap() with boolean"` @complexity Constant. @@ -5440,7 +5568,7 @@ } else { - throw std::domain_error("cannot use swap() with " + type_name()); + throw type_error(308, "cannot use swap() with " + type_name()); } } @@ -5932,6 +6060,8 @@ @return result of the deserialization + @throw parse_error (2xx) in case of parse errors + @complexity Linear in the length of the input. The parser is a predictive LL(1) parser. The complexity can be higher if the parser callback function @a cb has a super-linear complexity. @@ -5960,6 +6090,8 @@ which is used to control the deserialization by filtering unwanted values (optional) + @throw parse_error (2xx) in case of parse errors + @return result of the deserialization @complexity Linear in the length of the input. The parser is a predictive @@ -5999,7 +6131,7 @@ @param[in,out] i input stream to read a serialized JSON value from @param[in,out] j JSON value to write the deserialized input to - @throw std::invalid_argument in case of parse errors + @throw parse_error (2xx) in case of parse errors @complexity Linear in the length of the input. The parser is a predictive LL(1) parser. @@ -6807,7 +6939,7 @@ case basic_json::value_t::null: { - throw std::out_of_range("cannot get value"); + throw invalid_iterator(114, "cannot get value"); } default: @@ -6818,7 +6950,7 @@ } else { - throw std::out_of_range("cannot get value"); + throw invalid_iterator(114, "cannot get value"); } } } @@ -6854,7 +6986,7 @@ } else { - throw std::out_of_range("cannot get value"); + throw invalid_iterator(114, "cannot get value"); } } } @@ -6955,7 +7087,7 @@ // if objects are not the same, the comparison is undefined if (m_object != other.m_object) { - throw std::domain_error("cannot compare iterators of different containers"); + throw invalid_iterator(112, "cannot compare iterators of different containers"); } assert(m_object != nullptr); @@ -6997,7 +7129,7 @@ // if objects are not the same, the comparison is undefined if (m_object != other.m_object) { - throw std::domain_error("cannot compare iterators of different containers"); + throw invalid_iterator(112, "cannot compare iterators of different containers"); } assert(m_object != nullptr); @@ -7006,7 +7138,7 @@ { case basic_json::value_t::object: { - throw std::domain_error("cannot compare order of object iterators"); + throw invalid_iterator(113, "cannot compare order of object iterators"); } case basic_json::value_t::array: @@ -7060,7 +7192,7 @@ { case basic_json::value_t::object: { - throw std::domain_error("cannot use offsets with object iterators"); + throw invalid_iterator(109, "cannot use offsets with object iterators"); } case basic_json::value_t::array: @@ -7122,7 +7254,7 @@ { case basic_json::value_t::object: { - throw std::domain_error("cannot use offsets with object iterators"); + throw invalid_iterator(109, "cannot use offsets with object iterators"); } case basic_json::value_t::array: @@ -7149,7 +7281,7 @@ { case basic_json::value_t::object: { - throw std::domain_error("cannot use operator[] for object iterators"); + throw invalid_iterator(108, "cannot use operator[] for object iterators"); } case basic_json::value_t::array: @@ -7159,7 +7291,7 @@ case basic_json::value_t::null: { - throw std::out_of_range("cannot get value"); + throw invalid_iterator(114, "cannot get value"); } default: @@ -7170,7 +7302,7 @@ } else { - throw std::out_of_range("cannot get value"); + throw invalid_iterator(114, "cannot get value"); } } } @@ -7190,7 +7322,7 @@ } else { - throw std::domain_error("cannot use key() for non-object iterators"); + throw invalid_iterator(107, "cannot use key() for non-object iterators"); } } @@ -7501,7 +7633,7 @@ { m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str()); assert(m_content != nullptr); - m_start = m_cursor = m_content; + m_buffer_start = m_start = m_cursor = m_content; m_limit = m_content + s.size(); } @@ -7513,7 +7645,7 @@ std::getline(*m_stream, m_buffer); m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str()); assert(m_content != nullptr); - m_start = m_cursor = m_content; + m_buffer_start = m_start = m_cursor = m_content; m_limit = m_content + m_buffer.size(); } @@ -7538,17 +7670,17 @@ @return string representation of the code point; the length of the result string is between 1 and 4 characters. - @throw std::out_of_range if code point is > 0x10ffff; example: `"code + @throw parse_error (203) if code point is > 0x10ffff; example: `"code points above 0x10FFFF are invalid"` - @throw std::invalid_argument if the low surrogate is invalid; example: - `""missing or wrong low surrogate""` + @throw parse_error (202) if the low surrogate is invalid; example: + `"missing or wrong low surrogate"` @complexity Constant. @see <http://en.wikipedia.org/wiki/UTF-8#Sample_code> */ - static string_t to_unicode(const std::size_t codepoint1, - const std::size_t codepoint2 = 0) + string_t to_unicode(const std::size_t codepoint1, + const std::size_t codepoint2 = 0) const { // calculate the code point from the given code points std::size_t codepoint = codepoint1; @@ -7571,7 +7703,8 @@ } else { - throw std::invalid_argument("missing or wrong low surrogate"); + const std::string error_msg = error_message() + "; missing or wrong low surrogate"; + throw parse_error(202, error_msg); } } @@ -7605,7 +7738,8 @@ } else { - throw std::out_of_range("code points above 0x10FFFF are invalid"); + const std::string error_msg = error_message() + "; code points above 0x10FFFF are invalid"; + throw parse_error(203, error_msg); } return result; @@ -7755,7 +7889,8 @@ /// append data from the stream to the internal buffer void yyfill() noexcept { - if (m_stream == nullptr or not * m_stream) + // yyfill has no effect if we do not have a ready stream + if (m_stream == nullptr or m_stream->fail()) { return; } @@ -7764,20 +7899,56 @@ const auto offset_marker = m_marker - m_start; const auto offset_cursor = m_cursor - m_start; - m_buffer.erase(0, static_cast<size_t>(offset_start)); + // get the size of the previous buffer + const auto last_buffer_size = static_cast<size_t>(offset_start); + // remmeber all buffer sizes so far + m_previous_buffer_sizes += last_buffer_size; + + // delete previous buffer + m_buffer.erase(0, last_buffer_size); + + // read line from stream to buffer std::string line; assert(m_stream != nullptr); std::getline(*m_stream, line); m_buffer += "\n" + line; // add line with newline symbol + // set the pointers accordingly m_content = reinterpret_cast<const lexer_char_t*>(m_buffer.c_str()); assert(m_content != nullptr); - m_start = m_content; + m_buffer_start = m_start = m_content; m_marker = m_start + offset_marker; m_cursor = m_start + offset_cursor; m_limit = m_start + m_buffer.size() - 1; } + /// return the location of the end of the last token + size_t last_token_location() const noexcept + { + // m_buffer_start points to the first byte of the current buffer + // m_cursor points to the byte behind the current token + // m_previous_buffer_sizes contains the size the previous buffers + return static_cast<size_t>(m_cursor - m_buffer_start) + m_previous_buffer_sizes; + } + + /// returns an error message for parse errors + std::string error_message() const + { + const std::string last_token(reinterpret_cast<typename std::string::const_pointer>(m_start), + static_cast<size_t>(m_cursor - m_start)); + std::string result = "parse error: unexpected "; + if (last_token_type == token_type::end_of_input) + { + result += token_type_name(token_type::end_of_input); + } + else + { + result += "'" + last_token + "'"; + } + result += " at byte " + std::to_string(last_token_location() - last_token.size() + 1); + return result; + } + /// return string representation of last read token string_t get_token_string() const { @@ -7841,7 +8012,9 @@ @return string value of current token without opening and closing quotes - @throw std::out_of_range if to_unicode fails + + @throw parse_error (202,203) if to_unicode fails + @throw parse_error (204) if low surrogate is missing */ string_t get_string() const { @@ -7916,7 +8089,8 @@ // make sure there is a subsequent unicode if ((i + 6 >= m_limit) or * (i + 5) != '\\' or * (i + 6) != 'u') { - throw std::invalid_argument("missing low surrogate"); + std::string error_msg = error_message() + "; missing low surrogate"; + throw parse_error(204, error_msg); } // get code yyyy from uxxxx\uyyyy @@ -8129,6 +8303,10 @@ const lexer_char_t* m_cursor = nullptr; /// pointer to the end of the buffer const lexer_char_t* m_limit = nullptr; + /// pointer to the beginning of the buffer + const lexer_char_t* m_buffer_start = nullptr; + /// the size of the last buffer (before yyfill was called) + size_t m_previous_buffer_sizes = 0; /// the last token type token_type last_token_type = token_type::end_of_input; }; @@ -8374,12 +8552,9 @@ { if (t != last_token) { - std::string error_msg = "parse error - unexpected "; - error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token_string() + - "'") : - lexer::token_type_name(last_token)); + std::string error_msg = m_lexer.error_message(); error_msg += "; expected " + lexer::token_type_name(t); - throw std::invalid_argument(error_msg); + throw parse_error(201, error_msg); } } @@ -8387,11 +8562,9 @@ { if (t == last_token) { - std::string error_msg = "parse error - unexpected "; - error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token_string() + - "'") : - lexer::token_type_name(last_token)); - throw std::invalid_argument(error_msg); + std::string error_msg = m_lexer.error_message(); + error_msg += "; expected JSON value"; + throw parse_error(201, error_msg); } } @@ -8434,10 +8607,10 @@ empty string is assumed which references the whole JSON value - @throw std::domain_error if reference token is nonempty and does not - begin with a slash (`/`); example: `"JSON pointer must be empty or + @throw extension_error (403) if reference token is nonempty and does + not begin with a slash (`/`); example: `"JSON pointer must be empty or begin with /"` - @throw std::domain_error if a tilde (`~`) is not followed by `0` + @throw extension_error (404) if a tilde (`~`) is not followed by `0` (representing `~`) or `1` (representing `/`); example: `"escape error: ~ must be followed with 0 or 1"` @@ -8487,7 +8660,7 @@ { if (is_root()) { - throw std::domain_error("JSON pointer has no parent"); + throw extension_error(401, "JSON pointer has no parent"); } auto last = reference_tokens.back(); @@ -8505,7 +8678,7 @@ { if (is_root()) { - throw std::domain_error("JSON pointer has no parent"); + throw extension_error(401, "JSON pointer has no parent"); } json_pointer result = *this; @@ -8566,7 +8739,7 @@ */ default: { - throw std::domain_error("invalid value to unflatten"); + throw extension_error(411, "invalid value to unflatten"); } } } @@ -8584,8 +8757,10 @@ @complexity Linear in the length of the JSON pointer. @throw std::out_of_range if the JSON pointer can not be resolved - @throw std::domain_error if an array index begins with '0' - @throw std::invalid_argument if an array index was not a number + @throw extension_error (402) if an array index begins with '0' or is + not a number + @throw extension_error (405) if the reference token could not be + resolved */ reference get_unchecked(pointer ptr) const { @@ -8605,7 +8780,7 @@ // error condition (cf. RFC 6901, Sect. 4) if (reference_token.size() > 1 and reference_token[0] == '0') { - throw std::domain_error("array index must not begin with '0'"); + throw extension_error(402, "array index must not begin with '0'"); } if (reference_token == "-") @@ -8616,14 +8791,24 @@ else { // convert array index to number; unchecked access - ptr = &ptr->operator[](static_cast<size_type>(std::stoi(reference_token))); + try + { + ptr = &ptr->operator[](static_cast<size_type>(std::stoi(reference_token))); + } + catch (std::invalid_argument&) + { + // std::stoi throws std::invalid_argument if + // no conversion could be performed; we catch + // it for better diagnosis + throw extension_error(402, "array index is '" + reference_token + "', but must be a number"); + } } break; } default: { - throw std::out_of_range("unresolved reference token '" + reference_token + "'"); + throw extension_error(405, "unresolved reference token '" + reference_token + "'"); } } } @@ -8649,15 +8834,15 @@ if (reference_token == "-") { // "-" always fails the range check - throw std::out_of_range("array index '-' (" + - std::to_string(ptr->m_value.array->size()) + - ") is out of range"); + throw extension_error(406, "array index '-' (" + + std::to_string(ptr->m_value.array->size()) + + ") is out of range"); } // error condition (cf. RFC 6901, Sect. 4) if (reference_token.size() > 1 and reference_token[0] == '0') { - throw std::domain_error("array index must not begin with '0'"); + throw extension_error(402, "array index must not begin with '0'"); } // note: at performs range check @@ -8667,7 +8852,7 @@ default: { - throw std::out_of_range("unresolved reference token '" + reference_token + "'"); + throw extension_error(405, "unresolved reference token '" + reference_token + "'"); } } } @@ -8701,15 +8886,15 @@ if (reference_token == "-") { // "-" cannot be used for const access - throw std::out_of_range("array index '-' (" + - std::to_string(ptr->m_value.array->size()) + - ") is out of range"); + throw extension_error(406, "array index '-' (" + + std::to_string(ptr->m_value.array->size()) + + ") is out of range"); } // error condition (cf. RFC 6901, Sect. 4) if (reference_token.size() > 1 and reference_token[0] == '0') { - throw std::domain_error("array index must not begin with '0'"); + throw extension_error(402, "array index must not begin with '0'"); } // use unchecked array access @@ -8719,7 +8904,7 @@ default: { - throw std::out_of_range("unresolved reference token '" + reference_token + "'"); + throw extension_error(405, "unresolved reference token '" + reference_token + "'"); } } } @@ -8745,15 +8930,15 @@ if (reference_token == "-") { // "-" always fails the range check - throw std::out_of_range("array index '-' (" + - std::to_string(ptr->m_value.array->size()) + - ") is out of range"); + throw extension_error(406, "array index '-' (" + + std::to_string(ptr->m_value.array->size()) + + ") is out of range"); } // error condition (cf. RFC 6901, Sect. 4) if (reference_token.size() > 1 and reference_token[0] == '0') { - throw std::domain_error("array index must not begin with '0'"); + throw extension_error(402, "array index must not begin with '0'"); } // note: at performs range check @@ -8763,7 +8948,7 @@ default: { - throw std::out_of_range("unresolved reference token '" + reference_token + "'"); + throw extension_error(405, "unresolved reference token '" + reference_token + "'"); } } } @@ -8785,7 +8970,7 @@ // check if nonempty reference string begins with slash if (reference_string[0] != '/') { - throw std::domain_error("JSON pointer must be empty or begin with '/'"); + throw extension_error(403, "JSON pointer must be empty or begin with '/'"); } // extract the reference tokens: @@ -8820,13 +9005,13 @@ (reference_token[pos + 1] != '0' and reference_token[pos + 1] != '1')) { - throw std::domain_error("escape error: '~' must be followed with '0' or '1'"); + throw extension_error(404, "escape error: '~' must be followed with '0' or '1'"); } } // finally, store the reference token unescape(reference_token); - result.push_back(reference_token); + result.emplace_back(reference_token); } return result; @@ -8948,7 +9133,7 @@ { if (not value.is_object()) { - throw std::domain_error("only objects can be unflattened"); + throw extension_error(412, "only objects can be unflattened"); } basic_json result; @@ -8958,7 +9143,7 @@ { if (not element.second.is_primitive()) { - throw std::domain_error("values in object must be primitive"); + throw extension_error(413, "values in object must be primitive"); } // assign value to reference pointed to by JSON pointer; Note @@ -9010,8 +9195,8 @@ @complexity Constant. @throw std::out_of_range if the JSON pointer can not be resolved - @throw std::domain_error if an array index begins with '0' - @throw std::invalid_argument if an array index was not a number + @throw extension_error (402) if an array index begins with '0' or is not + a number @liveexample{The behavior is shown in the example.,operatorjson_pointer} @@ -9037,8 +9222,8 @@ @complexity Constant. @throw std::out_of_range if the JSON pointer can not be resolved - @throw std::domain_error if an array index begins with '0' - @throw std::invalid_argument if an array index was not a number + @throw extension_error (402) if an array index begins with '0' or is not + a number @liveexample{The behavior is shown in the example.,operatorjson_pointer_const} @@ -9062,8 +9247,8 @@ @complexity Constant. @throw std::out_of_range if the JSON pointer can not be resolved - @throw std::domain_error if an array index begins with '0' - @throw std::invalid_argument if an array index was not a number + @throw extension_error (402) if an array index begins with '0' or is not + a number @liveexample{The behavior is shown in the example.,at_json_pointer} @@ -9087,8 +9272,8 @@ @complexity Constant. @throw std::out_of_range if the JSON pointer can not be resolved - @throw std::domain_error if an array index begins with '0' - @throw std::invalid_argument if an array index was not a number + @throw extension_error (402) if an array index begins with '0' or is not + a number @liveexample{The behavior is shown in the example.,at_json_pointer_const} @@ -9188,8 +9373,11 @@ @throw std::out_of_range if a JSON pointer inside the patch could not be resolved successfully in the current JSON value; example: `"key baz not found"` - @throw invalid_argument if the JSON patch is malformed (e.g., mandatory - attributes are missing); example: `"operation add must have member path"` + @throw extension_error (408) if the JSON patch is malformed (e.g., + mandatory attributes are missing); example: `"operation add must have + string member path"` + @throw extension_error (407) if the JSON patch is malformed; example: + `"JSON patch must be an array of objects"` @complexity Linear in the size of the JSON value and the length of the JSON patch. As usually only a fraction of the JSON value is affected by @@ -9287,7 +9475,7 @@ if (static_cast<size_type>(idx) > parent.size()) { // avoid undefined behavior - throw std::out_of_range("array index " + std::to_string(idx) + " is out of range"); + throw extension_error(406, "array index " + std::to_string(idx) + " is out of range"); } else { @@ -9339,7 +9527,7 @@ if (not json_patch.is_array()) { // a JSON patch must be an array of objects - throw std::invalid_argument("JSON patch must be an array of objects"); + throw extension_error(407, "JSON patch must be an array of objects"); } // iterate and apply th eoperations @@ -9359,13 +9547,13 @@ // check if desired value is present if (it == val.m_value.object->end()) { - throw std::invalid_argument(error_msg + " must have member '" + member + "'"); + throw extension_error(408, error_msg + " must have string member '" + member + "'"); } // check if result is of type string if (string_type and not it->second.is_string()) { - throw std::invalid_argument(error_msg + " must have string member '" + member + "'"); + throw extension_error(408, error_msg + " must have string member '" + member + "'"); } // no error: return value @@ -9375,7 +9563,7 @@ // type check if (not val.is_object()) { - throw std::invalid_argument("JSON patch must be an array of objects"); + throw extension_error(407, "JSON patch must be an array of objects"); } // collect mandatory members @@ -9448,7 +9636,7 @@ // throw an exception if test fails if (not success) { - throw std::domain_error("unsuccessful: " + val.dump()); + throw extension_error(410, "unsuccessful: " + val.dump()); } break; @@ -9458,7 +9646,7 @@ { // op must be "add", "remove", "replace", "move", "copy", or // "test" - throw std::invalid_argument("operation value '" + op + "' is invalid"); + throw extension_error(409, "operation value '" + op + "' is invalid"); } } }
diff --git a/test/data/json.org/1.json b/test/data/json.org/1.json index eacfbf5..c8f1d8c 100644 --- a/test/data/json.org/1.json +++ b/test/data/json.org/1.json
@@ -1,20 +1,20 @@ { "glossary": { "title": "example glossary", - "GlossDiv": { + "GlossDiv": { "title": "S", - "GlossList": { + "GlossList": { "GlossEntry": { "ID": "SGML", - "SortAs": "SGML", - "GlossTerm": "Standard Generalized Markup Language", - "Acronym": "SGML", - "Abbrev": "ISO 8879:1986", - "GlossDef": { + "SortAs": "SGML", + "GlossTerm": "Standard Generalized Markup Language", + "Acronym": "SGML", + "Abbrev": "ISO 8879:1986", + "GlossDef": { "para": "A meta-markup language, used to create markup languages such as DocBook.", - "GlossSeeAlso": ["GML", "XML"] + "GlossSeeAlso": ["GML", "XML"] }, - "GlossSee": "markup" + "GlossSee": "markup" } } }
diff --git a/test/src/fuzz.cpp b/test/src/fuzz.cpp index de8ad42..f40059d 100644 --- a/test/src/fuzz.cpp +++ b/test/src/fuzz.cpp
@@ -24,7 +24,7 @@ json j(std::cin); std::cout << j << std::endl; } - catch (std::invalid_argument& e) + catch (json::parse_error& e) { std::cout << "Invalid argument in parsing" << e.what() << '\n'; }
diff --git a/test/src/unit.cpp b/test/src/unit.cpp index 79a4bb0..75f689f 100644 --- a/test/src/unit.cpp +++ b/test/src/unit.cpp
@@ -944,9 +944,9 @@ SECTION("object with error") { CHECK_THROWS_AS(json::object({ {"one", 1}, {"two", 1u}, {"three", 2.2}, {"four", false}, 13 }), - std::logic_error); + json::type_error); CHECK_THROWS_WITH(json::object({ {"one", 1}, {"two", 1u}, {"three", 2.2}, {"four", false}, 13 }), - "cannot create object from initializer list"); + "[except.301] cannot create object from initializer list"); } SECTION("empty array") @@ -1018,18 +1018,22 @@ { json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}, {"d", false}, {"e", true}}; json jobject2 = {{"a", "a"}, {"b", 1}, {"c", 17u}}; - CHECK_THROWS_AS(json(jobject.begin(), jobject2.end()), std::domain_error); - CHECK_THROWS_AS(json(jobject2.begin(), jobject.end()), std::domain_error); - CHECK_THROWS_WITH(json(jobject.begin(), jobject2.end()), "iterators are not compatible"); - CHECK_THROWS_WITH(json(jobject2.begin(), jobject.end()), "iterators are not compatible"); + CHECK_THROWS_AS(json(jobject.begin(), jobject2.end()), json::invalid_iterator); + CHECK_THROWS_AS(json(jobject2.begin(), jobject.end()), json::invalid_iterator); + CHECK_THROWS_WITH(json(jobject.begin(), jobject2.end()), + "[except.101] iterators are not compatible"); + CHECK_THROWS_WITH(json(jobject2.begin(), jobject.end()), + "[except.101] iterators are not compatible"); } { json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}, {"d", false}, {"e", true}}; json jobject2 = {{"a", "a"}, {"b", 1}, {"c", 17u}}; - CHECK_THROWS_AS(json(jobject.cbegin(), jobject2.cend()), std::domain_error); - CHECK_THROWS_AS(json(jobject2.cbegin(), jobject.cend()), std::domain_error); - CHECK_THROWS_WITH(json(jobject.cbegin(), jobject2.cend()), "iterators are not compatible"); - CHECK_THROWS_WITH(json(jobject2.cbegin(), jobject.cend()), "iterators are not compatible"); + CHECK_THROWS_AS(json(jobject.cbegin(), jobject2.cend()), json::invalid_iterator); + CHECK_THROWS_AS(json(jobject2.cbegin(), jobject.cend()), json::invalid_iterator); + CHECK_THROWS_WITH(json(jobject.cbegin(), jobject2.cend()), + "[except.101] iterators are not compatible"); + CHECK_THROWS_WITH(json(jobject2.cbegin(), jobject.cend()), + "[except.101] iterators are not compatible"); } } } @@ -1083,18 +1087,20 @@ { json jarray = {1, 2, 3, 4}; json jarray2 = {2, 3, 4, 5}; - CHECK_THROWS_AS(json(jarray.begin(), jarray2.end()), std::domain_error); - CHECK_THROWS_AS(json(jarray2.begin(), jarray.end()), std::domain_error); - CHECK_THROWS_WITH(json(jarray.begin(), jarray2.end()), "iterators are not compatible"); - CHECK_THROWS_WITH(json(jarray2.begin(), jarray.end()), "iterators are not compatible"); + CHECK_THROWS_AS(json(jarray.begin(), jarray2.end()), json::invalid_iterator); + CHECK_THROWS_AS(json(jarray2.begin(), jarray.end()), json::invalid_iterator); + CHECK_THROWS_WITH(json(jarray.begin(), jarray2.end()), "[except.101] iterators are not compatible"); + CHECK_THROWS_WITH(json(jarray2.begin(), jarray.end()), "[except.101] iterators are not compatible"); } { json jarray = {1, 2, 3, 4}; json jarray2 = {2, 3, 4, 5}; - CHECK_THROWS_AS(json(jarray.cbegin(), jarray2.cend()), std::domain_error); - CHECK_THROWS_AS(json(jarray2.cbegin(), jarray.cend()), std::domain_error); - CHECK_THROWS_WITH(json(jarray.cbegin(), jarray2.cend()), "iterators are not compatible"); - CHECK_THROWS_WITH(json(jarray2.cbegin(), jarray.cend()), "iterators are not compatible"); + CHECK_THROWS_AS(json(jarray.cbegin(), jarray2.cend()), json::invalid_iterator); + CHECK_THROWS_AS(json(jarray2.cbegin(), jarray.cend()), json::invalid_iterator); + CHECK_THROWS_WITH(json(jarray.cbegin(), jarray2.cend()), + "[except.101] iterators are not compatible"); + CHECK_THROWS_WITH(json(jarray2.cbegin(), jarray.cend()), + "[except.101] iterators are not compatible"); } } } @@ -1107,13 +1113,15 @@ { { json j; - CHECK_THROWS_AS(json(j.begin(), j.end()), std::domain_error); - CHECK_THROWS_WITH(json(j.begin(), j.end()), "cannot use construct with iterators from null"); + CHECK_THROWS_AS(json(j.begin(), j.end()), json::invalid_iterator); + CHECK_THROWS_WITH(json(j.begin(), j.end()), + "[except.106] cannot use construct with iterators from null"); } { json j; - CHECK_THROWS_AS(json(j.cbegin(), j.cend()), std::domain_error); - CHECK_THROWS_WITH(json(j.cbegin(), j.cend()), "cannot use construct with iterators from null"); + CHECK_THROWS_AS(json(j.cbegin(), j.cend()), json::invalid_iterator); + CHECK_THROWS_WITH(json(j.cbegin(), j.cend()), + "[except.106] cannot use construct with iterators from null"); } } @@ -1194,17 +1202,17 @@ { { json j = "foo"; - CHECK_THROWS_AS(json(j.end(), j.end()), std::out_of_range); - CHECK_THROWS_AS(json(j.begin(), j.begin()), std::out_of_range); - CHECK_THROWS_WITH(json(j.end(), j.end()), "iterators out of range"); - CHECK_THROWS_WITH(json(j.begin(), j.begin()), "iterators out of range"); + CHECK_THROWS_AS(json(j.end(), j.end()), json::invalid_iterator); + CHECK_THROWS_AS(json(j.begin(), j.begin()), json::invalid_iterator); + CHECK_THROWS_WITH(json(j.end(), j.end()), "[except.104] iterators out of range"); + CHECK_THROWS_WITH(json(j.begin(), j.begin()), "[except.104] iterators out of range"); } { json j = "bar"; - CHECK_THROWS_AS(json(j.cend(), j.cend()), std::out_of_range); - CHECK_THROWS_AS(json(j.cbegin(), j.cbegin()), std::out_of_range); - CHECK_THROWS_WITH(json(j.cend(), j.cend()), "iterators out of range"); - CHECK_THROWS_WITH(json(j.cbegin(), j.cbegin()), "iterators out of range"); + CHECK_THROWS_AS(json(j.cend(), j.cend()), json::invalid_iterator); + CHECK_THROWS_AS(json(j.cbegin(), j.cbegin()), json::invalid_iterator); + CHECK_THROWS_WITH(json(j.cend(), j.cend()), "[except.104] iterators out of range"); + CHECK_THROWS_WITH(json(j.cbegin(), j.cbegin()), "[except.104] iterators out of range"); } } @@ -1212,17 +1220,17 @@ { { json j = false; - CHECK_THROWS_AS(json(j.end(), j.end()), std::out_of_range); - CHECK_THROWS_AS(json(j.begin(), j.begin()), std::out_of_range); - CHECK_THROWS_WITH(json(j.end(), j.end()), "iterators out of range"); - CHECK_THROWS_WITH(json(j.begin(), j.begin()), "iterators out of range"); + CHECK_THROWS_AS(json(j.end(), j.end()), json::invalid_iterator); + CHECK_THROWS_AS(json(j.begin(), j.begin()), json::invalid_iterator); + CHECK_THROWS_WITH(json(j.end(), j.end()), "[except.104] iterators out of range"); + CHECK_THROWS_WITH(json(j.begin(), j.begin()), "[except.104] iterators out of range"); } { json j = true; - CHECK_THROWS_AS(json(j.cend(), j.cend()), std::out_of_range); - CHECK_THROWS_AS(json(j.cbegin(), j.cbegin()), std::out_of_range); - CHECK_THROWS_WITH(json(j.cend(), j.cend()), "iterators out of range"); - CHECK_THROWS_WITH(json(j.cbegin(), j.cbegin()), "iterators out of range"); + CHECK_THROWS_AS(json(j.cend(), j.cend()), json::invalid_iterator); + CHECK_THROWS_AS(json(j.cbegin(), j.cbegin()), json::invalid_iterator); + CHECK_THROWS_WITH(json(j.cend(), j.cend()), "[except.104] iterators out of range"); + CHECK_THROWS_WITH(json(j.cbegin(), j.cbegin()), "[except.104] iterators out of range"); } } @@ -1230,17 +1238,17 @@ { { json j = 17; - CHECK_THROWS_AS(json(j.end(), j.end()), std::out_of_range); - CHECK_THROWS_AS(json(j.begin(), j.begin()), std::out_of_range); - CHECK_THROWS_WITH(json(j.end(), j.end()), "iterators out of range"); - CHECK_THROWS_WITH(json(j.begin(), j.begin()), "iterators out of range"); + CHECK_THROWS_AS(json(j.end(), j.end()), json::invalid_iterator); + CHECK_THROWS_AS(json(j.begin(), j.begin()), json::invalid_iterator); + CHECK_THROWS_WITH(json(j.end(), j.end()), "[except.104] iterators out of range"); + CHECK_THROWS_WITH(json(j.begin(), j.begin()), "[except.104] iterators out of range"); } { json j = 17; - CHECK_THROWS_AS(json(j.cend(), j.cend()), std::out_of_range); - CHECK_THROWS_AS(json(j.cbegin(), j.cbegin()), std::out_of_range); - CHECK_THROWS_WITH(json(j.cend(), j.cend()), "iterators out of range"); - CHECK_THROWS_WITH(json(j.cbegin(), j.cbegin()), "iterators out of range"); + CHECK_THROWS_AS(json(j.cend(), j.cend()), json::invalid_iterator); + CHECK_THROWS_AS(json(j.cbegin(), j.cbegin()), json::invalid_iterator); + CHECK_THROWS_WITH(json(j.cend(), j.cend()), "[except.104] iterators out of range"); + CHECK_THROWS_WITH(json(j.cbegin(), j.cbegin()), "[except.104] iterators out of range"); } } @@ -1248,17 +1256,17 @@ { { json j = 17u; - CHECK_THROWS_AS(json(j.end(), j.end()), std::out_of_range); - CHECK_THROWS_AS(json(j.begin(), j.begin()), std::out_of_range); - CHECK_THROWS_WITH(json(j.end(), j.end()), "iterators out of range"); - CHECK_THROWS_WITH(json(j.begin(), j.begin()), "iterators out of range"); + CHECK_THROWS_AS(json(j.end(), j.end()), json::invalid_iterator); + CHECK_THROWS_AS(json(j.begin(), j.begin()), json::invalid_iterator); + CHECK_THROWS_WITH(json(j.end(), j.end()), "[except.104] iterators out of range"); + CHECK_THROWS_WITH(json(j.begin(), j.begin()), "[except.104] iterators out of range"); } { json j = 17u; - CHECK_THROWS_AS(json(j.cend(), j.cend()), std::out_of_range); - CHECK_THROWS_AS(json(j.cbegin(), j.cbegin()), std::out_of_range); - CHECK_THROWS_WITH(json(j.cend(), j.cend()), "iterators out of range"); - CHECK_THROWS_WITH(json(j.cbegin(), j.cbegin()), "iterators out of range"); + CHECK_THROWS_AS(json(j.cend(), j.cend()), json::invalid_iterator); + CHECK_THROWS_AS(json(j.cbegin(), j.cbegin()), json::invalid_iterator); + CHECK_THROWS_WITH(json(j.cend(), j.cend()), "[except.104] iterators out of range"); + CHECK_THROWS_WITH(json(j.cbegin(), j.cbegin()), "[except.104] iterators out of range"); } } @@ -1266,17 +1274,17 @@ { { json j = 23.42; - CHECK_THROWS_AS(json(j.end(), j.end()), std::out_of_range); - CHECK_THROWS_AS(json(j.begin(), j.begin()), std::out_of_range); - CHECK_THROWS_WITH(json(j.end(), j.end()), "iterators out of range"); - CHECK_THROWS_WITH(json(j.begin(), j.begin()), "iterators out of range"); + CHECK_THROWS_AS(json(j.end(), j.end()), json::invalid_iterator); + CHECK_THROWS_AS(json(j.begin(), j.begin()), json::invalid_iterator); + CHECK_THROWS_WITH(json(j.end(), j.end()), "[except.104] iterators out of range"); + CHECK_THROWS_WITH(json(j.begin(), j.begin()), "[except.104] iterators out of range"); } { json j = 23.42; - CHECK_THROWS_AS(json(j.cend(), j.cend()), std::out_of_range); - CHECK_THROWS_AS(json(j.cbegin(), j.cbegin()), std::out_of_range); - CHECK_THROWS_WITH(json(j.cend(), j.cend()), "iterators out of range"); - CHECK_THROWS_WITH(json(j.cbegin(), j.cbegin()), "iterators out of range"); + CHECK_THROWS_AS(json(j.cend(), j.cend()), json::invalid_iterator); + CHECK_THROWS_AS(json(j.cbegin(), j.cbegin()), json::invalid_iterator); + CHECK_THROWS_WITH(json(j.cend(), j.cend()), "[except.104] iterators out of range"); + CHECK_THROWS_WITH(json(j.cbegin(), j.cbegin()), "[except.104] iterators out of range"); } } } @@ -1491,6 +1499,7 @@ CHECK(not j.is_number()); CHECK(not j.is_number_integer()); CHECK(not j.is_number_unsigned()); + CHECK(not j.is_number_signed()); CHECK(not j.is_number_float()); CHECK(j.is_object()); CHECK(not j.is_array()); @@ -1508,6 +1517,7 @@ CHECK(not j.is_number()); CHECK(not j.is_number_integer()); CHECK(not j.is_number_unsigned()); + CHECK(not j.is_number_signed()); CHECK(not j.is_number_float()); CHECK(not j.is_object()); CHECK(j.is_array()); @@ -1525,6 +1535,7 @@ CHECK(not j.is_number()); CHECK(not j.is_number_integer()); CHECK(not j.is_number_unsigned()); + CHECK(not j.is_number_signed()); CHECK(not j.is_number_float()); CHECK(not j.is_object()); CHECK(not j.is_array()); @@ -1542,6 +1553,7 @@ CHECK(not j.is_number()); CHECK(not j.is_number_integer()); CHECK(not j.is_number_unsigned()); + CHECK(not j.is_number_signed()); CHECK(not j.is_number_float()); CHECK(not j.is_object()); CHECK(not j.is_array()); @@ -1559,6 +1571,7 @@ CHECK(not j.is_number()); CHECK(not j.is_number_integer()); CHECK(not j.is_number_unsigned()); + CHECK(not j.is_number_signed()); CHECK(not j.is_number_float()); CHECK(not j.is_object()); CHECK(not j.is_array()); @@ -1576,6 +1589,7 @@ CHECK(j.is_number()); CHECK(j.is_number_integer()); CHECK(not j.is_number_unsigned()); + CHECK(j.is_number_signed()); CHECK(not j.is_number_float()); CHECK(not j.is_object()); CHECK(not j.is_array()); @@ -1593,6 +1607,7 @@ CHECK(j.is_number()); CHECK(j.is_number_integer()); CHECK(j.is_number_unsigned()); + CHECK(not j.is_number_signed()); CHECK(not j.is_number_float()); CHECK(not j.is_object()); CHECK(not j.is_array()); @@ -1610,6 +1625,7 @@ CHECK(j.is_number()); CHECK(not j.is_number_integer()); CHECK(not j.is_number_unsigned()); + CHECK(not j.is_number_signed()); CHECK(j.is_number_float()); CHECK(not j.is_object()); CHECK(not j.is_array()); @@ -1627,6 +1643,7 @@ CHECK(not j.is_number()); CHECK(not j.is_number_integer()); CHECK(not j.is_number_unsigned()); + CHECK(not j.is_number_signed()); CHECK(not j.is_number_float()); CHECK(not j.is_object()); CHECK(not j.is_array()); @@ -1860,28 +1877,28 @@ SECTION("exception in case of a non-object type") { - CHECK_THROWS_AS(json(json::value_t::null).get<json::object_t>(), std::logic_error); - CHECK_THROWS_AS(json(json::value_t::array).get<json::object_t>(), std::logic_error); - CHECK_THROWS_AS(json(json::value_t::string).get<json::object_t>(), std::logic_error); - CHECK_THROWS_AS(json(json::value_t::boolean).get<json::object_t>(), std::logic_error); - CHECK_THROWS_AS(json(json::value_t::number_integer).get<json::object_t>(), std::logic_error); - CHECK_THROWS_AS(json(json::value_t::number_unsigned).get<json::object_t>(), std::logic_error); - CHECK_THROWS_AS(json(json::value_t::number_float).get<json::object_t>(), std::logic_error); + CHECK_THROWS_AS(json(json::value_t::null).get<json::object_t>(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::array).get<json::object_t>(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::string).get<json::object_t>(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::boolean).get<json::object_t>(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::number_integer).get<json::object_t>(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::number_unsigned).get<json::object_t>(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::number_float).get<json::object_t>(), json::type_error); CHECK_THROWS_WITH(json(json::value_t::null).get<json::object_t>(), - "type must be object, but is null"); + "[except.302] type must be object, but is null"); CHECK_THROWS_WITH(json(json::value_t::array).get<json::object_t>(), - "type must be object, but is array"); + "[except.302] type must be object, but is array"); CHECK_THROWS_WITH(json(json::value_t::string).get<json::object_t>(), - "type must be object, but is string"); + "[except.302] type must be object, but is string"); CHECK_THROWS_WITH(json(json::value_t::boolean).get<json::object_t>(), - "type must be object, but is boolean"); + "[except.302] type must be object, but is boolean"); CHECK_THROWS_WITH(json(json::value_t::number_integer).get<json::object_t>(), - "type must be object, but is number"); + "[except.302] type must be object, but is number"); CHECK_THROWS_WITH(json(json::value_t::number_unsigned).get<json::object_t>(), - "type must be object, but is number"); + "[except.302] type must be object, but is number"); CHECK_THROWS_WITH(json(json::value_t::number_float).get<json::object_t>(), - "type must be object, but is number"); + "[except.302] type must be object, but is number"); } } @@ -1958,28 +1975,28 @@ SECTION("exception in case of a non-array type") { - CHECK_THROWS_AS(json(json::value_t::null).get<json::array_t>(), std::logic_error); - CHECK_THROWS_AS(json(json::value_t::object).get<json::array_t>(), std::logic_error); - CHECK_THROWS_AS(json(json::value_t::string).get<json::array_t>(), std::logic_error); - CHECK_THROWS_AS(json(json::value_t::boolean).get<json::array_t>(), std::logic_error); - CHECK_THROWS_AS(json(json::value_t::number_integer).get<json::array_t>(), std::logic_error); - CHECK_THROWS_AS(json(json::value_t::number_unsigned).get<json::array_t>(), std::logic_error); - CHECK_THROWS_AS(json(json::value_t::number_float).get<json::array_t>(), std::logic_error); + CHECK_THROWS_AS(json(json::value_t::null).get<json::array_t>(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::object).get<json::array_t>(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::string).get<json::array_t>(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::boolean).get<json::array_t>(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::number_integer).get<json::array_t>(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::number_unsigned).get<json::array_t>(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::number_float).get<json::array_t>(), json::type_error); CHECK_THROWS_WITH(json(json::value_t::null).get<json::array_t>(), - "type must be array, but is null"); + "[except.302] type must be array, but is null"); CHECK_THROWS_WITH(json(json::value_t::object).get<json::array_t>(), - "type must be array, but is object"); + "[except.302] type must be array, but is object"); CHECK_THROWS_WITH(json(json::value_t::string).get<json::array_t>(), - "type must be array, but is string"); + "[except.302] type must be array, but is string"); CHECK_THROWS_WITH(json(json::value_t::boolean).get<json::array_t>(), - "type must be array, but is boolean"); + "[except.302] type must be array, but is boolean"); CHECK_THROWS_WITH(json(json::value_t::number_integer).get<json::array_t>(), - "type must be array, but is number"); + "[except.302] type must be array, but is number"); CHECK_THROWS_WITH(json(json::value_t::number_unsigned).get<json::array_t>(), - "type must be array, but is number"); + "[except.302] type must be array, but is number"); CHECK_THROWS_WITH(json(json::value_t::number_float).get<json::array_t>(), - "type must be array, but is number"); + "[except.302] type must be array, but is number"); } } @@ -2038,28 +2055,28 @@ SECTION("exception in case of a non-string type") { - CHECK_THROWS_AS(json(json::value_t::null).get<json::string_t>(), std::logic_error); - CHECK_THROWS_AS(json(json::value_t::object).get<json::string_t>(), std::logic_error); - CHECK_THROWS_AS(json(json::value_t::array).get<json::string_t>(), std::logic_error); - CHECK_THROWS_AS(json(json::value_t::boolean).get<json::string_t>(), std::logic_error); - CHECK_THROWS_AS(json(json::value_t::number_integer).get<json::string_t>(), std::logic_error); - CHECK_THROWS_AS(json(json::value_t::number_unsigned).get<json::string_t>(), std::logic_error); - CHECK_THROWS_AS(json(json::value_t::number_float).get<json::string_t>(), std::logic_error); + CHECK_THROWS_AS(json(json::value_t::null).get<json::string_t>(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::object).get<json::string_t>(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::array).get<json::string_t>(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::boolean).get<json::string_t>(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::number_integer).get<json::string_t>(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::number_unsigned).get<json::string_t>(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::number_float).get<json::string_t>(), json::type_error); CHECK_THROWS_WITH(json(json::value_t::null).get<json::string_t>(), - "type must be string, but is null"); + "[except.302] type must be string, but is null"); CHECK_THROWS_WITH(json(json::value_t::object).get<json::string_t>(), - "type must be string, but is object"); + "[except.302] type must be string, but is object"); CHECK_THROWS_WITH(json(json::value_t::array).get<json::string_t>(), - "type must be string, but is array"); + "[except.302] type must be string, but is array"); CHECK_THROWS_WITH(json(json::value_t::boolean).get<json::string_t>(), - "type must be string, but is boolean"); + "[except.302] type must be string, but is boolean"); CHECK_THROWS_WITH(json(json::value_t::number_integer).get<json::string_t>(), - "type must be string, but is number"); + "[except.302] type must be string, but is number"); CHECK_THROWS_WITH(json(json::value_t::number_unsigned).get<json::string_t>(), - "type must be string, but is number"); + "[except.302] type must be string, but is number"); CHECK_THROWS_WITH(json(json::value_t::number_float).get<json::string_t>(), - "type must be string, but is number"); + "[except.302] type must be string, but is number"); } } @@ -2100,28 +2117,28 @@ SECTION("exception in case of a non-string type") { - CHECK_THROWS_AS(json(json::value_t::null).get<json::boolean_t>(), std::logic_error); - CHECK_THROWS_AS(json(json::value_t::object).get<json::boolean_t>(), std::logic_error); - CHECK_THROWS_AS(json(json::value_t::array).get<json::boolean_t>(), std::logic_error); - CHECK_THROWS_AS(json(json::value_t::string).get<json::boolean_t>(), std::logic_error); - CHECK_THROWS_AS(json(json::value_t::number_integer).get<json::boolean_t>(), std::logic_error); - CHECK_THROWS_AS(json(json::value_t::number_unsigned).get<json::boolean_t>(), std::logic_error); - CHECK_THROWS_AS(json(json::value_t::number_float).get<json::boolean_t>(), std::logic_error); + CHECK_THROWS_AS(json(json::value_t::null).get<json::boolean_t>(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::object).get<json::boolean_t>(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::array).get<json::boolean_t>(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::string).get<json::boolean_t>(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::number_integer).get<json::boolean_t>(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::number_unsigned).get<json::boolean_t>(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::number_float).get<json::boolean_t>(), json::type_error); CHECK_THROWS_WITH(json(json::value_t::null).get<json::boolean_t>(), - "type must be boolean, but is null"); + "[except.302] type must be boolean, but is null"); CHECK_THROWS_WITH(json(json::value_t::object).get<json::boolean_t>(), - "type must be boolean, but is object"); + "[except.302] type must be boolean, but is object"); CHECK_THROWS_WITH(json(json::value_t::array).get<json::boolean_t>(), - "type must be boolean, but is array"); + "[except.302] type must be boolean, but is array"); CHECK_THROWS_WITH(json(json::value_t::string).get<json::boolean_t>(), - "type must be boolean, but is string"); + "[except.302] type must be boolean, but is string"); CHECK_THROWS_WITH(json(json::value_t::number_integer).get<json::boolean_t>(), - "type must be boolean, but is number"); + "[except.302] type must be boolean, but is number"); CHECK_THROWS_WITH(json(json::value_t::number_unsigned).get<json::boolean_t>(), - "type must be boolean, but is number"); + "[except.302] type must be boolean, but is number"); CHECK_THROWS_WITH(json(json::value_t::number_float).get<json::boolean_t>(), - "type must be boolean, but is number"); + "[except.302] type must be boolean, but is number"); } } @@ -2356,22 +2373,22 @@ SECTION("exception in case of a non-number type") { - CHECK_THROWS_AS(json(json::value_t::null).get<json::number_integer_t>(), std::logic_error); - CHECK_THROWS_AS(json(json::value_t::object).get<json::number_integer_t>(), std::logic_error); - CHECK_THROWS_AS(json(json::value_t::array).get<json::number_integer_t>(), std::logic_error); - CHECK_THROWS_AS(json(json::value_t::string).get<json::number_integer_t>(), std::logic_error); - CHECK_THROWS_AS(json(json::value_t::boolean).get<json::number_integer_t>(), std::logic_error); + CHECK_THROWS_AS(json(json::value_t::null).get<json::number_integer_t>(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::object).get<json::number_integer_t>(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::array).get<json::number_integer_t>(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::string).get<json::number_integer_t>(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::boolean).get<json::number_integer_t>(), json::type_error); CHECK_THROWS_WITH(json(json::value_t::null).get<json::number_integer_t>(), - "type must be number, but is null"); + "[except.302] type must be number, but is null"); CHECK_THROWS_WITH(json(json::value_t::object).get<json::number_integer_t>(), - "type must be number, but is object"); + "[except.302] type must be number, but is object"); CHECK_THROWS_WITH(json(json::value_t::array).get<json::number_integer_t>(), - "type must be number, but is array"); + "[except.302] type must be number, but is array"); CHECK_THROWS_WITH(json(json::value_t::string).get<json::number_integer_t>(), - "type must be number, but is string"); + "[except.302] type must be number, but is string"); CHECK_THROWS_WITH(json(json::value_t::boolean).get<json::number_integer_t>(), - "type must be number, but is boolean"); + "[except.302] type must be number, but is boolean"); CHECK_NOTHROW(json(json::value_t::number_float).get<json::number_integer_t>()); CHECK_NOTHROW(json(json::value_t::number_float).get<json::number_unsigned_t>()); @@ -2615,22 +2632,22 @@ SECTION("exception in case of a non-string type") { - CHECK_THROWS_AS(json(json::value_t::null).get<json::number_float_t>(), std::logic_error); - CHECK_THROWS_AS(json(json::value_t::object).get<json::number_float_t>(), std::logic_error); - CHECK_THROWS_AS(json(json::value_t::array).get<json::number_float_t>(), std::logic_error); - CHECK_THROWS_AS(json(json::value_t::string).get<json::number_float_t>(), std::logic_error); - CHECK_THROWS_AS(json(json::value_t::boolean).get<json::number_float_t>(), std::logic_error); + CHECK_THROWS_AS(json(json::value_t::null).get<json::number_float_t>(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::object).get<json::number_float_t>(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::array).get<json::number_float_t>(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::string).get<json::number_float_t>(), json::type_error); + CHECK_THROWS_AS(json(json::value_t::boolean).get<json::number_float_t>(), json::type_error); CHECK_THROWS_WITH(json(json::value_t::null).get<json::number_float_t>(), - "type must be number, but is null"); + "[except.302] type must be number, but is null"); CHECK_THROWS_WITH(json(json::value_t::object).get<json::number_float_t>(), - "type must be number, but is object"); + "[except.302] type must be number, but is object"); CHECK_THROWS_WITH(json(json::value_t::array).get<json::number_float_t>(), - "type must be number, but is array"); + "[except.302] type must be number, but is array"); CHECK_THROWS_WITH(json(json::value_t::string).get<json::number_float_t>(), - "type must be number, but is string"); + "[except.302] type must be number, but is string"); CHECK_THROWS_WITH(json(json::value_t::boolean).get<json::number_float_t>(), - "type must be number, but is boolean"); + "[except.302] type must be number, but is boolean"); CHECK_NOTHROW(json(json::value_t::number_integer).get<json::number_float_t>()); CHECK_NOTHROW(json(json::value_t::number_unsigned).get<json::number_float_t>()); @@ -2712,8 +2729,9 @@ SECTION("exception in case of a non-object type") { - CHECK_THROWS_AS((json().get<std::map<std::string, int>>()), std::logic_error); - CHECK_THROWS_WITH((json().get<std::map<std::string, int>>()), "type must be object, but is null"); + CHECK_THROWS_AS((json().get<std::map<std::string, int>>()), json::type_error); + CHECK_THROWS_WITH((json().get<std::map<std::string, int>>()), + "[except.302] type must be object, but is null"); } } @@ -2781,15 +2799,19 @@ SECTION("exception in case of a non-object type") { - CHECK_THROWS_AS((json().get<std::list<int>>()), std::logic_error); - CHECK_THROWS_AS((json().get<std::vector<int>>()), std::logic_error); - CHECK_THROWS_AS((json().get<std::vector<json>>()), std::logic_error); - CHECK_THROWS_AS((json().get<std::list<json>>()), std::logic_error); + CHECK_THROWS_AS((json().get<std::list<int>>()), json::type_error); + CHECK_THROWS_AS((json().get<std::vector<int>>()), json::type_error); + CHECK_THROWS_AS((json().get<std::vector<json>>()), json::type_error); + CHECK_THROWS_AS((json().get<std::list<json>>()), json::type_error); - CHECK_THROWS_WITH((json().get<std::list<int>>()), "type must be array, but is null"); - CHECK_THROWS_WITH((json().get<std::vector<int>>()), "type must be array, but is null"); - CHECK_THROWS_WITH((json().get<std::vector<json>>()), "type must be array, but is null"); - CHECK_THROWS_WITH((json().get<std::list<json>>()), "type must be array, but is null"); + CHECK_THROWS_WITH((json().get<std::list<int>>()), + "[except.302] type must be array, but is null"); + CHECK_THROWS_WITH((json().get<std::vector<int>>()), + "[except.302] type must be array, but is null"); + CHECK_THROWS_WITH((json().get<std::vector<json>>()), + "[except.302] type must be array, but is null"); + CHECK_THROWS_WITH((json().get<std::list<json>>()), + "[except.302] type must be array, but is null"); } } } @@ -2992,7 +3014,7 @@ CHECK(value.get_ptr<json::array_t*>() == nullptr); CHECK(value.get_ptr<json::string_t*>() == nullptr); CHECK(value.get_ptr<json::boolean_t*>() == nullptr); - CHECK(value.get_ptr<json::number_integer_t*>() != nullptr); + CHECK(value.get_ptr<json::number_integer_t*>() == nullptr); CHECK(value.get_ptr<json::number_unsigned_t*>() != nullptr); CHECK(value.get_ptr<json::number_float_t*>() == nullptr); } @@ -3059,11 +3081,25 @@ // check if mismatching references throw correctly CHECK_NOTHROW(value.get_ref<json::object_t&>()); - CHECK_THROWS(value.get_ref<json::array_t&>()); - CHECK_THROWS(value.get_ref<json::string_t&>()); - CHECK_THROWS(value.get_ref<json::boolean_t&>()); - CHECK_THROWS(value.get_ref<json::number_integer_t&>()); - CHECK_THROWS(value.get_ref<json::number_float_t&>()); + CHECK_THROWS_AS(value.get_ref<json::array_t&>(), json::type_error); + CHECK_THROWS_AS(value.get_ref<json::string_t&>(), json::type_error); + CHECK_THROWS_AS(value.get_ref<json::boolean_t&>(), json::type_error); + CHECK_THROWS_AS(value.get_ref<json::number_integer_t&>(), json::type_error); + CHECK_THROWS_AS(value.get_ref<json::number_unsigned_t&>(), json::type_error); + CHECK_THROWS_AS(value.get_ref<json::number_float_t&>(), json::type_error); + + CHECK_THROWS_WITH(value.get_ref<json::array_t&>(), + "[except.310] incompatible ReferenceType for get_ref, actual type is object"); + CHECK_THROWS_WITH(value.get_ref<json::string_t&>(), + "[except.310] incompatible ReferenceType for get_ref, actual type is object"); + CHECK_THROWS_WITH(value.get_ref<json::boolean_t&>(), + "[except.310] incompatible ReferenceType for get_ref, actual type is object"); + CHECK_THROWS_WITH(value.get_ref<json::number_integer_t&>(), + "[except.310] incompatible ReferenceType for get_ref, actual type is object"); + CHECK_THROWS_WITH(value.get_ref<json::number_unsigned_t&>(), + "[except.310] incompatible ReferenceType for get_ref, actual type is object"); + CHECK_THROWS_WITH(value.get_ref<json::number_float_t&>(), + "[except.310] incompatible ReferenceType for get_ref, actual type is object"); } SECTION("const reference access to const object_t") @@ -3095,12 +3131,26 @@ CHECK(p2 == value.get<test_type>()); // check if mismatching references throw correctly - CHECK_THROWS(value.get_ref<json::object_t&>()); + CHECK_THROWS_AS(value.get_ref<json::object_t&>(), json::type_error); CHECK_NOTHROW(value.get_ref<json::array_t&>()); - CHECK_THROWS(value.get_ref<json::string_t&>()); - CHECK_THROWS(value.get_ref<json::boolean_t&>()); - CHECK_THROWS(value.get_ref<json::number_integer_t&>()); - CHECK_THROWS(value.get_ref<json::number_float_t&>()); + CHECK_THROWS_AS(value.get_ref<json::string_t&>(), json::type_error); + CHECK_THROWS_AS(value.get_ref<json::boolean_t&>(), json::type_error); + CHECK_THROWS_AS(value.get_ref<json::number_integer_t&>(), json::type_error); + CHECK_THROWS_AS(value.get_ref<json::number_unsigned_t&>(), json::type_error); + CHECK_THROWS_AS(value.get_ref<json::number_float_t&>(), json::type_error); + + CHECK_THROWS_WITH(value.get_ref<json::object_t&>(), + "[except.310] incompatible ReferenceType for get_ref, actual type is array"); + CHECK_THROWS_WITH(value.get_ref<json::string_t&>(), + "[except.310] incompatible ReferenceType for get_ref, actual type is array"); + CHECK_THROWS_WITH(value.get_ref<json::boolean_t&>(), + "[except.310] incompatible ReferenceType for get_ref, actual type is array"); + CHECK_THROWS_WITH(value.get_ref<json::number_integer_t&>(), + "[except.310] incompatible ReferenceType for get_ref, actual type is array"); + CHECK_THROWS_WITH(value.get_ref<json::number_unsigned_t&>(), + "[except.310] incompatible ReferenceType for get_ref, actual type is array"); + CHECK_THROWS_WITH(value.get_ref<json::number_float_t&>(), + "[except.310] incompatible ReferenceType for get_ref, actual type is array"); } SECTION("reference access to string_t") @@ -3118,12 +3168,26 @@ CHECK(p2 == value.get<test_type>()); // check if mismatching references throw correctly - CHECK_THROWS(value.get_ref<json::object_t&>()); - CHECK_THROWS(value.get_ref<json::array_t&>()); + CHECK_THROWS_AS(value.get_ref<json::object_t&>(), json::type_error); + CHECK_THROWS_AS(value.get_ref<json::array_t&>(), json::type_error); CHECK_NOTHROW(value.get_ref<json::string_t&>()); - CHECK_THROWS(value.get_ref<json::boolean_t&>()); - CHECK_THROWS(value.get_ref<json::number_integer_t&>()); - CHECK_THROWS(value.get_ref<json::number_float_t&>()); + CHECK_THROWS_AS(value.get_ref<json::boolean_t&>(), json::type_error); + CHECK_THROWS_AS(value.get_ref<json::number_integer_t&>(), json::type_error); + CHECK_THROWS_AS(value.get_ref<json::number_unsigned_t&>(), json::type_error); + CHECK_THROWS_AS(value.get_ref<json::number_float_t&>(), json::type_error); + + CHECK_THROWS_WITH(value.get_ref<json::object_t&>(), + "[except.310] incompatible ReferenceType for get_ref, actual type is string"); + CHECK_THROWS_WITH(value.get_ref<json::array_t&>(), + "[except.310] incompatible ReferenceType for get_ref, actual type is string"); + CHECK_THROWS_WITH(value.get_ref<json::boolean_t&>(), + "[except.310] incompatible ReferenceType for get_ref, actual type is string"); + CHECK_THROWS_WITH(value.get_ref<json::number_integer_t&>(), + "[except.310] incompatible ReferenceType for get_ref, actual type is string"); + CHECK_THROWS_WITH(value.get_ref<json::number_unsigned_t&>(), + "[except.310] incompatible ReferenceType for get_ref, actual type is string"); + CHECK_THROWS_WITH(value.get_ref<json::number_float_t&>(), + "[except.310] incompatible ReferenceType for get_ref, actual type is string"); } SECTION("reference access to boolean_t") @@ -3141,12 +3205,26 @@ CHECK(p2 == value.get<test_type>()); // check if mismatching references throw correctly - CHECK_THROWS(value.get_ref<json::object_t&>()); - CHECK_THROWS(value.get_ref<json::array_t&>()); - CHECK_THROWS(value.get_ref<json::string_t&>()); + CHECK_THROWS_AS(value.get_ref<json::object_t&>(), json::type_error); + CHECK_THROWS_AS(value.get_ref<json::array_t&>(), json::type_error); + CHECK_THROWS_AS(value.get_ref<json::string_t&>(), json::type_error); CHECK_NOTHROW(value.get_ref<json::boolean_t&>()); - CHECK_THROWS(value.get_ref<json::number_integer_t&>()); - CHECK_THROWS(value.get_ref<json::number_float_t&>()); + CHECK_THROWS_AS(value.get_ref<json::number_integer_t&>(), json::type_error); + CHECK_THROWS_AS(value.get_ref<json::number_unsigned_t&>(), json::type_error); + CHECK_THROWS_AS(value.get_ref<json::number_float_t&>(), json::type_error); + + CHECK_THROWS_WITH(value.get_ref<json::object_t&>(), + "[except.310] incompatible ReferenceType for get_ref, actual type is boolean"); + CHECK_THROWS_WITH(value.get_ref<json::array_t&>(), + "[except.310] incompatible ReferenceType for get_ref, actual type is boolean"); + CHECK_THROWS_WITH(value.get_ref<json::string_t&>(), + "[except.310] incompatible ReferenceType for get_ref, actual type is boolean"); + CHECK_THROWS_WITH(value.get_ref<json::number_integer_t&>(), + "[except.310] incompatible ReferenceType for get_ref, actual type is boolean"); + CHECK_THROWS_WITH(value.get_ref<json::number_unsigned_t&>(), + "[except.310] incompatible ReferenceType for get_ref, actual type is boolean"); + CHECK_THROWS_WITH(value.get_ref<json::number_float_t&>(), + "[except.310] incompatible ReferenceType for get_ref, actual type is boolean"); } SECTION("reference access to number_integer_t") @@ -3164,12 +3242,63 @@ CHECK(p2 == value.get<test_type>()); // check if mismatching references throw correctly - CHECK_THROWS(value.get_ref<json::object_t&>()); - CHECK_THROWS(value.get_ref<json::array_t&>()); - CHECK_THROWS(value.get_ref<json::string_t&>()); - CHECK_THROWS(value.get_ref<json::boolean_t&>()); + CHECK_THROWS_AS(value.get_ref<json::object_t&>(), json::type_error); + CHECK_THROWS_AS(value.get_ref<json::array_t&>(), json::type_error); + CHECK_THROWS_AS(value.get_ref<json::string_t&>(), json::type_error); + CHECK_THROWS_AS(value.get_ref<json::boolean_t&>(), json::type_error); CHECK_NOTHROW(value.get_ref<json::number_integer_t&>()); - CHECK_THROWS(value.get_ref<json::number_float_t&>()); + CHECK_THROWS_AS(value.get_ref<json::number_unsigned_t&>(), json::type_error); + CHECK_THROWS_AS(value.get_ref<json::number_float_t&>(), json::type_error); + + CHECK_THROWS_WITH(value.get_ref<json::object_t&>(), + "[except.310] incompatible ReferenceType for get_ref, actual type is number"); + CHECK_THROWS_WITH(value.get_ref<json::array_t&>(), + "[except.310] incompatible ReferenceType for get_ref, actual type is number"); + CHECK_THROWS_WITH(value.get_ref<json::string_t&>(), + "[except.310] incompatible ReferenceType for get_ref, actual type is number"); + CHECK_THROWS_WITH(value.get_ref<json::boolean_t&>(), + "[except.310] incompatible ReferenceType for get_ref, actual type is number"); + CHECK_THROWS_WITH(value.get_ref<json::number_unsigned_t&>(), + "[except.310] incompatible ReferenceType for get_ref, actual type is number"); + CHECK_THROWS_WITH(value.get_ref<json::number_float_t&>(), + "[except.310] incompatible ReferenceType for get_ref, actual type is number"); + } + + SECTION("reference access to number_unsigned_t") + { + using test_type = json::number_unsigned_t; + json value = static_cast<json::number_unsigned_t>(23); + + // check if references are returned correctly + test_type& p1 = value.get_ref<test_type&>(); + CHECK(&p1 == value.get_ptr<test_type*>()); + CHECK(p1 == value.get<test_type>()); + + const test_type& p2 = value.get_ref<const test_type&>(); + CHECK(&p2 == value.get_ptr<const test_type*>()); + CHECK(p2 == value.get<test_type>()); + + // check if mismatching references throw correctly + CHECK_THROWS_AS(value.get_ref<json::object_t&>(), json::type_error); + CHECK_THROWS_AS(value.get_ref<json::array_t&>(), json::type_error); + CHECK_THROWS_AS(value.get_ref<json::string_t&>(), json::type_error); + CHECK_THROWS_AS(value.get_ref<json::boolean_t&>(), json::type_error); + CHECK_THROWS_AS(value.get_ref<json::number_integer_t&>(), json::type_error); + CHECK_NOTHROW(value.get_ref<json::number_unsigned_t&>()); + CHECK_THROWS_AS(value.get_ref<json::number_float_t&>(), json::type_error); + + CHECK_THROWS_WITH(value.get_ref<json::object_t&>(), + "[except.310] incompatible ReferenceType for get_ref, actual type is number"); + CHECK_THROWS_WITH(value.get_ref<json::array_t&>(), + "[except.310] incompatible ReferenceType for get_ref, actual type is number"); + CHECK_THROWS_WITH(value.get_ref<json::string_t&>(), + "[except.310] incompatible ReferenceType for get_ref, actual type is number"); + CHECK_THROWS_WITH(value.get_ref<json::boolean_t&>(), + "[except.310] incompatible ReferenceType for get_ref, actual type is number"); + CHECK_THROWS_WITH(value.get_ref<json::number_integer_t&>(), + "[except.310] incompatible ReferenceType for get_ref, actual type is number"); + CHECK_THROWS_WITH(value.get_ref<json::number_float_t&>(), + "[except.310] incompatible ReferenceType for get_ref, actual type is number"); } SECTION("reference access to number_float_t") @@ -3187,12 +3316,26 @@ CHECK(p2 == value.get<test_type>()); // check if mismatching references throw correctly - CHECK_THROWS(value.get_ref<json::object_t&>()); - CHECK_THROWS(value.get_ref<json::array_t&>()); - CHECK_THROWS(value.get_ref<json::string_t&>()); - CHECK_THROWS(value.get_ref<json::boolean_t&>()); - CHECK_THROWS(value.get_ref<json::number_integer_t&>()); + CHECK_THROWS_AS(value.get_ref<json::object_t&>(), json::type_error); + CHECK_THROWS_AS(value.get_ref<json::array_t&>(), json::type_error); + CHECK_THROWS_AS(value.get_ref<json::string_t&>(), json::type_error); + CHECK_THROWS_AS(value.get_ref<json::boolean_t&>(), json::type_error); + CHECK_THROWS_AS(value.get_ref<json::number_integer_t&>(), json::type_error); + CHECK_THROWS_AS(value.get_ref<json::number_unsigned_t&>(), json::type_error); CHECK_NOTHROW(value.get_ref<json::number_float_t&>()); + + CHECK_THROWS_WITH(value.get_ref<json::object_t&>(), + "[except.310] incompatible ReferenceType for get_ref, actual type is number"); + CHECK_THROWS_WITH(value.get_ref<json::array_t&>(), + "[except.310] incompatible ReferenceType for get_ref, actual type is number"); + CHECK_THROWS_WITH(value.get_ref<json::string_t&>(), + "[except.310] incompatible ReferenceType for get_ref, actual type is number"); + CHECK_THROWS_WITH(value.get_ref<json::boolean_t&>(), + "[except.310] incompatible ReferenceType for get_ref, actual type is number"); + CHECK_THROWS_WITH(value.get_ref<json::number_integer_t&>(), + "[except.310] incompatible ReferenceType for get_ref, actual type is number"); + CHECK_THROWS_WITH(value.get_ref<json::number_unsigned_t&>(), + "[except.310] incompatible ReferenceType for get_ref, actual type is number"); } } @@ -3241,77 +3384,77 @@ { json j_nonarray(json::value_t::null); const json j_nonarray_const(j_nonarray); - CHECK_THROWS_AS(j_nonarray.at(0), std::domain_error); - CHECK_THROWS_AS(j_nonarray_const.at(0), std::domain_error); + CHECK_THROWS_AS(j_nonarray.at(0), json::type_error); + CHECK_THROWS_AS(j_nonarray_const.at(0), json::type_error); - CHECK_THROWS_WITH(j_nonarray.at(0), "cannot use at() with null"); - CHECK_THROWS_WITH(j_nonarray_const.at(0), "cannot use at() with null"); + CHECK_THROWS_WITH(j_nonarray.at(0), "[except.303] cannot use at() with null"); + CHECK_THROWS_WITH(j_nonarray_const.at(0), "[except.303] cannot use at() with null"); } SECTION("boolean") { json j_nonarray(json::value_t::boolean); const json j_nonarray_const(j_nonarray); - CHECK_THROWS_AS(j_nonarray.at(0), std::domain_error); - CHECK_THROWS_AS(j_nonarray_const.at(0), std::domain_error); + CHECK_THROWS_AS(j_nonarray.at(0), json::type_error); + CHECK_THROWS_AS(j_nonarray_const.at(0), json::type_error); - CHECK_THROWS_WITH(j_nonarray.at(0), "cannot use at() with boolean"); - CHECK_THROWS_WITH(j_nonarray_const.at(0), "cannot use at() with boolean"); + CHECK_THROWS_WITH(j_nonarray.at(0), "[except.303] cannot use at() with boolean"); + CHECK_THROWS_WITH(j_nonarray_const.at(0), "[except.303] cannot use at() with boolean"); } SECTION("string") { json j_nonarray(json::value_t::string); const json j_nonarray_const(j_nonarray); - CHECK_THROWS_AS(j_nonarray.at(0), std::domain_error); - CHECK_THROWS_AS(j_nonarray_const.at(0), std::domain_error); + CHECK_THROWS_AS(j_nonarray.at(0), json::type_error); + CHECK_THROWS_AS(j_nonarray_const.at(0), json::type_error); - CHECK_THROWS_WITH(j_nonarray.at(0), "cannot use at() with string"); - CHECK_THROWS_WITH(j_nonarray_const.at(0), "cannot use at() with string"); + CHECK_THROWS_WITH(j_nonarray.at(0), "[except.303] cannot use at() with string"); + CHECK_THROWS_WITH(j_nonarray_const.at(0), "[except.303] cannot use at() with string"); } SECTION("object") { json j_nonarray(json::value_t::object); const json j_nonarray_const(j_nonarray); - CHECK_THROWS_AS(j_nonarray.at(0), std::domain_error); - CHECK_THROWS_AS(j_nonarray_const.at(0), std::domain_error); + CHECK_THROWS_AS(j_nonarray.at(0), json::type_error); + CHECK_THROWS_AS(j_nonarray_const.at(0), json::type_error); - CHECK_THROWS_WITH(j_nonarray.at(0), "cannot use at() with object"); - CHECK_THROWS_WITH(j_nonarray_const.at(0), "cannot use at() with object"); + CHECK_THROWS_WITH(j_nonarray.at(0), "[except.303] cannot use at() with object"); + CHECK_THROWS_WITH(j_nonarray_const.at(0), "[except.303] cannot use at() with object"); } SECTION("number (integer)") { json j_nonarray(json::value_t::number_integer); const json j_nonarray_const(j_nonarray); - CHECK_THROWS_AS(j_nonarray.at(0), std::domain_error); - CHECK_THROWS_AS(j_nonarray_const.at(0), std::domain_error); + CHECK_THROWS_AS(j_nonarray.at(0), json::type_error); + CHECK_THROWS_AS(j_nonarray_const.at(0), json::type_error); - CHECK_THROWS_WITH(j_nonarray.at(0), "cannot use at() with number"); - CHECK_THROWS_WITH(j_nonarray_const.at(0), "cannot use at() with number"); + CHECK_THROWS_WITH(j_nonarray.at(0), "[except.303] cannot use at() with number"); + CHECK_THROWS_WITH(j_nonarray_const.at(0), "[except.303] cannot use at() with number"); } SECTION("number (unsigned)") { json j_nonarray(json::value_t::number_unsigned); const json j_nonarray_const(j_nonarray); - CHECK_THROWS_AS(j_nonarray.at(0), std::domain_error); - CHECK_THROWS_AS(j_nonarray_const.at(0), std::domain_error); + CHECK_THROWS_AS(j_nonarray.at(0), json::type_error); + CHECK_THROWS_AS(j_nonarray_const.at(0), json::type_error); - CHECK_THROWS_WITH(j_nonarray.at(0), "cannot use at() with number"); - CHECK_THROWS_WITH(j_nonarray_const.at(0), "cannot use at() with number"); + CHECK_THROWS_WITH(j_nonarray.at(0), "[except.303] cannot use at() with number"); + CHECK_THROWS_WITH(j_nonarray_const.at(0), "[except.303] cannot use at() with number"); } SECTION("number (floating-point)") { json j_nonarray(json::value_t::number_float); const json j_nonarray_const(j_nonarray); - CHECK_THROWS_AS(j_nonarray.at(0), std::domain_error); - CHECK_THROWS_AS(j_nonarray_const.at(0), std::domain_error); + CHECK_THROWS_AS(j_nonarray.at(0), json::type_error); + CHECK_THROWS_AS(j_nonarray_const.at(0), json::type_error); - CHECK_THROWS_WITH(j_nonarray.at(0), "cannot use at() with number"); - CHECK_THROWS_WITH(j_nonarray_const.at(0), "cannot use at() with number"); + CHECK_THROWS_WITH(j_nonarray.at(0), "[except.303] cannot use at() with number"); + CHECK_THROWS_WITH(j_nonarray_const.at(0), "[except.303] cannot use at() with number"); } } } @@ -3356,8 +3499,8 @@ json j_nonarray(json::value_t::null); const json j_nonarray_const(j_nonarray); CHECK_NOTHROW(j_nonarray[0]); - CHECK_THROWS_AS(j_nonarray_const[0], std::domain_error); - CHECK_THROWS_WITH(j_nonarray_const[0], "cannot use operator[] with null"); + CHECK_THROWS_AS(j_nonarray_const[0], json::type_error); + CHECK_THROWS_WITH(j_nonarray_const[0], "[except.304] cannot use operator[] with null"); } SECTION("implicit transformation to properly filled array") @@ -3372,60 +3515,60 @@ { json j_nonarray(json::value_t::boolean); const json j_nonarray_const(j_nonarray); - CHECK_THROWS_AS(j_nonarray[0], std::domain_error); - CHECK_THROWS_AS(j_nonarray_const[0], std::domain_error); - CHECK_THROWS_WITH(j_nonarray[0], "cannot use operator[] with boolean"); - CHECK_THROWS_WITH(j_nonarray_const[0], "cannot use operator[] with boolean"); + CHECK_THROWS_AS(j_nonarray[0], json::type_error); + CHECK_THROWS_AS(j_nonarray_const[0], json::type_error); + CHECK_THROWS_WITH(j_nonarray[0], "[except.304] cannot use operator[] with boolean"); + CHECK_THROWS_WITH(j_nonarray_const[0], "[except.304] cannot use operator[] with boolean"); } SECTION("string") { json j_nonarray(json::value_t::string); const json j_nonarray_const(j_nonarray); - CHECK_THROWS_AS(j_nonarray[0], std::domain_error); - CHECK_THROWS_AS(j_nonarray_const[0], std::domain_error); - CHECK_THROWS_WITH(j_nonarray[0], "cannot use operator[] with string"); - CHECK_THROWS_WITH(j_nonarray_const[0], "cannot use operator[] with string"); + CHECK_THROWS_AS(j_nonarray[0], json::type_error); + CHECK_THROWS_AS(j_nonarray_const[0], json::type_error); + CHECK_THROWS_WITH(j_nonarray[0], "[except.304] cannot use operator[] with string"); + CHECK_THROWS_WITH(j_nonarray_const[0], "[except.304] cannot use operator[] with string"); } SECTION("object") { json j_nonarray(json::value_t::object); const json j_nonarray_const(j_nonarray); - CHECK_THROWS_AS(j_nonarray[0], std::domain_error); - CHECK_THROWS_AS(j_nonarray_const[0], std::domain_error); - CHECK_THROWS_WITH(j_nonarray[0], "cannot use operator[] with object"); - CHECK_THROWS_WITH(j_nonarray_const[0], "cannot use operator[] with object"); + CHECK_THROWS_AS(j_nonarray[0], json::type_error); + CHECK_THROWS_AS(j_nonarray_const[0], json::type_error); + CHECK_THROWS_WITH(j_nonarray[0], "[except.304] cannot use operator[] with object"); + CHECK_THROWS_WITH(j_nonarray_const[0], "[except.304] cannot use operator[] with object"); } SECTION("number (integer)") { json j_nonarray(json::value_t::number_integer); const json j_nonarray_const(j_nonarray); - CHECK_THROWS_AS(j_nonarray[0], std::domain_error); - CHECK_THROWS_AS(j_nonarray_const[0], std::domain_error); - CHECK_THROWS_WITH(j_nonarray[0], "cannot use operator[] with number"); - CHECK_THROWS_WITH(j_nonarray_const[0], "cannot use operator[] with number"); + CHECK_THROWS_AS(j_nonarray[0], json::type_error); + CHECK_THROWS_AS(j_nonarray_const[0], json::type_error); + CHECK_THROWS_WITH(j_nonarray[0], "[except.304] cannot use operator[] with number"); + CHECK_THROWS_WITH(j_nonarray_const[0], "[except.304] cannot use operator[] with number"); } SECTION("number (unsigned)") { json j_nonarray(json::value_t::number_unsigned); const json j_nonarray_const(j_nonarray); - CHECK_THROWS_AS(j_nonarray[0], std::domain_error); - CHECK_THROWS_AS(j_nonarray_const[0], std::domain_error); - CHECK_THROWS_WITH(j_nonarray[0], "cannot use operator[] with number"); - CHECK_THROWS_WITH(j_nonarray_const[0], "cannot use operator[] with number"); + CHECK_THROWS_AS(j_nonarray[0], json::type_error); + CHECK_THROWS_AS(j_nonarray_const[0], json::type_error); + CHECK_THROWS_WITH(j_nonarray[0], "[except.304] cannot use operator[] with number"); + CHECK_THROWS_WITH(j_nonarray_const[0], "[except.304] cannot use operator[] with number"); } SECTION("number (floating-point)") { json j_nonarray(json::value_t::number_float); const json j_nonarray_const(j_nonarray); - CHECK_THROWS_AS(j_nonarray[0], std::domain_error); - CHECK_THROWS_AS(j_nonarray_const[0], std::domain_error); - CHECK_THROWS_WITH(j_nonarray[0], "cannot use operator[] with number"); - CHECK_THROWS_WITH(j_nonarray_const[0], "cannot use operator[] with number"); + CHECK_THROWS_AS(j_nonarray[0], json::type_error); + CHECK_THROWS_AS(j_nonarray_const[0], json::type_error); + CHECK_THROWS_WITH(j_nonarray[0], "[except.304] cannot use operator[] with number"); + CHECK_THROWS_WITH(j_nonarray_const[0], "[except.304] cannot use operator[] with number"); } } } @@ -3570,34 +3713,36 @@ { json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}}; json jarray2 = {"foo", "bar"}; - CHECK_THROWS_AS(jarray.erase(jarray2.begin()), std::domain_error); - CHECK_THROWS_AS(jarray.erase(jarray.begin(), jarray2.end()), std::domain_error); - CHECK_THROWS_AS(jarray.erase(jarray2.begin(), jarray.end()), std::domain_error); - CHECK_THROWS_AS(jarray.erase(jarray2.begin(), jarray2.end()), std::domain_error); + CHECK_THROWS_AS(jarray.erase(jarray2.begin()), json::invalid_iterator); + CHECK_THROWS_AS(jarray.erase(jarray.begin(), jarray2.end()), json::invalid_iterator); + CHECK_THROWS_AS(jarray.erase(jarray2.begin(), jarray.end()), json::invalid_iterator); + CHECK_THROWS_AS(jarray.erase(jarray2.begin(), jarray2.end()), json::invalid_iterator); - CHECK_THROWS_WITH(jarray.erase(jarray2.begin()), "iterator does not fit current value"); + CHECK_THROWS_WITH(jarray.erase(jarray2.begin()), + "[except.103] iterator does not fit current value"); CHECK_THROWS_WITH(jarray.erase(jarray.begin(), jarray2.end()), - "iterators do not fit current value"); + "[except.102] iterators do not fit current value"); CHECK_THROWS_WITH(jarray.erase(jarray2.begin(), jarray.end()), - "iterators do not fit current value"); + "[except.102] iterators do not fit current value"); CHECK_THROWS_WITH(jarray.erase(jarray2.begin(), jarray2.end()), - "iterators do not fit current value"); + "[except.102] iterators do not fit current value"); } { json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}}; json jarray2 = {"foo", "bar"}; - CHECK_THROWS_AS(jarray.erase(jarray2.cbegin()), std::domain_error); - CHECK_THROWS_AS(jarray.erase(jarray.cbegin(), jarray2.cend()), std::domain_error); - CHECK_THROWS_AS(jarray.erase(jarray2.cbegin(), jarray.cend()), std::domain_error); - CHECK_THROWS_AS(jarray.erase(jarray2.cbegin(), jarray2.cend()), std::domain_error); + CHECK_THROWS_AS(jarray.erase(jarray2.cbegin()), json::invalid_iterator); + CHECK_THROWS_AS(jarray.erase(jarray.cbegin(), jarray2.cend()), json::invalid_iterator); + CHECK_THROWS_AS(jarray.erase(jarray2.cbegin(), jarray.cend()), json::invalid_iterator); + CHECK_THROWS_AS(jarray.erase(jarray2.cbegin(), jarray2.cend()), json::invalid_iterator); - CHECK_THROWS_WITH(jarray.erase(jarray2.cbegin()), "iterator does not fit current value"); + CHECK_THROWS_WITH(jarray.erase(jarray2.cbegin()), + "[except.103] iterator does not fit current value"); CHECK_THROWS_WITH(jarray.erase(jarray.cbegin(), jarray2.cend()), - "iterators do not fit current value"); + "[except.102] iterators do not fit current value"); CHECK_THROWS_WITH(jarray.erase(jarray2.cbegin(), jarray.cend()), - "iterators do not fit current value"); + "[except.102] iterators do not fit current value"); CHECK_THROWS_WITH(jarray.erase(jarray2.cbegin(), jarray2.cend()), - "iterators do not fit current value"); + "[except.102] iterators do not fit current value"); } } } @@ -3607,50 +3752,50 @@ SECTION("null") { json j_nonobject(json::value_t::null); - CHECK_THROWS_AS(j_nonobject.erase(0), std::domain_error); - CHECK_THROWS_WITH(j_nonobject.erase(0), "cannot use erase() with null"); + CHECK_THROWS_AS(j_nonobject.erase(0), json::type_error); + CHECK_THROWS_WITH(j_nonobject.erase(0), "[except.306] cannot use erase() with null"); } SECTION("boolean") { json j_nonobject(json::value_t::boolean); - CHECK_THROWS_AS(j_nonobject.erase(0), std::domain_error); - CHECK_THROWS_WITH(j_nonobject.erase(0), "cannot use erase() with boolean"); + CHECK_THROWS_AS(j_nonobject.erase(0), json::type_error); + CHECK_THROWS_WITH(j_nonobject.erase(0), "[except.306] cannot use erase() with boolean"); } SECTION("string") { json j_nonobject(json::value_t::string); - CHECK_THROWS_AS(j_nonobject.erase(0), std::domain_error); - CHECK_THROWS_WITH(j_nonobject.erase(0), "cannot use erase() with string"); + CHECK_THROWS_AS(j_nonobject.erase(0), json::type_error); + CHECK_THROWS_WITH(j_nonobject.erase(0), "[except.306] cannot use erase() with string"); } SECTION("object") { json j_nonobject(json::value_t::object); - CHECK_THROWS_AS(j_nonobject.erase(0), std::domain_error); - CHECK_THROWS_WITH(j_nonobject.erase(0), "cannot use erase() with object"); + CHECK_THROWS_AS(j_nonobject.erase(0), json::type_error); + CHECK_THROWS_WITH(j_nonobject.erase(0), "[except.306] cannot use erase() with object"); } SECTION("number (integer)") { json j_nonobject(json::value_t::number_integer); - CHECK_THROWS_AS(j_nonobject.erase(0), std::domain_error); - CHECK_THROWS_WITH(j_nonobject.erase(0), "cannot use erase() with number"); + CHECK_THROWS_AS(j_nonobject.erase(0), json::type_error); + CHECK_THROWS_WITH(j_nonobject.erase(0), "[except.306] cannot use erase() with number"); } SECTION("number (unsigned)") { json j_nonobject(json::value_t::number_unsigned); - CHECK_THROWS_AS(j_nonobject.erase(0), std::domain_error); - CHECK_THROWS_WITH(j_nonobject.erase(0), "cannot use erase() with number"); + CHECK_THROWS_AS(j_nonobject.erase(0), json::type_error); + CHECK_THROWS_WITH(j_nonobject.erase(0), "[except.306] cannot use erase() with number"); } SECTION("number (floating-point)") { json j_nonobject(json::value_t::number_float); - CHECK_THROWS_AS(j_nonobject.erase(0), std::domain_error); - CHECK_THROWS_WITH(j_nonobject.erase(0), "cannot use erase() with number"); + CHECK_THROWS_AS(j_nonobject.erase(0), json::type_error); + CHECK_THROWS_WITH(j_nonobject.erase(0), "[except.306] cannot use erase() with number"); } } } @@ -3698,70 +3843,70 @@ { json j_nonobject(json::value_t::null); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.at("foo"), std::domain_error); - CHECK_THROWS_AS(j_nonobject_const.at("foo"), std::domain_error); - CHECK_THROWS_WITH(j_nonobject.at("foo"), "cannot use at() with null"); - CHECK_THROWS_WITH(j_nonobject_const.at("foo"), "cannot use at() with null"); + CHECK_THROWS_AS(j_nonobject.at("foo"), json::type_error); + CHECK_THROWS_AS(j_nonobject_const.at("foo"), json::type_error); + CHECK_THROWS_WITH(j_nonobject.at("foo"), "[except.303] cannot use at() with null"); + CHECK_THROWS_WITH(j_nonobject_const.at("foo"), "[except.303] cannot use at() with null"); } SECTION("boolean") { json j_nonobject(json::value_t::boolean); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.at("foo"), std::domain_error); - CHECK_THROWS_AS(j_nonobject_const.at("foo"), std::domain_error); - CHECK_THROWS_WITH(j_nonobject.at("foo"), "cannot use at() with boolean"); - CHECK_THROWS_WITH(j_nonobject_const.at("foo"), "cannot use at() with boolean"); + CHECK_THROWS_AS(j_nonobject.at("foo"), json::type_error); + CHECK_THROWS_AS(j_nonobject_const.at("foo"), json::type_error); + CHECK_THROWS_WITH(j_nonobject.at("foo"), "[except.303] cannot use at() with boolean"); + CHECK_THROWS_WITH(j_nonobject_const.at("foo"), "[except.303] cannot use at() with boolean"); } SECTION("string") { json j_nonobject(json::value_t::string); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.at("foo"), std::domain_error); - CHECK_THROWS_AS(j_nonobject_const.at("foo"), std::domain_error); - CHECK_THROWS_WITH(j_nonobject.at("foo"), "cannot use at() with string"); - CHECK_THROWS_WITH(j_nonobject_const.at("foo"), "cannot use at() with string"); + CHECK_THROWS_AS(j_nonobject.at("foo"), json::type_error); + CHECK_THROWS_AS(j_nonobject_const.at("foo"), json::type_error); + CHECK_THROWS_WITH(j_nonobject.at("foo"), "[except.303] cannot use at() with string"); + CHECK_THROWS_WITH(j_nonobject_const.at("foo"), "[except.303] cannot use at() with string"); } SECTION("array") { json j_nonobject(json::value_t::array); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.at("foo"), std::domain_error); - CHECK_THROWS_AS(j_nonobject_const.at("foo"), std::domain_error); - CHECK_THROWS_WITH(j_nonobject.at("foo"), "cannot use at() with array"); - CHECK_THROWS_WITH(j_nonobject_const.at("foo"), "cannot use at() with array"); + CHECK_THROWS_AS(j_nonobject.at("foo"), json::type_error); + CHECK_THROWS_AS(j_nonobject_const.at("foo"), json::type_error); + CHECK_THROWS_WITH(j_nonobject.at("foo"), "[except.303] cannot use at() with array"); + CHECK_THROWS_WITH(j_nonobject_const.at("foo"), "[except.303] cannot use at() with array"); } SECTION("number (integer)") { json j_nonobject(json::value_t::number_integer); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.at("foo"), std::domain_error); - CHECK_THROWS_AS(j_nonobject_const.at("foo"), std::domain_error); - CHECK_THROWS_WITH(j_nonobject.at("foo"), "cannot use at() with number"); - CHECK_THROWS_WITH(j_nonobject_const.at("foo"), "cannot use at() with number"); + CHECK_THROWS_AS(j_nonobject.at("foo"), json::type_error); + CHECK_THROWS_AS(j_nonobject_const.at("foo"), json::type_error); + CHECK_THROWS_WITH(j_nonobject.at("foo"), "[except.303] cannot use at() with number"); + CHECK_THROWS_WITH(j_nonobject_const.at("foo"), "[except.303] cannot use at() with number"); } SECTION("number (unsigned)") { json j_nonobject(json::value_t::number_unsigned); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.at("foo"), std::domain_error); - CHECK_THROWS_AS(j_nonobject_const.at("foo"), std::domain_error); - CHECK_THROWS_WITH(j_nonobject.at("foo"), "cannot use at() with number"); - CHECK_THROWS_WITH(j_nonobject_const.at("foo"), "cannot use at() with number"); + CHECK_THROWS_AS(j_nonobject.at("foo"), json::type_error); + CHECK_THROWS_AS(j_nonobject_const.at("foo"), json::type_error); + CHECK_THROWS_WITH(j_nonobject.at("foo"), "[except.303] cannot use at() with number"); + CHECK_THROWS_WITH(j_nonobject_const.at("foo"), "[except.303] cannot use at() with number"); } SECTION("number (floating-point)") { json j_nonobject(json::value_t::number_float); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.at("foo"), std::domain_error); - CHECK_THROWS_AS(j_nonobject_const.at("foo"), std::domain_error); - CHECK_THROWS_WITH(j_nonobject.at("foo"), "cannot use at() with number"); - CHECK_THROWS_WITH(j_nonobject_const.at("foo"), "cannot use at() with number"); + CHECK_THROWS_AS(j_nonobject.at("foo"), json::type_error); + CHECK_THROWS_AS(j_nonobject_const.at("foo"), json::type_error); + CHECK_THROWS_WITH(j_nonobject.at("foo"), "[except.303] cannot use at() with number"); + CHECK_THROWS_WITH(j_nonobject_const.at("foo"), "[except.303] cannot use at() with number"); } } } @@ -3823,70 +3968,71 @@ { json j_nonobject(json::value_t::null); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.value("foo", 1), std::domain_error); - CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), std::domain_error); - CHECK_THROWS_WITH(j_nonobject.value("foo", 1), "cannot use value() with null"); - CHECK_THROWS_WITH(j_nonobject_const.value("foo", 1), "cannot use value() with null"); + CHECK_THROWS_AS(j_nonobject.value("foo", 1), json::type_error); + CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), json::type_error); + CHECK_THROWS_WITH(j_nonobject.value("foo", 1), "[except.305] cannot use value() with null"); + CHECK_THROWS_WITH(j_nonobject_const.value("foo", 1), "[except.305] cannot use value() with null"); } SECTION("boolean") { json j_nonobject(json::value_t::boolean); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.value("foo", 1), std::domain_error); - CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), std::domain_error); - CHECK_THROWS_WITH(j_nonobject.value("foo", 1), "cannot use value() with boolean"); - CHECK_THROWS_WITH(j_nonobject_const.value("foo", 1), "cannot use value() with boolean"); + CHECK_THROWS_AS(j_nonobject.value("foo", 1), json::type_error); + CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), json::type_error); + CHECK_THROWS_WITH(j_nonobject.value("foo", 1), "[except.305] cannot use value() with boolean"); + CHECK_THROWS_WITH(j_nonobject_const.value("foo", 1), + "[except.305] cannot use value() with boolean"); } SECTION("string") { json j_nonobject(json::value_t::string); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.value("foo", 1), std::domain_error); - CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), std::domain_error); - CHECK_THROWS_WITH(j_nonobject.value("foo", 1), "cannot use value() with string"); - CHECK_THROWS_WITH(j_nonobject_const.value("foo", 1), "cannot use value() with string"); + CHECK_THROWS_AS(j_nonobject.value("foo", 1), json::type_error); + CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), json::type_error); + CHECK_THROWS_WITH(j_nonobject.value("foo", 1), "[except.305] cannot use value() with string"); + CHECK_THROWS_WITH(j_nonobject_const.value("foo", 1), "[except.305] cannot use value() with string"); } SECTION("array") { json j_nonobject(json::value_t::array); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.value("foo", 1), std::domain_error); - CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), std::domain_error); - CHECK_THROWS_WITH(j_nonobject.value("foo", 1), "cannot use value() with array"); - CHECK_THROWS_WITH(j_nonobject_const.value("foo", 1), "cannot use value() with array"); + CHECK_THROWS_AS(j_nonobject.value("foo", 1), json::type_error); + CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), json::type_error); + CHECK_THROWS_WITH(j_nonobject.value("foo", 1), "[except.305] cannot use value() with array"); + CHECK_THROWS_WITH(j_nonobject_const.value("foo", 1), "[except.305] cannot use value() with array"); } SECTION("number (integer)") { json j_nonobject(json::value_t::number_integer); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.value("foo", 1), std::domain_error); - CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), std::domain_error); - CHECK_THROWS_WITH(j_nonobject.value("foo", 1), "cannot use value() with number"); - CHECK_THROWS_WITH(j_nonobject_const.value("foo", 1), "cannot use value() with number"); + CHECK_THROWS_AS(j_nonobject.value("foo", 1), json::type_error); + CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), json::type_error); + CHECK_THROWS_WITH(j_nonobject.value("foo", 1), "[except.305] cannot use value() with number"); + CHECK_THROWS_WITH(j_nonobject_const.value("foo", 1), "[except.305] cannot use value() with number"); } SECTION("number (unsigned)") { json j_nonobject(json::value_t::number_unsigned); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.value("foo", 1), std::domain_error); - CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), std::domain_error); - CHECK_THROWS_WITH(j_nonobject.value("foo", 1), "cannot use value() with number"); - CHECK_THROWS_WITH(j_nonobject_const.value("foo", 1), "cannot use value() with number"); + CHECK_THROWS_AS(j_nonobject.value("foo", 1), json::type_error); + CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), json::type_error); + CHECK_THROWS_WITH(j_nonobject.value("foo", 1), "[except.305] cannot use value() with number"); + CHECK_THROWS_WITH(j_nonobject_const.value("foo", 1), "[except.305] cannot use value() with number"); } SECTION("number (floating-point)") { json j_nonobject(json::value_t::number_float); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.value("foo", 1), std::domain_error); - CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), std::domain_error); - CHECK_THROWS_WITH(j_nonobject.value("foo", 1), "cannot use value() with number"); - CHECK_THROWS_WITH(j_nonobject_const.value("foo", 1), "cannot use value() with number"); + CHECK_THROWS_AS(j_nonobject.value("foo", 1), json::type_error); + CHECK_THROWS_AS(j_nonobject_const.value("foo", 1), json::type_error); + CHECK_THROWS_WITH(j_nonobject.value("foo", 1), "[except.305] cannot use value() with number"); + CHECK_THROWS_WITH(j_nonobject_const.value("foo", 1), "[except.305] cannot use value() with number"); } } } @@ -3946,75 +4092,84 @@ { json j_nonobject(json::value_t::null); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), std::domain_error); - CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), std::domain_error); - CHECK_THROWS_WITH(j_nonobject.value("/foo"_json_pointer, 1), "cannot use value() with null"); - CHECK_THROWS_WITH(j_nonobject_const.value("/foo"_json_pointer, 1), "cannot use value() with null"); + CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), json::type_error); + CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), json::type_error); + CHECK_THROWS_WITH(j_nonobject.value("/foo"_json_pointer, 1), + "[except.305] cannot use value() with null"); + CHECK_THROWS_WITH(j_nonobject_const.value("/foo"_json_pointer, 1), + "[except.305] cannot use value() with null"); } SECTION("boolean") { json j_nonobject(json::value_t::boolean); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), std::domain_error); - CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), std::domain_error); - CHECK_THROWS_WITH(j_nonobject.value("/foo"_json_pointer, 1), "cannot use value() with boolean"); + CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), json::type_error); + CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), json::type_error); + CHECK_THROWS_WITH(j_nonobject.value("/foo"_json_pointer, 1), + "[except.305] cannot use value() with boolean"); CHECK_THROWS_WITH(j_nonobject_const.value("/foo"_json_pointer, 1), - "cannot use value() with boolean"); + "[except.305] cannot use value() with boolean"); } SECTION("string") { json j_nonobject(json::value_t::string); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), std::domain_error); - CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), std::domain_error); - CHECK_THROWS_WITH(j_nonobject.value("/foo"_json_pointer, 1), "cannot use value() with string"); + CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), json::type_error); + CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), json::type_error); + CHECK_THROWS_WITH(j_nonobject.value("/foo"_json_pointer, 1), + "[except.305] cannot use value() with string"); CHECK_THROWS_WITH(j_nonobject_const.value("/foo"_json_pointer, 1), - "cannot use value() with string"); + "[except.305] cannot use value() with string"); } SECTION("array") { json j_nonobject(json::value_t::array); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), std::domain_error); - CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), std::domain_error); - CHECK_THROWS_WITH(j_nonobject.value("/foo"_json_pointer, 1), "cannot use value() with array"); - CHECK_THROWS_WITH(j_nonobject_const.value("/foo"_json_pointer, 1), "cannot use value() with array"); + CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), json::type_error); + CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), json::type_error); + CHECK_THROWS_WITH(j_nonobject.value("/foo"_json_pointer, 1), + "[except.305] cannot use value() with array"); + CHECK_THROWS_WITH(j_nonobject_const.value("/foo"_json_pointer, 1), + "[except.305] cannot use value() with array"); } SECTION("number (integer)") { json j_nonobject(json::value_t::number_integer); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), std::domain_error); - CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), std::domain_error); - CHECK_THROWS_WITH(j_nonobject.value("/foo"_json_pointer, 1), "cannot use value() with number"); + CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), json::type_error); + CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), json::type_error); + CHECK_THROWS_WITH(j_nonobject.value("/foo"_json_pointer, 1), + "[except.305] cannot use value() with number"); CHECK_THROWS_WITH(j_nonobject_const.value("/foo"_json_pointer, 1), - "cannot use value() with number"); + "[except.305] cannot use value() with number"); } SECTION("number (unsigned)") { json j_nonobject(json::value_t::number_unsigned); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), std::domain_error); - CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), std::domain_error); - CHECK_THROWS_WITH(j_nonobject.value("/foo"_json_pointer, 1), "cannot use value() with number"); + CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), json::type_error); + CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), json::type_error); + CHECK_THROWS_WITH(j_nonobject.value("/foo"_json_pointer, 1), + "[except.305] cannot use value() with number"); CHECK_THROWS_WITH(j_nonobject_const.value("/foo"_json_pointer, 1), - "cannot use value() with number"); + "[except.305] cannot use value() with number"); } SECTION("number (floating-point)") { json j_nonobject(json::value_t::number_float); const json j_nonobject_const(j_nonobject); - CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), std::domain_error); - CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), std::domain_error); - CHECK_THROWS_WITH(j_nonobject.value("/foo"_json_pointer, 1), "cannot use value() with number"); + CHECK_THROWS_AS(j_nonobject.value("/foo"_json_pointer, 1), json::type_error); + CHECK_THROWS_AS(j_nonobject_const.value("/foo"_json_pointer, 1), json::type_error); + CHECK_THROWS_WITH(j_nonobject.value("/foo"_json_pointer, 1), + "[except.305] cannot use value() with number"); CHECK_THROWS_WITH(j_nonobject_const.value("/foo"_json_pointer, 1), - "cannot use value() with number"); + "[except.305] cannot use value() with number"); } } } @@ -4089,106 +4244,120 @@ const json j_const_nonobject(j_nonobject); CHECK_NOTHROW(j_nonobject["foo"]); CHECK_NOTHROW(j_nonobject2[json::object_t::key_type("foo")]); - CHECK_THROWS_AS(j_const_nonobject["foo"], std::domain_error); - CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], std::domain_error); - CHECK_THROWS_WITH(j_const_nonobject["foo"], "cannot use operator[] with null"); + CHECK_THROWS_AS(j_const_nonobject["foo"], json::type_error); + CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], json::type_error); + CHECK_THROWS_WITH(j_const_nonobject["foo"], + "[except.304] cannot use operator[] with null"); CHECK_THROWS_WITH(j_const_nonobject[json::object_t::key_type("foo")], - "cannot use operator[] with null"); + "[except.304] cannot use operator[] with null"); } SECTION("boolean") { json j_nonobject(json::value_t::boolean); const json j_const_nonobject(j_nonobject); - CHECK_THROWS_AS(j_nonobject["foo"], std::domain_error); - CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], std::domain_error); - CHECK_THROWS_AS(j_const_nonobject["foo"], std::domain_error); - CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], std::domain_error); - CHECK_THROWS_WITH(j_nonobject["foo"], "cannot use operator[] with boolean"); + CHECK_THROWS_AS(j_nonobject["foo"], json::type_error); + CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], json::type_error); + CHECK_THROWS_AS(j_const_nonobject["foo"], json::type_error); + CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], json::type_error); + CHECK_THROWS_WITH(j_nonobject["foo"], + "[except.304] cannot use operator[] with boolean"); CHECK_THROWS_WITH(j_nonobject[json::object_t::key_type("foo")], - "cannot use operator[] with boolean"); - CHECK_THROWS_WITH(j_const_nonobject["foo"], "cannot use operator[] with boolean"); + "[except.304] cannot use operator[] with boolean"); + CHECK_THROWS_WITH(j_const_nonobject["foo"], + "[except.304] cannot use operator[] with boolean"); CHECK_THROWS_WITH(j_const_nonobject[json::object_t::key_type("foo")], - "cannot use operator[] with boolean"); + "[except.304] cannot use operator[] with boolean"); } SECTION("string") { json j_nonobject(json::value_t::string); const json j_const_nonobject(j_nonobject); - CHECK_THROWS_AS(j_nonobject["foo"], std::domain_error); - CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], std::domain_error); - CHECK_THROWS_AS(j_const_nonobject["foo"], std::domain_error); - CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], std::domain_error); - CHECK_THROWS_WITH(j_nonobject["foo"], "cannot use operator[] with string"); + CHECK_THROWS_AS(j_nonobject["foo"], json::type_error); + CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], json::type_error); + CHECK_THROWS_AS(j_const_nonobject["foo"], json::type_error); + CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], json::type_error); + CHECK_THROWS_WITH(j_nonobject["foo"], + "[except.304] cannot use operator[] with string"); CHECK_THROWS_WITH(j_nonobject[json::object_t::key_type("foo")], - "cannot use operator[] with string"); - CHECK_THROWS_WITH(j_const_nonobject["foo"], "cannot use operator[] with string"); + "[except.304] cannot use operator[] with string"); + CHECK_THROWS_WITH(j_const_nonobject["foo"], + "[except.304] cannot use operator[] with string"); CHECK_THROWS_WITH(j_const_nonobject[json::object_t::key_type("foo")], - "cannot use operator[] with string"); + "[except.304] cannot use operator[] with string"); } SECTION("array") { json j_nonobject(json::value_t::array); const json j_const_nonobject(j_nonobject); - CHECK_THROWS_AS(j_nonobject["foo"], std::domain_error); - CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], std::domain_error); - CHECK_THROWS_AS(j_const_nonobject["foo"], std::domain_error); - CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], std::domain_error); - CHECK_THROWS_WITH(j_nonobject["foo"], "cannot use operator[] with array"); - CHECK_THROWS_WITH(j_nonobject[json::object_t::key_type("foo")], "cannot use operator[] with array"); - CHECK_THROWS_WITH(j_const_nonobject["foo"], "cannot use operator[] with array"); + CHECK_THROWS_AS(j_nonobject["foo"], json::type_error); + CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], json::type_error); + CHECK_THROWS_AS(j_const_nonobject["foo"], json::type_error); + CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], json::type_error); + CHECK_THROWS_WITH(j_nonobject["foo"], + "[except.304] cannot use operator[] with array"); + CHECK_THROWS_WITH(j_nonobject[json::object_t::key_type("foo")], + "[except.304] cannot use operator[] with array"); + CHECK_THROWS_WITH(j_const_nonobject["foo"], + "[except.304] cannot use operator[] with array"); CHECK_THROWS_WITH(j_const_nonobject[json::object_t::key_type("foo")], - "cannot use operator[] with array"); + "[except.304] cannot use operator[] with array"); } SECTION("number (integer)") { json j_nonobject(json::value_t::number_integer); const json j_const_nonobject(j_nonobject); - CHECK_THROWS_AS(j_nonobject["foo"], std::domain_error); - CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], std::domain_error); - CHECK_THROWS_AS(j_const_nonobject["foo"], std::domain_error); - CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], std::domain_error); - CHECK_THROWS_WITH(j_nonobject["foo"], "cannot use operator[] with number"); + CHECK_THROWS_AS(j_nonobject["foo"], json::type_error); + CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], json::type_error); + CHECK_THROWS_AS(j_const_nonobject["foo"], json::type_error); + CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], json::type_error); + CHECK_THROWS_WITH(j_nonobject["foo"], + "[except.304] cannot use operator[] with number"); CHECK_THROWS_WITH(j_nonobject[json::object_t::key_type("foo")], - "cannot use operator[] with number"); - CHECK_THROWS_WITH(j_const_nonobject["foo"], "cannot use operator[] with number"); + "[except.304] cannot use operator[] with number"); + CHECK_THROWS_WITH(j_const_nonobject["foo"], + "[except.304] cannot use operator[] with number"); CHECK_THROWS_WITH(j_const_nonobject[json::object_t::key_type("foo")], - "cannot use operator[] with number"); + "[except.304] cannot use operator[] with number"); } SECTION("number (unsigned)") { json j_nonobject(json::value_t::number_unsigned); const json j_const_nonobject(j_nonobject); - CHECK_THROWS_AS(j_nonobject["foo"], std::domain_error); - CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], std::domain_error); - CHECK_THROWS_AS(j_const_nonobject["foo"], std::domain_error); - CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], std::domain_error); - CHECK_THROWS_WITH(j_nonobject["foo"], "cannot use operator[] with number"); + CHECK_THROWS_AS(j_nonobject["foo"], json::type_error); + CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], json::type_error); + CHECK_THROWS_AS(j_const_nonobject["foo"], json::type_error); + CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], json::type_error); + CHECK_THROWS_WITH(j_nonobject["foo"], + "[except.304] cannot use operator[] with number"); CHECK_THROWS_WITH(j_nonobject[json::object_t::key_type("foo")], - "cannot use operator[] with number"); - CHECK_THROWS_WITH(j_const_nonobject["foo"], "cannot use operator[] with number"); + "[except.304] cannot use operator[] with number"); + CHECK_THROWS_WITH(j_const_nonobject["foo"], + "[except.304] cannot use operator[] with number"); CHECK_THROWS_WITH(j_const_nonobject[json::object_t::key_type("foo")], - "cannot use operator[] with number"); + "[except.304] cannot use operator[] with number"); } SECTION("number (floating-point)") { json j_nonobject(json::value_t::number_float); const json j_const_nonobject(j_nonobject); - CHECK_THROWS_AS(j_nonobject["foo"], std::domain_error); - CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], std::domain_error); - CHECK_THROWS_AS(j_const_nonobject["foo"], std::domain_error); - CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], std::domain_error); - CHECK_THROWS_WITH(j_nonobject["foo"], "cannot use operator[] with number"); + CHECK_THROWS_AS(j_nonobject["foo"], json::type_error); + CHECK_THROWS_AS(j_nonobject[json::object_t::key_type("foo")], json::type_error); + CHECK_THROWS_AS(j_const_nonobject["foo"], json::type_error); + CHECK_THROWS_AS(j_const_nonobject[json::object_t::key_type("foo")], json::type_error); + CHECK_THROWS_WITH(j_nonobject["foo"], + "[except.304] cannot use operator[] with number"); CHECK_THROWS_WITH(j_nonobject[json::object_t::key_type("foo")], - "cannot use operator[] with number"); - CHECK_THROWS_WITH(j_const_nonobject["foo"], "cannot use operator[] with number"); + "[except.304] cannot use operator[] with number"); + CHECK_THROWS_WITH(j_const_nonobject["foo"], + "[except.304] cannot use operator[] with number"); CHECK_THROWS_WITH(j_const_nonobject[json::object_t::key_type("foo")], - "cannot use operator[] with number"); + "[except.304] cannot use operator[] with number"); } } } @@ -4327,32 +4496,34 @@ { json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}, {"d", false}, {"e", true}}; json jobject2 = {{"a", "a"}, {"b", 1}, {"c", 17u}}; - CHECK_THROWS_AS(jobject.erase(jobject2.begin()), std::domain_error); - CHECK_THROWS_AS(jobject.erase(jobject.begin(), jobject2.end()), std::domain_error); - CHECK_THROWS_AS(jobject.erase(jobject2.begin(), jobject.end()), std::domain_error); - CHECK_THROWS_AS(jobject.erase(jobject2.begin(), jobject2.end()), std::domain_error); - CHECK_THROWS_WITH(jobject.erase(jobject2.begin()), "iterator does not fit current value"); + CHECK_THROWS_AS(jobject.erase(jobject2.begin()), json::invalid_iterator); + CHECK_THROWS_AS(jobject.erase(jobject.begin(), jobject2.end()), json::invalid_iterator); + CHECK_THROWS_AS(jobject.erase(jobject2.begin(), jobject.end()), json::invalid_iterator); + CHECK_THROWS_AS(jobject.erase(jobject2.begin(), jobject2.end()), json::invalid_iterator); + CHECK_THROWS_WITH(jobject.erase(jobject2.begin()), + "[except.103] iterator does not fit current value"); CHECK_THROWS_WITH(jobject.erase(jobject.begin(), jobject2.end()), - "iterators do not fit current value"); + "[except.102] iterators do not fit current value"); CHECK_THROWS_WITH(jobject.erase(jobject2.begin(), jobject.end()), - "iterators do not fit current value"); + "[except.102] iterators do not fit current value"); CHECK_THROWS_WITH(jobject.erase(jobject2.begin(), jobject2.end()), - "iterators do not fit current value"); + "[except.102] iterators do not fit current value"); } { json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}, {"d", false}, {"e", true}}; json jobject2 = {{"a", "a"}, {"b", 1}, {"c", 17u}}; - CHECK_THROWS_AS(jobject.erase(jobject2.cbegin()), std::domain_error); - CHECK_THROWS_AS(jobject.erase(jobject.cbegin(), jobject2.cend()), std::domain_error); - CHECK_THROWS_AS(jobject.erase(jobject2.cbegin(), jobject.cend()), std::domain_error); - CHECK_THROWS_AS(jobject.erase(jobject2.cbegin(), jobject2.cend()), std::domain_error); - CHECK_THROWS_WITH(jobject.erase(jobject2.cbegin()), "iterator does not fit current value"); + CHECK_THROWS_AS(jobject.erase(jobject2.cbegin()), json::invalid_iterator); + CHECK_THROWS_AS(jobject.erase(jobject.cbegin(), jobject2.cend()), json::invalid_iterator); + CHECK_THROWS_AS(jobject.erase(jobject2.cbegin(), jobject.cend()), json::invalid_iterator); + CHECK_THROWS_AS(jobject.erase(jobject2.cbegin(), jobject2.cend()), json::invalid_iterator); + CHECK_THROWS_WITH(jobject.erase(jobject2.cbegin()), + "[except.103] iterator does not fit current value"); CHECK_THROWS_WITH(jobject.erase(jobject.cbegin(), jobject2.cend()), - "iterators do not fit current value"); + "[except.102] iterators do not fit current value"); CHECK_THROWS_WITH(jobject.erase(jobject2.cbegin(), jobject.cend()), - "iterators do not fit current value"); + "[except.102] iterators do not fit current value"); CHECK_THROWS_WITH(jobject.erase(jobject2.cbegin(), jobject2.cend()), - "iterators do not fit current value"); + "[except.102] iterators do not fit current value"); } } } @@ -4362,43 +4533,43 @@ SECTION("null") { json j_nonobject(json::value_t::null); - CHECK_THROWS_AS(j_nonobject.erase("foo"), std::domain_error); - CHECK_THROWS_WITH(j_nonobject.erase("foo"), "cannot use erase() with null"); + CHECK_THROWS_AS(j_nonobject.erase("foo"), json::type_error); + CHECK_THROWS_WITH(j_nonobject.erase("foo"), "[except.306] cannot use erase() with null"); } SECTION("boolean") { json j_nonobject(json::value_t::boolean); - CHECK_THROWS_AS(j_nonobject.erase("foo"), std::domain_error); - CHECK_THROWS_WITH(j_nonobject.erase("foo"), "cannot use erase() with boolean"); + CHECK_THROWS_AS(j_nonobject.erase("foo"), json::type_error); + CHECK_THROWS_WITH(j_nonobject.erase("foo"), "[except.306] cannot use erase() with boolean"); } SECTION("string") { json j_nonobject(json::value_t::string); - CHECK_THROWS_AS(j_nonobject.erase("foo"), std::domain_error); - CHECK_THROWS_WITH(j_nonobject.erase("foo"), "cannot use erase() with string"); + CHECK_THROWS_AS(j_nonobject.erase("foo"), json::type_error); + CHECK_THROWS_WITH(j_nonobject.erase("foo"), "[except.306] cannot use erase() with string"); } SECTION("array") { json j_nonobject(json::value_t::array); - CHECK_THROWS_AS(j_nonobject.erase("foo"), std::domain_error); - CHECK_THROWS_WITH(j_nonobject.erase("foo"), "cannot use erase() with array"); + CHECK_THROWS_AS(j_nonobject.erase("foo"), json::type_error); + CHECK_THROWS_WITH(j_nonobject.erase("foo"), "[except.306] cannot use erase() with array"); } SECTION("number (integer)") { json j_nonobject(json::value_t::number_integer); - CHECK_THROWS_AS(j_nonobject.erase("foo"), std::domain_error); - CHECK_THROWS_WITH(j_nonobject.erase("foo"), "cannot use erase() with number"); + CHECK_THROWS_AS(j_nonobject.erase("foo"), json::type_error); + CHECK_THROWS_WITH(j_nonobject.erase("foo"), "[except.306] cannot use erase() with number"); } SECTION("number (floating-point)") { json j_nonobject(json::value_t::number_float); - CHECK_THROWS_AS(j_nonobject.erase("foo"), std::domain_error); - CHECK_THROWS_WITH(j_nonobject.erase("foo"), "cannot use erase() with number"); + CHECK_THROWS_AS(j_nonobject.erase("foo"), json::type_error); + CHECK_THROWS_WITH(j_nonobject.erase("foo"), "[except.306] cannot use erase() with number"); } } } @@ -4588,17 +4759,17 @@ { { json j; - CHECK_THROWS_AS(j.front(), std::out_of_range); - CHECK_THROWS_AS(j.back(), std::out_of_range); - CHECK_THROWS_WITH(j.front(), "cannot get value"); - CHECK_THROWS_WITH(j.back(), "cannot get value"); + CHECK_THROWS_AS(j.front(), json::invalid_iterator); + CHECK_THROWS_AS(j.back(), json::invalid_iterator); + CHECK_THROWS_WITH(j.front(), "[except.114] cannot get value"); + CHECK_THROWS_WITH(j.back(), "[except.114] cannot get value"); } { const json j{}; - CHECK_THROWS_AS(j.front(), std::out_of_range); - CHECK_THROWS_AS(j.back(), std::out_of_range); - CHECK_THROWS_WITH(j.front(), "cannot get value"); - CHECK_THROWS_WITH(j.back(), "cannot get value"); + CHECK_THROWS_AS(j.front(), json::invalid_iterator); + CHECK_THROWS_AS(j.back(), json::invalid_iterator); + CHECK_THROWS_WITH(j.front(), "[except.114] cannot get value"); + CHECK_THROWS_WITH(j.back(), "[except.114] cannot get value"); } } @@ -4679,13 +4850,13 @@ { { json j; - CHECK_THROWS_AS(j.erase(j.begin()), std::domain_error); - CHECK_THROWS_WITH(j.erase(j.begin()), "cannot use erase() with null"); + CHECK_THROWS_AS(j.erase(j.begin()), json::type_error); + CHECK_THROWS_WITH(j.erase(j.begin()), "[except.306] cannot use erase() with null"); } { json j; - CHECK_THROWS_AS(j.erase(j.cbegin()), std::domain_error); - CHECK_THROWS_WITH(j.erase(j.begin()), "cannot use erase() with null"); + CHECK_THROWS_AS(j.erase(j.cbegin()), json::type_error); + CHECK_THROWS_WITH(j.erase(j.begin()), "[except.306] cannot use erase() with null"); } } @@ -4776,13 +4947,13 @@ { { json j = "foo"; - CHECK_THROWS_AS(j.erase(j.end()), std::out_of_range); - CHECK_THROWS_WITH(j.erase(j.end()), "iterator out of range"); + CHECK_THROWS_AS(j.erase(j.end()), json::invalid_iterator); + CHECK_THROWS_WITH(j.erase(j.end()), "[except.105] iterator out of range"); } { json j = "bar"; - CHECK_THROWS_AS(j.erase(j.cend()), std::out_of_range); - CHECK_THROWS_WITH(j.erase(j.cend()), "iterator out of range"); + CHECK_THROWS_AS(j.erase(j.cend()), json::invalid_iterator); + CHECK_THROWS_WITH(j.erase(j.cend()), "[except.105] iterator out of range"); } } @@ -4790,13 +4961,13 @@ { { json j = false; - CHECK_THROWS_AS(j.erase(j.end()), std::out_of_range); - CHECK_THROWS_WITH(j.erase(j.end()), "iterator out of range"); + CHECK_THROWS_AS(j.erase(j.end()), json::invalid_iterator); + CHECK_THROWS_WITH(j.erase(j.end()), "[except.105] iterator out of range"); } { json j = true; - CHECK_THROWS_AS(j.erase(j.cend()), std::out_of_range); - CHECK_THROWS_WITH(j.erase(j.cend()), "iterator out of range"); + CHECK_THROWS_AS(j.erase(j.cend()), json::invalid_iterator); + CHECK_THROWS_WITH(j.erase(j.cend()), "[except.105] iterator out of range"); } } @@ -4804,13 +4975,13 @@ { { json j = 17; - CHECK_THROWS_AS(j.erase(j.end()), std::out_of_range); - CHECK_THROWS_WITH(j.erase(j.end()), "iterator out of range"); + CHECK_THROWS_AS(j.erase(j.end()), json::invalid_iterator); + CHECK_THROWS_WITH(j.erase(j.end()), "[except.105] iterator out of range"); } { json j = 17; - CHECK_THROWS_AS(j.erase(j.cend()), std::out_of_range); - CHECK_THROWS_WITH(j.erase(j.cend()), "iterator out of range"); + CHECK_THROWS_AS(j.erase(j.cend()), json::invalid_iterator); + CHECK_THROWS_WITH(j.erase(j.cend()), "[except.105] iterator out of range"); } } @@ -4818,13 +4989,13 @@ { { json j = 17u; - CHECK_THROWS_AS(j.erase(j.end()), std::out_of_range); - CHECK_THROWS_WITH(j.erase(j.end()), "iterator out of range"); + CHECK_THROWS_AS(j.erase(j.end()), json::invalid_iterator); + CHECK_THROWS_WITH(j.erase(j.end()), "[except.105] iterator out of range"); } { json j = 17u; - CHECK_THROWS_AS(j.erase(j.cend()), std::out_of_range); - CHECK_THROWS_WITH(j.erase(j.cend()), "iterator out of range"); + CHECK_THROWS_AS(j.erase(j.cend()), json::invalid_iterator); + CHECK_THROWS_WITH(j.erase(j.cend()), "[except.105] iterator out of range"); } } @@ -4832,13 +5003,13 @@ { { json j = 23.42; - CHECK_THROWS_AS(j.erase(j.end()), std::out_of_range); - CHECK_THROWS_WITH(j.erase(j.end()), "iterator out of range"); + CHECK_THROWS_AS(j.erase(j.end()), json::invalid_iterator); + CHECK_THROWS_WITH(j.erase(j.end()), "[except.105] iterator out of range"); } { json j = 23.42; - CHECK_THROWS_AS(j.erase(j.cend()), std::out_of_range); - CHECK_THROWS_WITH(j.erase(j.cend()), "iterator out of range"); + CHECK_THROWS_AS(j.erase(j.cend()), json::invalid_iterator); + CHECK_THROWS_WITH(j.erase(j.cend()), "[except.105] iterator out of range"); } } } @@ -4849,13 +5020,13 @@ { { json j; - CHECK_THROWS_AS(j.erase(j.begin(), j.end()), std::domain_error); - CHECK_THROWS_WITH(j.erase(j.begin(), j.end()), "cannot use erase() with null"); + CHECK_THROWS_AS(j.erase(j.begin(), j.end()), json::type_error); + CHECK_THROWS_WITH(j.erase(j.begin(), j.end()), "[except.306] cannot use erase() with null"); } { json j; - CHECK_THROWS_AS(j.erase(j.cbegin(), j.cend()), std::domain_error); - CHECK_THROWS_WITH(j.erase(j.cbegin(), j.cend()), "cannot use erase() with null"); + CHECK_THROWS_AS(j.erase(j.cbegin(), j.cend()), json::type_error); + CHECK_THROWS_WITH(j.erase(j.cbegin(), j.cend()), "[except.306] cannot use erase() with null"); } } @@ -4946,17 +5117,17 @@ { { json j = "foo"; - CHECK_THROWS_AS(j.erase(j.end(), j.end()), std::out_of_range); - CHECK_THROWS_AS(j.erase(j.begin(), j.begin()), std::out_of_range); - CHECK_THROWS_WITH(j.erase(j.end(), j.end()), "iterators out of range"); - CHECK_THROWS_WITH(j.erase(j.begin(), j.begin()), "iterators out of range"); + CHECK_THROWS_AS(j.erase(j.end(), j.end()), json::invalid_iterator); + CHECK_THROWS_AS(j.erase(j.begin(), j.begin()), json::invalid_iterator); + CHECK_THROWS_WITH(j.erase(j.end(), j.end()), "[except.104] iterators out of range"); + CHECK_THROWS_WITH(j.erase(j.begin(), j.begin()), "[except.104] iterators out of range"); } { json j = "bar"; - CHECK_THROWS_AS(j.erase(j.cend(), j.cend()), std::out_of_range); - CHECK_THROWS_AS(j.erase(j.cbegin(), j.cbegin()), std::out_of_range); - CHECK_THROWS_WITH(j.erase(j.cend(), j.cend()), "iterators out of range"); - CHECK_THROWS_WITH(j.erase(j.cbegin(), j.cbegin()), "iterators out of range"); + CHECK_THROWS_AS(j.erase(j.cend(), j.cend()), json::invalid_iterator); + CHECK_THROWS_AS(j.erase(j.cbegin(), j.cbegin()), json::invalid_iterator); + CHECK_THROWS_WITH(j.erase(j.cend(), j.cend()), "[except.104] iterators out of range"); + CHECK_THROWS_WITH(j.erase(j.cbegin(), j.cbegin()), "[except.104] iterators out of range"); } } @@ -4964,17 +5135,17 @@ { { json j = false; - CHECK_THROWS_AS(j.erase(j.end(), j.end()), std::out_of_range); - CHECK_THROWS_AS(j.erase(j.begin(), j.begin()), std::out_of_range); - CHECK_THROWS_WITH(j.erase(j.end(), j.end()), "iterators out of range"); - CHECK_THROWS_WITH(j.erase(j.begin(), j.begin()), "iterators out of range"); + CHECK_THROWS_AS(j.erase(j.end(), j.end()), json::invalid_iterator); + CHECK_THROWS_AS(j.erase(j.begin(), j.begin()), json::invalid_iterator); + CHECK_THROWS_WITH(j.erase(j.end(), j.end()), "[except.104] iterators out of range"); + CHECK_THROWS_WITH(j.erase(j.begin(), j.begin()), "[except.104] iterators out of range"); } { json j = true; - CHECK_THROWS_AS(j.erase(j.cend(), j.cend()), std::out_of_range); - CHECK_THROWS_AS(j.erase(j.cbegin(), j.cbegin()), std::out_of_range); - CHECK_THROWS_WITH(j.erase(j.cend(), j.cend()), "iterators out of range"); - CHECK_THROWS_WITH(j.erase(j.cbegin(), j.cbegin()), "iterators out of range"); + CHECK_THROWS_AS(j.erase(j.cend(), j.cend()), json::invalid_iterator); + CHECK_THROWS_AS(j.erase(j.cbegin(), j.cbegin()), json::invalid_iterator); + CHECK_THROWS_WITH(j.erase(j.cend(), j.cend()), "[except.104] iterators out of range"); + CHECK_THROWS_WITH(j.erase(j.cbegin(), j.cbegin()), "[except.104] iterators out of range"); } } @@ -4982,17 +5153,17 @@ { { json j = 17; - CHECK_THROWS_AS(j.erase(j.end(), j.end()), std::out_of_range); - CHECK_THROWS_AS(j.erase(j.begin(), j.begin()), std::out_of_range); - CHECK_THROWS_WITH(j.erase(j.end(), j.end()), "iterators out of range"); - CHECK_THROWS_WITH(j.erase(j.begin(), j.begin()), "iterators out of range"); + CHECK_THROWS_AS(j.erase(j.end(), j.end()), json::invalid_iterator); + CHECK_THROWS_AS(j.erase(j.begin(), j.begin()), json::invalid_iterator); + CHECK_THROWS_WITH(j.erase(j.end(), j.end()), "[except.104] iterators out of range"); + CHECK_THROWS_WITH(j.erase(j.begin(), j.begin()), "[except.104] iterators out of range"); } { json j = 17; - CHECK_THROWS_AS(j.erase(j.cend(), j.cend()), std::out_of_range); - CHECK_THROWS_AS(j.erase(j.cbegin(), j.cbegin()), std::out_of_range); - CHECK_THROWS_WITH(j.erase(j.cend(), j.cend()), "iterators out of range"); - CHECK_THROWS_WITH(j.erase(j.cbegin(), j.cbegin()), "iterators out of range"); + CHECK_THROWS_AS(j.erase(j.cend(), j.cend()), json::invalid_iterator); + CHECK_THROWS_AS(j.erase(j.cbegin(), j.cbegin()), json::invalid_iterator); + CHECK_THROWS_WITH(j.erase(j.cend(), j.cend()), "[except.104] iterators out of range"); + CHECK_THROWS_WITH(j.erase(j.cbegin(), j.cbegin()), "[except.104] iterators out of range"); } } @@ -5000,17 +5171,17 @@ { { json j = 17u; - CHECK_THROWS_AS(j.erase(j.end(), j.end()), std::out_of_range); - CHECK_THROWS_AS(j.erase(j.begin(), j.begin()), std::out_of_range); - CHECK_THROWS_WITH(j.erase(j.end(), j.end()), "iterators out of range"); - CHECK_THROWS_WITH(j.erase(j.begin(), j.begin()), "iterators out of range"); + CHECK_THROWS_AS(j.erase(j.end(), j.end()), json::invalid_iterator); + CHECK_THROWS_AS(j.erase(j.begin(), j.begin()), json::invalid_iterator); + CHECK_THROWS_WITH(j.erase(j.end(), j.end()), "[except.104] iterators out of range"); + CHECK_THROWS_WITH(j.erase(j.begin(), j.begin()), "[except.104] iterators out of range"); } { json j = 17u; - CHECK_THROWS_AS(j.erase(j.cend(), j.cend()), std::out_of_range); - CHECK_THROWS_AS(j.erase(j.cbegin(), j.cbegin()), std::out_of_range); - CHECK_THROWS_WITH(j.erase(j.cend(), j.cend()), "iterators out of range"); - CHECK_THROWS_WITH(j.erase(j.cbegin(), j.cbegin()), "iterators out of range"); + CHECK_THROWS_AS(j.erase(j.cend(), j.cend()), json::invalid_iterator); + CHECK_THROWS_AS(j.erase(j.cbegin(), j.cbegin()), json::invalid_iterator); + CHECK_THROWS_WITH(j.erase(j.cend(), j.cend()), "[except.104] iterators out of range"); + CHECK_THROWS_WITH(j.erase(j.cbegin(), j.cbegin()), "[except.104] iterators out of range"); } } @@ -5018,17 +5189,17 @@ { { json j = 23.42; - CHECK_THROWS_AS(j.erase(j.end(), j.end()), std::out_of_range); - CHECK_THROWS_AS(j.erase(j.begin(), j.begin()), std::out_of_range); - CHECK_THROWS_WITH(j.erase(j.end(), j.end()), "iterators out of range"); - CHECK_THROWS_WITH(j.erase(j.begin(), j.begin()), "iterators out of range"); + CHECK_THROWS_AS(j.erase(j.end(), j.end()), json::invalid_iterator); + CHECK_THROWS_AS(j.erase(j.begin(), j.begin()), json::invalid_iterator); + CHECK_THROWS_WITH(j.erase(j.end(), j.end()), "[except.104] iterators out of range"); + CHECK_THROWS_WITH(j.erase(j.begin(), j.begin()), "[except.104] iterators out of range"); } { json j = 23.42; - CHECK_THROWS_AS(j.erase(j.cend(), j.cend()), std::out_of_range); - CHECK_THROWS_AS(j.erase(j.cbegin(), j.cbegin()), std::out_of_range); - CHECK_THROWS_WITH(j.erase(j.cend(), j.cend()), "iterators out of range"); - CHECK_THROWS_WITH(j.erase(j.cbegin(), j.cbegin()), "iterators out of range"); + CHECK_THROWS_AS(j.erase(j.cend(), j.cend()), json::invalid_iterator); + CHECK_THROWS_AS(j.erase(j.cbegin(), j.cbegin()), json::invalid_iterator); + CHECK_THROWS_WITH(j.erase(j.cend(), j.cend()), "[except.104] iterators out of range"); + CHECK_THROWS_WITH(j.erase(j.cbegin(), j.cbegin()), "[except.104] iterators out of range"); } } } @@ -5232,23 +5403,23 @@ { auto it = j.begin(); auto cit = j_const.cbegin(); - CHECK_THROWS_AS(it.key(), std::domain_error); - CHECK_THROWS_WITH(it.key(), "cannot use key() for non-object iterators"); + CHECK_THROWS_AS(it.key(), json::invalid_iterator); + CHECK_THROWS_WITH(it.key(), "[except.107] cannot use key() for non-object iterators"); CHECK(it.value() == json(true)); - CHECK_THROWS_AS(cit.key(), std::domain_error); - CHECK_THROWS_WITH(cit.key(), "cannot use key() for non-object iterators"); + CHECK_THROWS_AS(cit.key(), json::invalid_iterator); + CHECK_THROWS_WITH(cit.key(), "[except.107] cannot use key() for non-object iterators"); CHECK(cit.value() == json(true)); auto rit = j.rend(); auto crit = j.crend(); - CHECK_THROWS_AS(rit.key(), std::domain_error); - CHECK_THROWS_AS(rit.value(), std::out_of_range); - CHECK_THROWS_AS(crit.key(), std::domain_error); - CHECK_THROWS_AS(crit.value(), std::out_of_range); - CHECK_THROWS_WITH(rit.key(), "cannot use key() for non-object iterators"); - CHECK_THROWS_WITH(rit.value(), "cannot get value"); - CHECK_THROWS_WITH(crit.key(), "cannot use key() for non-object iterators"); - CHECK_THROWS_WITH(crit.value(), "cannot get value"); + CHECK_THROWS_AS(rit.key(), json::invalid_iterator); + CHECK_THROWS_AS(rit.value(), json::invalid_iterator); + CHECK_THROWS_AS(crit.key(), json::invalid_iterator); + CHECK_THROWS_AS(crit.value(), json::invalid_iterator); + CHECK_THROWS_WITH(rit.key(), "[except.107] cannot use key() for non-object iterators"); + CHECK_THROWS_WITH(rit.value(), "[except.114] cannot get value"); + CHECK_THROWS_WITH(crit.key(), "[except.107] cannot use key() for non-object iterators"); + CHECK_THROWS_WITH(crit.value(), "[except.114] cannot get value"); } } @@ -5436,23 +5607,23 @@ { auto it = j.begin(); auto cit = j_const.cbegin(); - CHECK_THROWS_AS(it.key(), std::domain_error); - CHECK_THROWS_WITH(it.key(), "cannot use key() for non-object iterators"); + CHECK_THROWS_AS(it.key(), json::invalid_iterator); + CHECK_THROWS_WITH(it.key(), "[except.107] cannot use key() for non-object iterators"); CHECK(it.value() == json("hello world")); - CHECK_THROWS_AS(cit.key(), std::domain_error); - CHECK_THROWS_WITH(cit.key(), "cannot use key() for non-object iterators"); + CHECK_THROWS_AS(cit.key(), json::invalid_iterator); + CHECK_THROWS_WITH(cit.key(), "[except.107] cannot use key() for non-object iterators"); CHECK(cit.value() == json("hello world")); auto rit = j.rend(); auto crit = j.crend(); - CHECK_THROWS_AS(rit.key(), std::domain_error); - CHECK_THROWS_AS(rit.value(), std::out_of_range); - CHECK_THROWS_AS(crit.key(), std::domain_error); - CHECK_THROWS_AS(crit.value(), std::out_of_range); - CHECK_THROWS_WITH(rit.key(), "cannot use key() for non-object iterators"); - CHECK_THROWS_WITH(rit.value(), "cannot get value"); - CHECK_THROWS_WITH(crit.key(), "cannot use key() for non-object iterators"); - CHECK_THROWS_WITH(crit.value(), "cannot get value"); + CHECK_THROWS_AS(rit.key(), json::invalid_iterator); + CHECK_THROWS_AS(rit.value(), json::invalid_iterator); + CHECK_THROWS_AS(crit.key(), json::invalid_iterator); + CHECK_THROWS_AS(crit.value(), json::invalid_iterator); + CHECK_THROWS_WITH(rit.key(), "[except.107] cannot use key() for non-object iterators"); + CHECK_THROWS_WITH(rit.value(), "[except.114] cannot get value"); + CHECK_THROWS_WITH(crit.key(), "[except.107] cannot use key() for non-object iterators"); + CHECK_THROWS_WITH(crit.value(), "[except.114] cannot get value"); } } @@ -5633,11 +5804,11 @@ { auto it = j.begin(); auto cit = j_const.cbegin(); - CHECK_THROWS_AS(it.key(), std::domain_error); - CHECK_THROWS_WITH(it.key(), "cannot use key() for non-object iterators"); + CHECK_THROWS_AS(it.key(), json::invalid_iterator); + CHECK_THROWS_WITH(it.key(), "[except.107] cannot use key() for non-object iterators"); CHECK(it.value() == json(1)); - CHECK_THROWS_AS(cit.key(), std::domain_error); - CHECK_THROWS_WITH(cit.key(), "cannot use key() for non-object iterators"); + CHECK_THROWS_AS(cit.key(), json::invalid_iterator); + CHECK_THROWS_WITH(cit.key(), "[except.107] cannot use key() for non-object iterators"); CHECK(cit.value() == json(1)); } } @@ -6010,23 +6181,23 @@ { auto it = j.begin(); auto cit = j_const.cbegin(); - CHECK_THROWS_AS(it.key(), std::domain_error); - CHECK_THROWS_WITH(it.key(), "cannot use key() for non-object iterators"); + CHECK_THROWS_AS(it.key(), json::invalid_iterator); + CHECK_THROWS_WITH(it.key(), "[except.107] cannot use key() for non-object iterators"); CHECK(it.value() == json(23)); - CHECK_THROWS_AS(cit.key(), std::domain_error); - CHECK_THROWS_WITH(cit.key(), "cannot use key() for non-object iterators"); + CHECK_THROWS_AS(cit.key(), json::invalid_iterator); + CHECK_THROWS_WITH(cit.key(), "[except.107] cannot use key() for non-object iterators"); CHECK(cit.value() == json(23)); auto rit = j.rend(); auto crit = j.crend(); - CHECK_THROWS_AS(rit.key(), std::domain_error); - CHECK_THROWS_AS(rit.value(), std::out_of_range); - CHECK_THROWS_AS(crit.key(), std::domain_error); - CHECK_THROWS_AS(crit.value(), std::out_of_range); - CHECK_THROWS_WITH(rit.key(), "cannot use key() for non-object iterators"); - CHECK_THROWS_WITH(rit.value(), "cannot get value"); - CHECK_THROWS_WITH(crit.key(), "cannot use key() for non-object iterators"); - CHECK_THROWS_WITH(crit.value(), "cannot get value"); + CHECK_THROWS_AS(rit.key(), json::invalid_iterator); + CHECK_THROWS_AS(rit.value(), json::invalid_iterator); + CHECK_THROWS_AS(crit.key(), json::invalid_iterator); + CHECK_THROWS_AS(crit.value(), json::invalid_iterator); + CHECK_THROWS_WITH(rit.key(), "[except.107] cannot use key() for non-object iterators"); + CHECK_THROWS_WITH(rit.value(), "[except.114] cannot get value"); + CHECK_THROWS_WITH(crit.key(), "[except.107] cannot use key() for non-object iterators"); + CHECK_THROWS_WITH(crit.value(), "[except.114] cannot get value"); } } @@ -6214,23 +6385,23 @@ { auto it = j.begin(); auto cit = j_const.cbegin(); - CHECK_THROWS_AS(it.key(), std::domain_error); - CHECK_THROWS_WITH(it.key(), "cannot use key() for non-object iterators"); + CHECK_THROWS_AS(it.key(), json::invalid_iterator); + CHECK_THROWS_WITH(it.key(), "[except.107] cannot use key() for non-object iterators"); CHECK(it.value() == json(23)); - CHECK_THROWS_AS(cit.key(), std::domain_error); - CHECK_THROWS_WITH(cit.key(), "cannot use key() for non-object iterators"); + CHECK_THROWS_AS(cit.key(), json::invalid_iterator); + CHECK_THROWS_WITH(cit.key(), "[except.107] cannot use key() for non-object iterators"); CHECK(cit.value() == json(23)); auto rit = j.rend(); auto crit = j.crend(); - CHECK_THROWS_AS(rit.key(), std::domain_error); - CHECK_THROWS_AS(rit.value(), std::out_of_range); - CHECK_THROWS_AS(crit.key(), std::domain_error); - CHECK_THROWS_AS(crit.value(), std::out_of_range); - CHECK_THROWS_WITH(rit.key(), "cannot use key() for non-object iterators"); - CHECK_THROWS_WITH(rit.value(), "cannot get value"); - CHECK_THROWS_WITH(crit.key(), "cannot use key() for non-object iterators"); - CHECK_THROWS_WITH(crit.value(), "cannot get value"); + CHECK_THROWS_AS(rit.key(), json::invalid_iterator); + CHECK_THROWS_AS(rit.value(), json::invalid_iterator); + CHECK_THROWS_AS(crit.key(), json::invalid_iterator); + CHECK_THROWS_AS(crit.value(), json::invalid_iterator); + CHECK_THROWS_WITH(rit.key(), "[except.107] cannot use key() for non-object iterators"); + CHECK_THROWS_WITH(rit.value(), "[except.114] cannot get value"); + CHECK_THROWS_WITH(crit.key(), "[except.107] cannot use key() for non-object iterators"); + CHECK_THROWS_WITH(crit.value(), "[except.114] cannot get value"); } } @@ -6418,23 +6589,23 @@ { auto it = j.begin(); auto cit = j_const.cbegin(); - CHECK_THROWS_AS(it.key(), std::domain_error); - CHECK_THROWS_WITH(it.key(), "cannot use key() for non-object iterators"); + CHECK_THROWS_AS(it.key(), json::invalid_iterator); + CHECK_THROWS_WITH(it.key(), "[except.107] cannot use key() for non-object iterators"); CHECK(it.value() == json(23.42)); - CHECK_THROWS_AS(cit.key(), std::domain_error); - CHECK_THROWS_WITH(cit.key(), "cannot use key() for non-object iterators"); + CHECK_THROWS_AS(cit.key(), json::invalid_iterator); + CHECK_THROWS_WITH(cit.key(), "[except.107] cannot use key() for non-object iterators"); CHECK(cit.value() == json(23.42)); auto rit = j.rend(); auto crit = j.crend(); - CHECK_THROWS_AS(rit.key(), std::domain_error); - CHECK_THROWS_AS(rit.value(), std::out_of_range); - CHECK_THROWS_AS(crit.key(), std::domain_error); - CHECK_THROWS_AS(crit.value(), std::out_of_range); - CHECK_THROWS_WITH(rit.key(), "cannot use key() for non-object iterators"); - CHECK_THROWS_WITH(rit.value(), "cannot get value"); - CHECK_THROWS_WITH(crit.key(), "cannot use key() for non-object iterators"); - CHECK_THROWS_WITH(crit.value(), "cannot get value"); + CHECK_THROWS_AS(rit.key(), json::invalid_iterator); + CHECK_THROWS_AS(rit.value(), json::invalid_iterator); + CHECK_THROWS_AS(crit.key(), json::invalid_iterator); + CHECK_THROWS_AS(crit.value(), json::invalid_iterator); + CHECK_THROWS_WITH(rit.key(), "[except.107] cannot use key() for non-object iterators"); + CHECK_THROWS_WITH(rit.value(), "[except.114] cannot get value"); + CHECK_THROWS_WITH(crit.key(), "[except.107] cannot use key() for non-object iterators"); + CHECK_THROWS_WITH(crit.value(), "[except.114] cannot get value"); } } @@ -6492,25 +6663,25 @@ { auto it = j.begin(); auto cit = j_const.cbegin(); - CHECK_THROWS_AS(it.key(), std::domain_error); - CHECK_THROWS_AS(it.value(), std::out_of_range); - CHECK_THROWS_AS(cit.key(), std::domain_error); - CHECK_THROWS_AS(cit.value(), std::out_of_range); - CHECK_THROWS_WITH(it.key(), "cannot use key() for non-object iterators"); - CHECK_THROWS_WITH(it.value(), "cannot get value"); - CHECK_THROWS_WITH(cit.key(), "cannot use key() for non-object iterators"); - CHECK_THROWS_WITH(cit.value(), "cannot get value"); + CHECK_THROWS_AS(it.key(), json::invalid_iterator); + CHECK_THROWS_AS(it.value(), json::invalid_iterator); + CHECK_THROWS_AS(cit.key(), json::invalid_iterator); + CHECK_THROWS_AS(cit.value(), json::invalid_iterator); + CHECK_THROWS_WITH(it.key(), "[except.107] cannot use key() for non-object iterators"); + CHECK_THROWS_WITH(it.value(), "[except.114] cannot get value"); + CHECK_THROWS_WITH(cit.key(), "[except.107] cannot use key() for non-object iterators"); + CHECK_THROWS_WITH(cit.value(), "[except.114] cannot get value"); auto rit = j.rend(); auto crit = j.crend(); - CHECK_THROWS_AS(rit.key(), std::domain_error); - CHECK_THROWS_AS(rit.value(), std::out_of_range); - CHECK_THROWS_AS(crit.key(), std::domain_error); - CHECK_THROWS_AS(crit.value(), std::out_of_range); - CHECK_THROWS_WITH(rit.key(), "cannot use key() for non-object iterators"); - CHECK_THROWS_WITH(rit.value(), "cannot get value"); - CHECK_THROWS_WITH(crit.key(), "cannot use key() for non-object iterators"); - CHECK_THROWS_WITH(crit.value(), "cannot get value"); + CHECK_THROWS_AS(rit.key(), json::invalid_iterator); + CHECK_THROWS_AS(rit.value(), json::invalid_iterator); + CHECK_THROWS_AS(crit.key(), json::invalid_iterator); + CHECK_THROWS_AS(crit.value(), json::invalid_iterator); + CHECK_THROWS_WITH(rit.key(), "[except.107] cannot use key() for non-object iterators"); + CHECK_THROWS_WITH(rit.value(), "[except.114] cannot get value"); + CHECK_THROWS_WITH(crit.key(), "[except.107] cannot use key() for non-object iterators"); + CHECK_THROWS_WITH(crit.value(), "[except.114] cannot get value"); } } } @@ -6563,22 +6734,22 @@ { if (j.type() == json::value_t::object) { - CHECK_THROWS_AS(it1 < it1, std::domain_error); - CHECK_THROWS_AS(it1 < it2, std::domain_error); - CHECK_THROWS_AS(it2 < it3, std::domain_error); - CHECK_THROWS_AS(it1 < it3, std::domain_error); - CHECK_THROWS_AS(it1_c < it1_c, std::domain_error); - CHECK_THROWS_AS(it1_c < it2_c, std::domain_error); - CHECK_THROWS_AS(it2_c < it3_c, std::domain_error); - CHECK_THROWS_AS(it1_c < it3_c, std::domain_error); - CHECK_THROWS_WITH(it1 < it1, "cannot compare order of object iterators"); - CHECK_THROWS_WITH(it1 < it2, "cannot compare order of object iterators"); - CHECK_THROWS_WITH(it2 < it3, "cannot compare order of object iterators"); - CHECK_THROWS_WITH(it1 < it3, "cannot compare order of object iterators"); - CHECK_THROWS_WITH(it1_c < it1_c, "cannot compare order of object iterators"); - CHECK_THROWS_WITH(it1_c < it2_c, "cannot compare order of object iterators"); - CHECK_THROWS_WITH(it2_c < it3_c, "cannot compare order of object iterators"); - CHECK_THROWS_WITH(it1_c < it3_c, "cannot compare order of object iterators"); + CHECK_THROWS_AS(it1 < it1, json::invalid_iterator); + CHECK_THROWS_AS(it1 < it2, json::invalid_iterator); + CHECK_THROWS_AS(it2 < it3, json::invalid_iterator); + CHECK_THROWS_AS(it1 < it3, json::invalid_iterator); + CHECK_THROWS_AS(it1_c < it1_c, json::invalid_iterator); + CHECK_THROWS_AS(it1_c < it2_c, json::invalid_iterator); + CHECK_THROWS_AS(it2_c < it3_c, json::invalid_iterator); + CHECK_THROWS_AS(it1_c < it3_c, json::invalid_iterator); + CHECK_THROWS_WITH(it1 < it1, "[except.113] cannot compare order of object iterators"); + CHECK_THROWS_WITH(it1 < it2, "[except.113] cannot compare order of object iterators"); + CHECK_THROWS_WITH(it2 < it3, "[except.113] cannot compare order of object iterators"); + CHECK_THROWS_WITH(it1 < it3, "[except.113] cannot compare order of object iterators"); + CHECK_THROWS_WITH(it1_c < it1_c, "[except.113] cannot compare order of object iterators"); + CHECK_THROWS_WITH(it1_c < it2_c, "[except.113] cannot compare order of object iterators"); + CHECK_THROWS_WITH(it2_c < it3_c, "[except.113] cannot compare order of object iterators"); + CHECK_THROWS_WITH(it1_c < it3_c, "[except.113] cannot compare order of object iterators"); } else { @@ -6597,22 +6768,22 @@ { if (j.type() == json::value_t::object) { - CHECK_THROWS_AS(it1 <= it1, std::domain_error); - CHECK_THROWS_AS(it1 <= it2, std::domain_error); - CHECK_THROWS_AS(it2 <= it3, std::domain_error); - CHECK_THROWS_AS(it1 <= it3, std::domain_error); - CHECK_THROWS_AS(it1_c <= it1_c, std::domain_error); - CHECK_THROWS_AS(it1_c <= it2_c, std::domain_error); - CHECK_THROWS_AS(it2_c <= it3_c, std::domain_error); - CHECK_THROWS_AS(it1_c <= it3_c, std::domain_error); - CHECK_THROWS_WITH(it1 <= it1, "cannot compare order of object iterators"); - CHECK_THROWS_WITH(it1 <= it2, "cannot compare order of object iterators"); - CHECK_THROWS_WITH(it2 <= it3, "cannot compare order of object iterators"); - CHECK_THROWS_WITH(it1 <= it3, "cannot compare order of object iterators"); - CHECK_THROWS_WITH(it1_c <= it1_c, "cannot compare order of object iterators"); - CHECK_THROWS_WITH(it1_c <= it2_c, "cannot compare order of object iterators"); - CHECK_THROWS_WITH(it2_c <= it3_c, "cannot compare order of object iterators"); - CHECK_THROWS_WITH(it1_c <= it3_c, "cannot compare order of object iterators"); + CHECK_THROWS_AS(it1 <= it1, json::invalid_iterator); + CHECK_THROWS_AS(it1 <= it2, json::invalid_iterator); + CHECK_THROWS_AS(it2 <= it3, json::invalid_iterator); + CHECK_THROWS_AS(it1 <= it3, json::invalid_iterator); + CHECK_THROWS_AS(it1_c <= it1_c, json::invalid_iterator); + CHECK_THROWS_AS(it1_c <= it2_c, json::invalid_iterator); + CHECK_THROWS_AS(it2_c <= it3_c, json::invalid_iterator); + CHECK_THROWS_AS(it1_c <= it3_c, json::invalid_iterator); + CHECK_THROWS_WITH(it1 <= it1, "[except.113] cannot compare order of object iterators"); + CHECK_THROWS_WITH(it1 <= it2, "[except.113] cannot compare order of object iterators"); + CHECK_THROWS_WITH(it2 <= it3, "[except.113] cannot compare order of object iterators"); + CHECK_THROWS_WITH(it1 <= it3, "[except.113] cannot compare order of object iterators"); + CHECK_THROWS_WITH(it1_c <= it1_c, "[except.113] cannot compare order of object iterators"); + CHECK_THROWS_WITH(it1_c <= it2_c, "[except.113] cannot compare order of object iterators"); + CHECK_THROWS_WITH(it2_c <= it3_c, "[except.113] cannot compare order of object iterators"); + CHECK_THROWS_WITH(it1_c <= it3_c, "[except.113] cannot compare order of object iterators"); } else { @@ -6632,22 +6803,22 @@ { if (j.type() == json::value_t::object) { - CHECK_THROWS_AS(it1 > it1, std::domain_error); - CHECK_THROWS_AS(it1 > it2, std::domain_error); - CHECK_THROWS_AS(it2 > it3, std::domain_error); - CHECK_THROWS_AS(it1 > it3, std::domain_error); - CHECK_THROWS_AS(it1_c > it1_c, std::domain_error); - CHECK_THROWS_AS(it1_c > it2_c, std::domain_error); - CHECK_THROWS_AS(it2_c > it3_c, std::domain_error); - CHECK_THROWS_AS(it1_c > it3_c, std::domain_error); - CHECK_THROWS_WITH(it1 > it1, "cannot compare order of object iterators"); - CHECK_THROWS_WITH(it1 > it2, "cannot compare order of object iterators"); - CHECK_THROWS_WITH(it2 > it3, "cannot compare order of object iterators"); - CHECK_THROWS_WITH(it1 > it3, "cannot compare order of object iterators"); - CHECK_THROWS_WITH(it1_c > it1_c, "cannot compare order of object iterators"); - CHECK_THROWS_WITH(it1_c > it2_c, "cannot compare order of object iterators"); - CHECK_THROWS_WITH(it2_c > it3_c, "cannot compare order of object iterators"); - CHECK_THROWS_WITH(it1_c > it3_c, "cannot compare order of object iterators"); + CHECK_THROWS_AS(it1 > it1, json::invalid_iterator); + CHECK_THROWS_AS(it1 > it2, json::invalid_iterator); + CHECK_THROWS_AS(it2 > it3, json::invalid_iterator); + CHECK_THROWS_AS(it1 > it3, json::invalid_iterator); + CHECK_THROWS_AS(it1_c > it1_c, json::invalid_iterator); + CHECK_THROWS_AS(it1_c > it2_c, json::invalid_iterator); + CHECK_THROWS_AS(it2_c > it3_c, json::invalid_iterator); + CHECK_THROWS_AS(it1_c > it3_c, json::invalid_iterator); + CHECK_THROWS_WITH(it1 > it1, "[except.113] cannot compare order of object iterators"); + CHECK_THROWS_WITH(it1 > it2, "[except.113] cannot compare order of object iterators"); + CHECK_THROWS_WITH(it2 > it3, "[except.113] cannot compare order of object iterators"); + CHECK_THROWS_WITH(it1 > it3, "[except.113] cannot compare order of object iterators"); + CHECK_THROWS_WITH(it1_c > it1_c, "[except.113] cannot compare order of object iterators"); + CHECK_THROWS_WITH(it1_c > it2_c, "[except.113] cannot compare order of object iterators"); + CHECK_THROWS_WITH(it2_c > it3_c, "[except.113] cannot compare order of object iterators"); + CHECK_THROWS_WITH(it1_c > it3_c, "[except.113] cannot compare order of object iterators"); } else { @@ -6667,22 +6838,22 @@ { if (j.type() == json::value_t::object) { - CHECK_THROWS_AS(it1 >= it1, std::domain_error); - CHECK_THROWS_AS(it1 >= it2, std::domain_error); - CHECK_THROWS_AS(it2 >= it3, std::domain_error); - CHECK_THROWS_AS(it1 >= it3, std::domain_error); - CHECK_THROWS_AS(it1_c >= it1_c, std::domain_error); - CHECK_THROWS_AS(it1_c >= it2_c, std::domain_error); - CHECK_THROWS_AS(it2_c >= it3_c, std::domain_error); - CHECK_THROWS_AS(it1_c >= it3_c, std::domain_error); - CHECK_THROWS_WITH(it1 >= it1, "cannot compare order of object iterators"); - CHECK_THROWS_WITH(it1 >= it2, "cannot compare order of object iterators"); - CHECK_THROWS_WITH(it2 >= it3, "cannot compare order of object iterators"); - CHECK_THROWS_WITH(it1 >= it3, "cannot compare order of object iterators"); - CHECK_THROWS_WITH(it1_c >= it1_c, "cannot compare order of object iterators"); - CHECK_THROWS_WITH(it1_c >= it2_c, "cannot compare order of object iterators"); - CHECK_THROWS_WITH(it2_c >= it3_c, "cannot compare order of object iterators"); - CHECK_THROWS_WITH(it1_c >= it3_c, "cannot compare order of object iterators"); + CHECK_THROWS_AS(it1 >= it1, json::invalid_iterator); + CHECK_THROWS_AS(it1 >= it2, json::invalid_iterator); + CHECK_THROWS_AS(it2 >= it3, json::invalid_iterator); + CHECK_THROWS_AS(it1 >= it3, json::invalid_iterator); + CHECK_THROWS_AS(it1_c >= it1_c, json::invalid_iterator); + CHECK_THROWS_AS(it1_c >= it2_c, json::invalid_iterator); + CHECK_THROWS_AS(it2_c >= it3_c, json::invalid_iterator); + CHECK_THROWS_AS(it1_c >= it3_c, json::invalid_iterator); + CHECK_THROWS_WITH(it1 >= it1, "[except.113] cannot compare order of object iterators"); + CHECK_THROWS_WITH(it1 >= it2, "[except.113] cannot compare order of object iterators"); + CHECK_THROWS_WITH(it2 >= it3, "[except.113] cannot compare order of object iterators"); + CHECK_THROWS_WITH(it1 >= it3, "[except.113] cannot compare order of object iterators"); + CHECK_THROWS_WITH(it1_c >= it1_c, "[except.113] cannot compare order of object iterators"); + CHECK_THROWS_WITH(it1_c >= it2_c, "[except.113] cannot compare order of object iterators"); + CHECK_THROWS_WITH(it2_c >= it3_c, "[except.113] cannot compare order of object iterators"); + CHECK_THROWS_WITH(it1_c >= it3_c, "[except.113] cannot compare order of object iterators"); } else { @@ -6706,15 +6877,19 @@ { if (j != k) { - CHECK_THROWS_AS(j.begin() == k.begin(), std::domain_error); - CHECK_THROWS_AS(j.cbegin() == k.cbegin(), std::domain_error); - CHECK_THROWS_WITH(j.begin() == k.begin(), "cannot compare iterators of different containers"); - CHECK_THROWS_WITH(j.cbegin() == k.cbegin(), "cannot compare iterators of different containers"); + CHECK_THROWS_AS(j.begin() == k.begin(), json::invalid_iterator); + CHECK_THROWS_AS(j.cbegin() == k.cbegin(), json::invalid_iterator); + CHECK_THROWS_WITH(j.begin() == k.begin(), + "[except.112] cannot compare iterators of different containers"); + CHECK_THROWS_WITH(j.cbegin() == k.cbegin(), + "[except.112] cannot compare iterators of different containers"); - CHECK_THROWS_AS(j.begin() < k.begin(), std::domain_error); - CHECK_THROWS_AS(j.cbegin() < k.cbegin(), std::domain_error); - CHECK_THROWS_WITH(j.begin() < k.begin(), "cannot compare iterators of different containers"); - CHECK_THROWS_WITH(j.cbegin() < k.cbegin(), "cannot compare iterators of different containers"); + CHECK_THROWS_AS(j.begin() < k.begin(), json::invalid_iterator); + CHECK_THROWS_AS(j.cbegin() < k.cbegin(), json::invalid_iterator); + CHECK_THROWS_WITH(j.begin() < k.begin(), + "[except.112] cannot compare iterators of different containers"); + CHECK_THROWS_WITH(j.cbegin() < k.cbegin(), + "[except.112] cannot compare iterators of different containers"); } } } @@ -6733,53 +6908,53 @@ { { auto it = j_object.begin(); - CHECK_THROWS_AS(it += 1, std::domain_error); - CHECK_THROWS_WITH(it += 1, "cannot use offsets with object iterators"); + CHECK_THROWS_AS(it += 1, json::invalid_iterator); + CHECK_THROWS_WITH(it += 1, "[except.109] cannot use offsets with object iterators"); } { auto it = j_object.cbegin(); - CHECK_THROWS_AS(it += 1, std::domain_error); - CHECK_THROWS_WITH(it += 1, "cannot use offsets with object iterators"); + CHECK_THROWS_AS(it += 1, json::invalid_iterator); + CHECK_THROWS_WITH(it += 1, "[except.109] cannot use offsets with object iterators"); } { auto it = j_object.begin(); - CHECK_THROWS_AS(it + 1, std::domain_error); - CHECK_THROWS_WITH(it + 1, "cannot use offsets with object iterators"); + CHECK_THROWS_AS(it + 1, json::invalid_iterator); + CHECK_THROWS_WITH(it + 1, "[except.109] cannot use offsets with object iterators"); } { auto it = j_object.cbegin(); - CHECK_THROWS_AS(it + 1, std::domain_error); - CHECK_THROWS_WITH(it + 1, "cannot use offsets with object iterators"); + CHECK_THROWS_AS(it + 1, json::invalid_iterator); + CHECK_THROWS_WITH(it + 1, "[except.109] cannot use offsets with object iterators"); } { auto it = j_object.begin(); - CHECK_THROWS_AS(it -= 1, std::domain_error); - CHECK_THROWS_WITH(it -= 1, "cannot use offsets with object iterators"); + CHECK_THROWS_AS(it -= 1, json::invalid_iterator); + CHECK_THROWS_WITH(it -= 1, "[except.109] cannot use offsets with object iterators"); } { auto it = j_object.cbegin(); - CHECK_THROWS_AS(it -= 1, std::domain_error); - CHECK_THROWS_WITH(it -= 1, "cannot use offsets with object iterators"); + CHECK_THROWS_AS(it -= 1, json::invalid_iterator); + CHECK_THROWS_WITH(it -= 1, "[except.109] cannot use offsets with object iterators"); } { auto it = j_object.begin(); - CHECK_THROWS_AS(it - 1, std::domain_error); - CHECK_THROWS_WITH(it - 1, "cannot use offsets with object iterators"); + CHECK_THROWS_AS(it - 1, json::invalid_iterator); + CHECK_THROWS_WITH(it - 1, "[except.109] cannot use offsets with object iterators"); } { auto it = j_object.cbegin(); - CHECK_THROWS_AS(it - 1, std::domain_error); - CHECK_THROWS_WITH(it - 1, "cannot use offsets with object iterators"); + CHECK_THROWS_AS(it - 1, json::invalid_iterator); + CHECK_THROWS_WITH(it - 1, "[except.109] cannot use offsets with object iterators"); } { auto it = j_object.begin(); - CHECK_THROWS_AS(it - it, std::domain_error); - CHECK_THROWS_WITH(it - it, "cannot use offsets with object iterators"); + CHECK_THROWS_AS(it - it, json::invalid_iterator); + CHECK_THROWS_WITH(it - it, "[except.109] cannot use offsets with object iterators"); } { auto it = j_object.cbegin(); - CHECK_THROWS_AS(it - it, std::domain_error); - CHECK_THROWS_WITH(it - it, "cannot use offsets with object iterators"); + CHECK_THROWS_AS(it - it, json::invalid_iterator); + CHECK_THROWS_WITH(it - it, "[except.109] cannot use offsets with object iterators"); } } @@ -6862,17 +7037,17 @@ { { auto it = j_object.begin(); - CHECK_THROWS_AS(it[0], std::domain_error); - CHECK_THROWS_AS(it[1], std::domain_error); - CHECK_THROWS_WITH(it[0], "cannot use operator[] for object iterators"); - CHECK_THROWS_WITH(it[1], "cannot use operator[] for object iterators"); + CHECK_THROWS_AS(it[0], json::invalid_iterator); + CHECK_THROWS_AS(it[1], json::invalid_iterator); + CHECK_THROWS_WITH(it[0], "[except.108] cannot use operator[] for object iterators"); + CHECK_THROWS_WITH(it[1], "[except.108] cannot use operator[] for object iterators"); } { auto it = j_object.cbegin(); - CHECK_THROWS_AS(it[0], std::domain_error); - CHECK_THROWS_AS(it[1], std::domain_error); - CHECK_THROWS_WITH(it[0], "cannot use operator[] for object iterators"); - CHECK_THROWS_WITH(it[1], "cannot use operator[] for object iterators"); + CHECK_THROWS_AS(it[0], json::invalid_iterator); + CHECK_THROWS_AS(it[1], json::invalid_iterator); + CHECK_THROWS_WITH(it[0], "[except.108] cannot use operator[] for object iterators"); + CHECK_THROWS_WITH(it[1], "[except.108] cannot use operator[] for object iterators"); } } @@ -6902,17 +7077,17 @@ { { auto it = j_null.begin(); - CHECK_THROWS_AS(it[0], std::out_of_range); - CHECK_THROWS_AS(it[1], std::out_of_range); - CHECK_THROWS_WITH(it[0], "cannot get value"); - CHECK_THROWS_WITH(it[1], "cannot get value"); + CHECK_THROWS_AS(it[0], json::invalid_iterator); + CHECK_THROWS_AS(it[1], json::invalid_iterator); + CHECK_THROWS_WITH(it[0], "[except.114] cannot get value"); + CHECK_THROWS_WITH(it[1], "[except.114] cannot get value"); } { auto it = j_null.cbegin(); - CHECK_THROWS_AS(it[0], std::out_of_range); - CHECK_THROWS_AS(it[1], std::out_of_range); - CHECK_THROWS_WITH(it[0], "cannot get value"); - CHECK_THROWS_WITH(it[1], "cannot get value"); + CHECK_THROWS_AS(it[0], json::invalid_iterator); + CHECK_THROWS_AS(it[1], json::invalid_iterator); + CHECK_THROWS_WITH(it[0], "[except.114] cannot get value"); + CHECK_THROWS_WITH(it[1], "[except.114] cannot get value"); } } @@ -6921,14 +7096,14 @@ { auto it = j_value.begin(); CHECK(it[0] == json(42)); - CHECK_THROWS_AS(it[1], std::out_of_range); - CHECK_THROWS_WITH(it[1], "cannot get value"); + CHECK_THROWS_AS(it[1], json::invalid_iterator); + CHECK_THROWS_WITH(it[1], "[except.114] cannot get value"); } { auto it = j_value.cbegin(); CHECK(it[0] == json(42)); - CHECK_THROWS_AS(it[1], std::out_of_range); - CHECK_THROWS_WITH(it[1], "cannot get value"); + CHECK_THROWS_AS(it[1], json::invalid_iterator); + CHECK_THROWS_WITH(it[1], "[except.114] cannot get value"); } } } @@ -6982,22 +7157,22 @@ { if (j.type() == json::value_t::object) { - CHECK_THROWS_AS(it1 < it1, std::domain_error); - CHECK_THROWS_AS(it1 < it2, std::domain_error); - CHECK_THROWS_AS(it2 < it3, std::domain_error); - CHECK_THROWS_AS(it1 < it3, std::domain_error); - CHECK_THROWS_AS(it1_c < it1_c, std::domain_error); - CHECK_THROWS_AS(it1_c < it2_c, std::domain_error); - CHECK_THROWS_AS(it2_c < it3_c, std::domain_error); - CHECK_THROWS_AS(it1_c < it3_c, std::domain_error); - CHECK_THROWS_WITH(it1 < it1, "cannot compare order of object iterators"); - CHECK_THROWS_WITH(it1 < it2, "cannot compare order of object iterators"); - CHECK_THROWS_WITH(it2 < it3, "cannot compare order of object iterators"); - CHECK_THROWS_WITH(it1 < it3, "cannot compare order of object iterators"); - CHECK_THROWS_WITH(it1_c < it1_c, "cannot compare order of object iterators"); - CHECK_THROWS_WITH(it1_c < it2_c, "cannot compare order of object iterators"); - CHECK_THROWS_WITH(it2_c < it3_c, "cannot compare order of object iterators"); - CHECK_THROWS_WITH(it1_c < it3_c, "cannot compare order of object iterators"); + CHECK_THROWS_AS(it1 < it1, json::invalid_iterator); + CHECK_THROWS_AS(it1 < it2, json::invalid_iterator); + CHECK_THROWS_AS(it2 < it3, json::invalid_iterator); + CHECK_THROWS_AS(it1 < it3, json::invalid_iterator); + CHECK_THROWS_AS(it1_c < it1_c, json::invalid_iterator); + CHECK_THROWS_AS(it1_c < it2_c, json::invalid_iterator); + CHECK_THROWS_AS(it2_c < it3_c, json::invalid_iterator); + CHECK_THROWS_AS(it1_c < it3_c, json::invalid_iterator); + CHECK_THROWS_WITH(it1 < it1, "[except.113] cannot compare order of object iterators"); + CHECK_THROWS_WITH(it1 < it2, "[except.113] cannot compare order of object iterators"); + CHECK_THROWS_WITH(it2 < it3, "[except.113] cannot compare order of object iterators"); + CHECK_THROWS_WITH(it1 < it3, "[except.113] cannot compare order of object iterators"); + CHECK_THROWS_WITH(it1_c < it1_c, "[except.113] cannot compare order of object iterators"); + CHECK_THROWS_WITH(it1_c < it2_c, "[except.113] cannot compare order of object iterators"); + CHECK_THROWS_WITH(it2_c < it3_c, "[except.113] cannot compare order of object iterators"); + CHECK_THROWS_WITH(it1_c < it3_c, "[except.113] cannot compare order of object iterators"); } else { @@ -7016,22 +7191,22 @@ { if (j.type() == json::value_t::object) { - CHECK_THROWS_AS(it1 <= it1, std::domain_error); - CHECK_THROWS_AS(it1 <= it2, std::domain_error); - CHECK_THROWS_AS(it2 <= it3, std::domain_error); - CHECK_THROWS_AS(it1 <= it3, std::domain_error); - CHECK_THROWS_AS(it1_c <= it1_c, std::domain_error); - CHECK_THROWS_AS(it1_c <= it2_c, std::domain_error); - CHECK_THROWS_AS(it2_c <= it3_c, std::domain_error); - CHECK_THROWS_AS(it1_c <= it3_c, std::domain_error); - CHECK_THROWS_WITH(it1 <= it1, "cannot compare order of object iterators"); - CHECK_THROWS_WITH(it1 <= it2, "cannot compare order of object iterators"); - CHECK_THROWS_WITH(it2 <= it3, "cannot compare order of object iterators"); - CHECK_THROWS_WITH(it1 <= it3, "cannot compare order of object iterators"); - CHECK_THROWS_WITH(it1_c <= it1_c, "cannot compare order of object iterators"); - CHECK_THROWS_WITH(it1_c <= it2_c, "cannot compare order of object iterators"); - CHECK_THROWS_WITH(it2_c <= it3_c, "cannot compare order of object iterators"); - CHECK_THROWS_WITH(it1_c <= it3_c, "cannot compare order of object iterators"); + CHECK_THROWS_AS(it1 <= it1, json::invalid_iterator); + CHECK_THROWS_AS(it1 <= it2, json::invalid_iterator); + CHECK_THROWS_AS(it2 <= it3, json::invalid_iterator); + CHECK_THROWS_AS(it1 <= it3, json::invalid_iterator); + CHECK_THROWS_AS(it1_c <= it1_c, json::invalid_iterator); + CHECK_THROWS_AS(it1_c <= it2_c, json::invalid_iterator); + CHECK_THROWS_AS(it2_c <= it3_c, json::invalid_iterator); + CHECK_THROWS_AS(it1_c <= it3_c, json::invalid_iterator); + CHECK_THROWS_WITH(it1 <= it1, "[except.113] cannot compare order of object iterators"); + CHECK_THROWS_WITH(it1 <= it2, "[except.113] cannot compare order of object iterators"); + CHECK_THROWS_WITH(it2 <= it3, "[except.113] cannot compare order of object iterators"); + CHECK_THROWS_WITH(it1 <= it3, "[except.113] cannot compare order of object iterators"); + CHECK_THROWS_WITH(it1_c <= it1_c, "[except.113] cannot compare order of object iterators"); + CHECK_THROWS_WITH(it1_c <= it2_c, "[except.113] cannot compare order of object iterators"); + CHECK_THROWS_WITH(it2_c <= it3_c, "[except.113] cannot compare order of object iterators"); + CHECK_THROWS_WITH(it1_c <= it3_c, "[except.113] cannot compare order of object iterators"); } else { @@ -7051,22 +7226,22 @@ { if (j.type() == json::value_t::object) { - CHECK_THROWS_AS(it1 > it1, std::domain_error); - CHECK_THROWS_AS(it1 > it2, std::domain_error); - CHECK_THROWS_AS(it2 > it3, std::domain_error); - CHECK_THROWS_AS(it1 > it3, std::domain_error); - CHECK_THROWS_AS(it1_c > it1_c, std::domain_error); - CHECK_THROWS_AS(it1_c > it2_c, std::domain_error); - CHECK_THROWS_AS(it2_c > it3_c, std::domain_error); - CHECK_THROWS_AS(it1_c > it3_c, std::domain_error); - CHECK_THROWS_WITH(it1 > it1, "cannot compare order of object iterators"); - CHECK_THROWS_WITH(it1 > it2, "cannot compare order of object iterators"); - CHECK_THROWS_WITH(it2 > it3, "cannot compare order of object iterators"); - CHECK_THROWS_WITH(it1 > it3, "cannot compare order of object iterators"); - CHECK_THROWS_WITH(it1_c > it1_c, "cannot compare order of object iterators"); - CHECK_THROWS_WITH(it1_c > it2_c, "cannot compare order of object iterators"); - CHECK_THROWS_WITH(it2_c > it3_c, "cannot compare order of object iterators"); - CHECK_THROWS_WITH(it1_c > it3_c, "cannot compare order of object iterators"); + CHECK_THROWS_AS(it1 > it1, json::invalid_iterator); + CHECK_THROWS_AS(it1 > it2, json::invalid_iterator); + CHECK_THROWS_AS(it2 > it3, json::invalid_iterator); + CHECK_THROWS_AS(it1 > it3, json::invalid_iterator); + CHECK_THROWS_AS(it1_c > it1_c, json::invalid_iterator); + CHECK_THROWS_AS(it1_c > it2_c, json::invalid_iterator); + CHECK_THROWS_AS(it2_c > it3_c, json::invalid_iterator); + CHECK_THROWS_AS(it1_c > it3_c, json::invalid_iterator); + CHECK_THROWS_WITH(it1 > it1, "[except.113] cannot compare order of object iterators"); + CHECK_THROWS_WITH(it1 > it2, "[except.113] cannot compare order of object iterators"); + CHECK_THROWS_WITH(it2 > it3, "[except.113] cannot compare order of object iterators"); + CHECK_THROWS_WITH(it1 > it3, "[except.113] cannot compare order of object iterators"); + CHECK_THROWS_WITH(it1_c > it1_c, "[except.113] cannot compare order of object iterators"); + CHECK_THROWS_WITH(it1_c > it2_c, "[except.113] cannot compare order of object iterators"); + CHECK_THROWS_WITH(it2_c > it3_c, "[except.113] cannot compare order of object iterators"); + CHECK_THROWS_WITH(it1_c > it3_c, "[except.113] cannot compare order of object iterators"); } else { @@ -7086,22 +7261,22 @@ { if (j.type() == json::value_t::object) { - CHECK_THROWS_AS(it1 >= it1, std::domain_error); - CHECK_THROWS_AS(it1 >= it2, std::domain_error); - CHECK_THROWS_AS(it2 >= it3, std::domain_error); - CHECK_THROWS_AS(it1 >= it3, std::domain_error); - CHECK_THROWS_AS(it1_c >= it1_c, std::domain_error); - CHECK_THROWS_AS(it1_c >= it2_c, std::domain_error); - CHECK_THROWS_AS(it2_c >= it3_c, std::domain_error); - CHECK_THROWS_AS(it1_c >= it3_c, std::domain_error); - CHECK_THROWS_WITH(it1 >= it1, "cannot compare order of object iterators"); - CHECK_THROWS_WITH(it1 >= it2, "cannot compare order of object iterators"); - CHECK_THROWS_WITH(it2 >= it3, "cannot compare order of object iterators"); - CHECK_THROWS_WITH(it1 >= it3, "cannot compare order of object iterators"); - CHECK_THROWS_WITH(it1_c >= it1_c, "cannot compare order of object iterators"); - CHECK_THROWS_WITH(it1_c >= it2_c, "cannot compare order of object iterators"); - CHECK_THROWS_WITH(it2_c >= it3_c, "cannot compare order of object iterators"); - CHECK_THROWS_WITH(it1_c >= it3_c, "cannot compare order of object iterators"); + CHECK_THROWS_AS(it1 >= it1, json::invalid_iterator); + CHECK_THROWS_AS(it1 >= it2, json::invalid_iterator); + CHECK_THROWS_AS(it2 >= it3, json::invalid_iterator); + CHECK_THROWS_AS(it1 >= it3, json::invalid_iterator); + CHECK_THROWS_AS(it1_c >= it1_c, json::invalid_iterator); + CHECK_THROWS_AS(it1_c >= it2_c, json::invalid_iterator); + CHECK_THROWS_AS(it2_c >= it3_c, json::invalid_iterator); + CHECK_THROWS_AS(it1_c >= it3_c, json::invalid_iterator); + CHECK_THROWS_WITH(it1 >= it1, "[except.113] cannot compare order of object iterators"); + CHECK_THROWS_WITH(it1 >= it2, "[except.113] cannot compare order of object iterators"); + CHECK_THROWS_WITH(it2 >= it3, "[except.113] cannot compare order of object iterators"); + CHECK_THROWS_WITH(it1 >= it3, "[except.113] cannot compare order of object iterators"); + CHECK_THROWS_WITH(it1_c >= it1_c, "[except.113] cannot compare order of object iterators"); + CHECK_THROWS_WITH(it1_c >= it2_c, "[except.113] cannot compare order of object iterators"); + CHECK_THROWS_WITH(it2_c >= it3_c, "[except.113] cannot compare order of object iterators"); + CHECK_THROWS_WITH(it1_c >= it3_c, "[except.113] cannot compare order of object iterators"); } else { @@ -7125,15 +7300,19 @@ { if (j != k) { - CHECK_THROWS_AS(j.rbegin() == k.rbegin(), std::domain_error); - CHECK_THROWS_AS(j.crbegin() == k.crbegin(), std::domain_error); - CHECK_THROWS_WITH(j.rbegin() == k.rbegin(), "cannot compare iterators of different containers"); - CHECK_THROWS_WITH(j.crbegin() == k.crbegin(), "cannot compare iterators of different containers"); + CHECK_THROWS_AS(j.rbegin() == k.rbegin(), json::invalid_iterator); + CHECK_THROWS_AS(j.crbegin() == k.crbegin(), json::invalid_iterator); + CHECK_THROWS_WITH(j.rbegin() == k.rbegin(), + "[except.112] cannot compare iterators of different containers"); + CHECK_THROWS_WITH(j.crbegin() == k.crbegin(), + "[except.112] cannot compare iterators of different containers"); - CHECK_THROWS_AS(j.rbegin() < k.rbegin(), std::domain_error); - CHECK_THROWS_AS(j.crbegin() < k.crbegin(), std::domain_error); - CHECK_THROWS_WITH(j.rbegin() < k.rbegin(), "cannot compare iterators of different containers"); - CHECK_THROWS_WITH(j.crbegin() < k.crbegin(), "cannot compare iterators of different containers"); + CHECK_THROWS_AS(j.rbegin() < k.rbegin(), json::invalid_iterator); + CHECK_THROWS_AS(j.crbegin() < k.crbegin(), json::invalid_iterator); + CHECK_THROWS_WITH(j.rbegin() < k.rbegin(), + "[except.112] cannot compare iterators of different containers"); + CHECK_THROWS_WITH(j.crbegin() < k.crbegin(), + "[except.112] cannot compare iterators of different containers"); } } } @@ -7152,53 +7331,53 @@ { { auto it = j_object.rbegin(); - CHECK_THROWS_AS(it += 1, std::domain_error); - CHECK_THROWS_WITH(it += 1, "cannot use offsets with object iterators"); + CHECK_THROWS_AS(it += 1, json::invalid_iterator); + CHECK_THROWS_WITH(it += 1, "[except.109] cannot use offsets with object iterators"); } { auto it = j_object.crbegin(); - CHECK_THROWS_AS(it += 1, std::domain_error); - CHECK_THROWS_WITH(it += 1, "cannot use offsets with object iterators"); + CHECK_THROWS_AS(it += 1, json::invalid_iterator); + CHECK_THROWS_WITH(it += 1, "[except.109] cannot use offsets with object iterators"); } { auto it = j_object.rbegin(); - CHECK_THROWS_AS(it + 1, std::domain_error); - CHECK_THROWS_WITH(it + 1, "cannot use offsets with object iterators"); + CHECK_THROWS_AS(it + 1, json::invalid_iterator); + CHECK_THROWS_WITH(it + 1, "[except.109] cannot use offsets with object iterators"); } { auto it = j_object.crbegin(); - CHECK_THROWS_AS(it + 1, std::domain_error); - CHECK_THROWS_WITH(it + 1, "cannot use offsets with object iterators"); + CHECK_THROWS_AS(it + 1, json::invalid_iterator); + CHECK_THROWS_WITH(it + 1, "[except.109] cannot use offsets with object iterators"); } { auto it = j_object.rbegin(); - CHECK_THROWS_AS(it -= 1, std::domain_error); - CHECK_THROWS_WITH(it -= 1, "cannot use offsets with object iterators"); + CHECK_THROWS_AS(it -= 1, json::invalid_iterator); + CHECK_THROWS_WITH(it -= 1, "[except.109] cannot use offsets with object iterators"); } { auto it = j_object.crbegin(); - CHECK_THROWS_AS(it -= 1, std::domain_error); - CHECK_THROWS_WITH(it -= 1, "cannot use offsets with object iterators"); + CHECK_THROWS_AS(it -= 1, json::invalid_iterator); + CHECK_THROWS_WITH(it -= 1, "[except.109] cannot use offsets with object iterators"); } { auto it = j_object.rbegin(); - CHECK_THROWS_AS(it - 1, std::domain_error); - CHECK_THROWS_WITH(it - 1, "cannot use offsets with object iterators"); + CHECK_THROWS_AS(it - 1, json::invalid_iterator); + CHECK_THROWS_WITH(it - 1, "[except.109] cannot use offsets with object iterators"); } { auto it = j_object.crbegin(); - CHECK_THROWS_AS(it - 1, std::domain_error); - CHECK_THROWS_WITH(it - 1, "cannot use offsets with object iterators"); + CHECK_THROWS_AS(it - 1, json::invalid_iterator); + CHECK_THROWS_WITH(it - 1, "[except.109] cannot use offsets with object iterators"); } { auto it = j_object.rbegin(); - CHECK_THROWS_AS(it - it, std::domain_error); - CHECK_THROWS_WITH(it - it, "cannot use offsets with object iterators"); + CHECK_THROWS_AS(it - it, json::invalid_iterator); + CHECK_THROWS_WITH(it - it, "[except.109] cannot use offsets with object iterators"); } { auto it = j_object.crbegin(); - CHECK_THROWS_AS(it - it, std::domain_error); - CHECK_THROWS_WITH(it - it, "cannot use offsets with object iterators"); + CHECK_THROWS_AS(it - it, json::invalid_iterator); + CHECK_THROWS_WITH(it - it, "[except.109] cannot use offsets with object iterators"); } } @@ -7281,17 +7460,17 @@ { { auto it = j_object.rbegin(); - CHECK_THROWS_AS(it[0], std::domain_error); - CHECK_THROWS_AS(it[1], std::domain_error); - CHECK_THROWS_WITH(it[0], "cannot use offsets with object iterators"); - CHECK_THROWS_WITH(it[1], "cannot use offsets with object iterators"); + CHECK_THROWS_AS(it[0], json::invalid_iterator); + CHECK_THROWS_AS(it[1], json::invalid_iterator); + CHECK_THROWS_WITH(it[0], "[except.109] cannot use offsets with object iterators"); + CHECK_THROWS_WITH(it[1], "[except.109] cannot use offsets with object iterators"); } { auto it = j_object.crbegin(); - CHECK_THROWS_AS(it[0], std::domain_error); - CHECK_THROWS_AS(it[1], std::domain_error); - CHECK_THROWS_WITH(it[0], "cannot use offsets with object iterators"); - CHECK_THROWS_WITH(it[1], "cannot use offsets with object iterators"); + CHECK_THROWS_AS(it[0], json::invalid_iterator); + CHECK_THROWS_AS(it[1], json::invalid_iterator); + CHECK_THROWS_WITH(it[0], "[except.109] cannot use offsets with object iterators"); + CHECK_THROWS_WITH(it[1], "[except.109] cannot use offsets with object iterators"); } } @@ -7321,17 +7500,17 @@ { { auto it = j_null.rbegin(); - CHECK_THROWS_AS(it[0], std::out_of_range); - CHECK_THROWS_AS(it[1], std::out_of_range); - CHECK_THROWS_WITH(it[0], "cannot get value"); - CHECK_THROWS_WITH(it[1], "cannot get value"); + CHECK_THROWS_AS(it[0], json::invalid_iterator); + CHECK_THROWS_AS(it[1], json::invalid_iterator); + CHECK_THROWS_WITH(it[0], "[except.114] cannot get value"); + CHECK_THROWS_WITH(it[1], "[except.114] cannot get value"); } { auto it = j_null.crbegin(); - CHECK_THROWS_AS(it[0], std::out_of_range); - CHECK_THROWS_AS(it[1], std::out_of_range); - CHECK_THROWS_WITH(it[0], "cannot get value"); - CHECK_THROWS_WITH(it[1], "cannot get value"); + CHECK_THROWS_AS(it[0], json::invalid_iterator); + CHECK_THROWS_AS(it[1], json::invalid_iterator); + CHECK_THROWS_WITH(it[0], "[except.114] cannot get value"); + CHECK_THROWS_WITH(it[1], "[except.114] cannot get value"); } } @@ -7340,14 +7519,14 @@ { auto it = j_value.rbegin(); CHECK(it[0] == json(42)); - CHECK_THROWS_AS(it[1], std::out_of_range); - CHECK_THROWS_WITH(it[1], "cannot get value"); + CHECK_THROWS_AS(it[1], json::invalid_iterator); + CHECK_THROWS_WITH(it[1], "[except.114] cannot get value"); } { auto it = j_value.crbegin(); CHECK(it[0] == json(42)); - CHECK_THROWS_AS(it[1], std::out_of_range); - CHECK_THROWS_WITH(it[1], "cannot get value"); + CHECK_THROWS_AS(it[1], json::invalid_iterator); + CHECK_THROWS_WITH(it[1], "[except.114] cannot get value"); } } } @@ -8005,8 +8184,8 @@ SECTION("other type") { json j = 1; - CHECK_THROWS_AS(j.push_back("Hello"), std::domain_error); - CHECK_THROWS_WITH(j.push_back("Hello"), "cannot use push_back() with number"); + CHECK_THROWS_AS(j.push_back("Hello"), json::type_error); + CHECK_THROWS_WITH(j.push_back("Hello"), "[except.307] cannot use push_back() with number"); } } @@ -8035,8 +8214,8 @@ { json j = 1; json k("Hello"); - CHECK_THROWS_AS(j.push_back(k), std::domain_error); - CHECK_THROWS_WITH(j.push_back(k), "cannot use push_back() with number"); + CHECK_THROWS_AS(j.push_back(k), json::type_error); + CHECK_THROWS_WITH(j.push_back(k), "[except.307] cannot use push_back() with number"); } } } @@ -8068,9 +8247,9 @@ { json j = 1; json k("Hello"); - CHECK_THROWS_AS(j.push_back(json::object_t::value_type({"one", 1})), std::domain_error); + CHECK_THROWS_AS(j.push_back(json::object_t::value_type({"one", 1})), json::type_error); CHECK_THROWS_WITH(j.push_back(json::object_t::value_type({"one", 1})), - "cannot use push_back() with number"); + "[except.307] cannot use push_back() with number"); } } @@ -8105,8 +8284,8 @@ CHECK(j == json({{"key1", 1}, {"key2", "bar"}})); json k = {{"key1", 1}}; - CHECK_THROWS_AS(k.push_back({1, 2, 3, 4}), std::domain_error); - CHECK_THROWS_WITH(k.push_back({1, 2, 3, 4}), "cannot use push_back() with object"); + CHECK_THROWS_AS(k.push_back({1, 2, 3, 4}), json::type_error); + CHECK_THROWS_WITH(k.push_back({1, 2, 3, 4}), "[except.307] cannot use push_back() with object"); } } } @@ -8137,8 +8316,8 @@ SECTION("other type") { json j = 1; - CHECK_THROWS_AS(j += "Hello", std::domain_error); - CHECK_THROWS_WITH(j += "Hello", "cannot use push_back() with number"); + CHECK_THROWS_AS(j += "Hello", json::type_error); + CHECK_THROWS_WITH(j += "Hello", "[except.307] cannot use push_back() with number"); } } @@ -8167,8 +8346,8 @@ { json j = 1; json k("Hello"); - CHECK_THROWS_AS(j += k, std::domain_error); - CHECK_THROWS_WITH(j += k, "cannot use push_back() with number"); + CHECK_THROWS_AS(j += k, json::type_error); + CHECK_THROWS_WITH(j += k, "[except.307] cannot use push_back() with number"); } } } @@ -8200,9 +8379,9 @@ { json j = 1; json k("Hello"); - CHECK_THROWS_AS(j += json::object_t::value_type({"one", 1}), std::domain_error); + CHECK_THROWS_AS(j += json::object_t::value_type({"one", 1}), json::type_error); CHECK_THROWS_WITH(j += json::object_t::value_type({"one", 1}), - "cannot use push_back() with number"); + "[except.307] cannot use push_back() with number"); } } @@ -8237,8 +8416,8 @@ CHECK(j == json({{"key1", 1}, {"key2", "bar"}})); json k = {{"key1", 1}}; - CHECK_THROWS_AS((k += {1, 2, 3, 4}), std::domain_error); - CHECK_THROWS_WITH((k += {1, 2, 3, 4}), "cannot use push_back() with object"); + CHECK_THROWS_AS((k += {1, 2, 3, 4}), json::type_error); + CHECK_THROWS_WITH((k += {1, 2, 3, 4}), "[except.307] cannot use push_back() with object"); } } } @@ -8372,14 +8551,15 @@ { json j_other_array2 = {"first", "second"}; - CHECK_THROWS_AS(j_array.insert(j_array.end(), j_array.begin(), j_array.end()), std::domain_error); + CHECK_THROWS_AS(j_array.insert(j_array.end(), j_array.begin(), j_array.end()), + json::invalid_iterator); CHECK_THROWS_AS(j_array.insert(j_array.end(), j_other_array.begin(), j_other_array2.end()), - std::domain_error); + json::invalid_iterator); CHECK_THROWS_WITH(j_array.insert(j_array.end(), j_array.begin(), j_array.end()), - "passed iterators may not belong to container"); + "[except.111] passed iterators may not belong to container"); CHECK_THROWS_WITH(j_array.insert(j_array.end(), j_other_array.begin(), j_other_array2.end()), - "iterators do not fit"); + "[except.110] iterators do not fit"); } } @@ -8418,22 +8598,24 @@ // pass iterator to a different array json j_another_array = {1, 2}; json j_yet_another_array = {"first", "second"}; - CHECK_THROWS_AS(j_array.insert(j_another_array.end(), 10), std::domain_error); - CHECK_THROWS_AS(j_array.insert(j_another_array.end(), j_value), std::domain_error); - CHECK_THROWS_AS(j_array.insert(j_another_array.end(), 10, 11), std::domain_error); + CHECK_THROWS_AS(j_array.insert(j_another_array.end(), 10), json::invalid_iterator); + CHECK_THROWS_AS(j_array.insert(j_another_array.end(), j_value), json::invalid_iterator); + CHECK_THROWS_AS(j_array.insert(j_another_array.end(), 10, 11), json::invalid_iterator); CHECK_THROWS_AS(j_array.insert(j_another_array.end(), j_yet_another_array.begin(), - j_yet_another_array.end()), std::domain_error); - CHECK_THROWS_AS(j_array.insert(j_another_array.end(), {1, 2, 3, 4}), std::domain_error); + j_yet_another_array.end()), json::invalid_iterator); + CHECK_THROWS_AS(j_array.insert(j_another_array.end(), {1, 2, 3, 4}), json::invalid_iterator); - CHECK_THROWS_WITH(j_array.insert(j_another_array.end(), 10), "iterator does not fit current value"); + CHECK_THROWS_WITH(j_array.insert(j_another_array.end(), 10), + "[except.103] iterator does not fit current value"); CHECK_THROWS_WITH(j_array.insert(j_another_array.end(), j_value), - "iterator does not fit current value"); + "[except.103] iterator does not fit current value"); CHECK_THROWS_WITH(j_array.insert(j_another_array.end(), 10, 11), - "iterator does not fit current value"); + "[except.103] iterator does not fit current value"); CHECK_THROWS_WITH(j_array.insert(j_another_array.end(), j_yet_another_array.begin(), - j_yet_another_array.end()), "iterator does not fit current value"); + j_yet_another_array.end()), + "[except.103] iterator does not fit current value"); CHECK_THROWS_WITH(j_array.insert(j_another_array.end(), {1, 2, 3, 4}), - "iterator does not fit current value"); + "[except.103] iterator does not fit current value"); } SECTION("non-array type") @@ -8441,20 +8623,24 @@ // call insert on a non-array type json j_nonarray = 3; json j_yet_another_array = {"first", "second"}; - CHECK_THROWS_AS(j_nonarray.insert(j_nonarray.end(), 10), std::domain_error); - CHECK_THROWS_AS(j_nonarray.insert(j_nonarray.end(), j_value), std::domain_error); - CHECK_THROWS_AS(j_nonarray.insert(j_nonarray.end(), 10, 11), std::domain_error); + CHECK_THROWS_AS(j_nonarray.insert(j_nonarray.end(), 10), json::type_error); + CHECK_THROWS_AS(j_nonarray.insert(j_nonarray.end(), j_value), json::type_error); + CHECK_THROWS_AS(j_nonarray.insert(j_nonarray.end(), 10, 11), json::type_error); CHECK_THROWS_AS(j_nonarray.insert(j_nonarray.end(), j_yet_another_array.begin(), - j_yet_another_array.end()), std::domain_error); - CHECK_THROWS_AS(j_nonarray.insert(j_nonarray.end(), {1, 2, 3, 4}), std::domain_error); + j_yet_another_array.end()), json::type_error); + CHECK_THROWS_AS(j_nonarray.insert(j_nonarray.end(), {1, 2, 3, 4}), json::type_error); - CHECK_THROWS_WITH(j_nonarray.insert(j_nonarray.end(), 10), "cannot use insert() with number"); - CHECK_THROWS_WITH(j_nonarray.insert(j_nonarray.end(), j_value), "cannot use insert() with number"); - CHECK_THROWS_WITH(j_nonarray.insert(j_nonarray.end(), 10, 11), "cannot use insert() with number"); + CHECK_THROWS_WITH(j_nonarray.insert(j_nonarray.end(), 10), + "[except.309] cannot use insert() with number"); + CHECK_THROWS_WITH(j_nonarray.insert(j_nonarray.end(), j_value), + "[except.309] cannot use insert() with number"); + CHECK_THROWS_WITH(j_nonarray.insert(j_nonarray.end(), 10, 11), + "[except.309] cannot use insert() with number"); CHECK_THROWS_WITH(j_nonarray.insert(j_nonarray.end(), j_yet_another_array.begin(), - j_yet_another_array.end()), "cannot use insert() with number"); + j_yet_another_array.end()), + "[except.309] cannot use insert() with number"); CHECK_THROWS_WITH(j_nonarray.insert(j_nonarray.end(), {1, 2, 3, 4}), - "cannot use insert() with number"); + "[except.309] cannot use insert() with number"); } } @@ -8506,8 +8692,8 @@ json j = 17; json::array_t a = {"foo", "bar", "baz"}; - CHECK_THROWS_AS(j.swap(a), std::domain_error); - CHECK_THROWS_WITH(j.swap(a), "cannot use swap() with number"); + CHECK_THROWS_AS(j.swap(a), json::type_error); + CHECK_THROWS_WITH(j.swap(a), "[except.308] cannot use swap() with number"); } } @@ -8532,8 +8718,8 @@ json j = 17; json::object_t o = {{"cow", "Kuh"}, {"chicken", "Huhn"}}; - CHECK_THROWS_AS(j.swap(o), std::domain_error); - CHECK_THROWS_WITH(j.swap(o), "cannot use swap() with number"); + CHECK_THROWS_AS(j.swap(o), json::type_error); + CHECK_THROWS_WITH(j.swap(o), "[except.308] cannot use swap() with number"); } } @@ -8558,8 +8744,8 @@ json j = 17; json::string_t s = "Hallo Welt"; - CHECK_THROWS_AS(j.swap(s), std::domain_error); - CHECK_THROWS_WITH(j.swap(s), "cannot use swap() with number"); + CHECK_THROWS_AS(j.swap(s), json::type_error); + CHECK_THROWS_WITH(j.swap(s), "[except.308] cannot use swap() with number"); } } } @@ -8963,8 +9149,8 @@ { json j(json::value_t::null); json::iterator it = j.begin(); - CHECK_THROWS_AS(*it, std::out_of_range); - CHECK_THROWS_WITH(*it, "cannot get value"); + CHECK_THROWS_AS(*it, json::invalid_iterator); + CHECK_THROWS_WITH(*it, "[except.114] cannot get value"); } SECTION("number") @@ -8973,8 +9159,8 @@ json::iterator it = j.begin(); CHECK(*it == json(17)); it = j.end(); - CHECK_THROWS_AS(*it, std::out_of_range); - CHECK_THROWS_WITH(*it, "cannot get value"); + CHECK_THROWS_AS(*it, json::invalid_iterator); + CHECK_THROWS_WITH(*it, "[except.114] cannot get value"); } SECTION("object") @@ -8998,8 +9184,8 @@ { json j(json::value_t::null); json::iterator it = j.begin(); - CHECK_THROWS_AS(it->type_name(), std::out_of_range); - CHECK_THROWS_WITH(it->type_name(), "cannot get value"); + CHECK_THROWS_AS(it->type_name(), json::invalid_iterator); + CHECK_THROWS_WITH(it->type_name(), "[except.114] cannot get value"); } SECTION("number") @@ -9008,8 +9194,8 @@ json::iterator it = j.begin(); CHECK(it->type_name() == "number"); it = j.end(); - CHECK_THROWS_AS(it->type_name(), std::out_of_range); - CHECK_THROWS_WITH(it->type_name(), "cannot get value"); + CHECK_THROWS_AS(it->type_name(), json::invalid_iterator); + CHECK_THROWS_WITH(it->type_name(), "[except.114] cannot get value"); } SECTION("object") @@ -9331,8 +9517,8 @@ { json j(json::value_t::null); json::const_iterator it = j.cbegin(); - CHECK_THROWS_AS(*it, std::out_of_range); - CHECK_THROWS_WITH(*it, "cannot get value"); + CHECK_THROWS_AS(*it, json::invalid_iterator); + CHECK_THROWS_WITH(*it, "[except.114] cannot get value"); } SECTION("number") @@ -9341,8 +9527,8 @@ json::const_iterator it = j.cbegin(); CHECK(*it == json(17)); it = j.cend(); - CHECK_THROWS_AS(*it, std::out_of_range); - CHECK_THROWS_WITH(*it, "cannot get value"); + CHECK_THROWS_AS(*it, json::invalid_iterator); + CHECK_THROWS_WITH(*it, "[except.114] cannot get value"); } SECTION("object") @@ -9366,8 +9552,8 @@ { json j(json::value_t::null); json::const_iterator it = j.cbegin(); - CHECK_THROWS_AS(it->type_name(), std::out_of_range); - CHECK_THROWS_WITH(it->type_name(), "cannot get value"); + CHECK_THROWS_AS(it->type_name(), json::invalid_iterator); + CHECK_THROWS_WITH(it->type_name(), "[except.114] cannot get value"); } SECTION("number") @@ -9376,8 +9562,8 @@ json::const_iterator it = j.cbegin(); CHECK(it->type_name() == "number"); it = j.cend(); - CHECK_THROWS_AS(it->type_name(), std::out_of_range); - CHECK_THROWS_WITH(it->type_name(), "cannot get value"); + CHECK_THROWS_AS(it->type_name(), json::invalid_iterator); + CHECK_THROWS_WITH(it->type_name(), "[except.114] cannot get value"); } SECTION("object") @@ -9774,9 +9960,11 @@ SECTION("to_unicode") { - CHECK(json::lexer::to_unicode(0x1F4A9) == "💩"); - CHECK_THROWS_AS(json::lexer::to_unicode(0x200000), std::out_of_range); - CHECK_THROWS_WITH(json::lexer::to_unicode(0x200000), "code points above 0x10FFFF are invalid"); + json::lexer l(""); + CHECK(l.to_unicode(0x1F4A9) == "💩"); + CHECK_THROWS_AS(l.to_unicode(0x200000), json::parse_error); + CHECK_THROWS_WITH(l.to_unicode(0x200000), + "[except.203] parse error: unexpected end of input at byte 1; code points above 0x10FFFF are invalid"); } } @@ -9835,51 +10023,55 @@ SECTION("errors") { // error: tab in string - CHECK_THROWS_AS(json::parser("\"\t\"").parse(), std::invalid_argument); - CHECK_THROWS_WITH(json::parser("\"\t\"").parse(), "parse error - unexpected '\"'"); + CHECK_THROWS_AS(json::parser("\"\t\"").parse(), json::parse_error); + CHECK_THROWS_WITH(json::parser("\"\t\"").parse(), + "[except.201] parse error: unexpected '\"' at byte 1; expected JSON value"); // error: newline in string - CHECK_THROWS_AS(json::parser("\"\n\"").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("\"\r\"").parse(), std::invalid_argument); - CHECK_THROWS_WITH(json::parser("\"\n\"").parse(), "parse error - unexpected '\"'"); - CHECK_THROWS_WITH(json::parser("\"\r\"").parse(), "parse error - unexpected '\"'"); + CHECK_THROWS_AS(json::parser("\"\n\"").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("\"\r\"").parse(), json::parse_error); + CHECK_THROWS_WITH(json::parser("\"\n\"").parse(), + "[except.201] parse error: unexpected '\"' at byte 1; expected JSON value"); + CHECK_THROWS_WITH(json::parser("\"\r\"").parse(), + "[except.201] parse error: unexpected '\"' at byte 1; expected JSON value"); // error: backspace in string - CHECK_THROWS_AS(json::parser("\"\b\"").parse(), std::invalid_argument); - CHECK_THROWS_WITH(json::parser("\"\b\"").parse(), "parse error - unexpected '\"'"); + CHECK_THROWS_AS(json::parser("\"\b\"").parse(), json::parse_error); + CHECK_THROWS_WITH(json::parser("\"\b\"").parse(), + "[except.201] parse error: unexpected '\"' at byte 1; expected JSON value"); // improve code coverage - CHECK_THROWS_AS(json::parser("\uFF01").parse(), std::invalid_argument); + CHECK_THROWS_AS(json::parser("\uFF01").parse(), json::parse_error); // unescaped control characters - CHECK_THROWS_AS(json::parser("\"\x00\"").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("\"\x01\"").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("\"\x02\"").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("\"\x03\"").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("\"\x04\"").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("\"\x05\"").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("\"\x06\"").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("\"\x07\"").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("\"\x08\"").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("\"\x09\"").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("\"\x0a\"").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("\"\x0b\"").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("\"\x0c\"").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("\"\x0d\"").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("\"\x0e\"").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("\"\x0f\"").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("\"\x10\"").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("\"\x11\"").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("\"\x12\"").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("\"\x13\"").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("\"\x14\"").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("\"\x15\"").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("\"\x16\"").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("\"\x17\"").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("\"\x18\"").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("\"\x19\"").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("\"\x1a\"").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("\"\x1b\"").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("\"\x1c\"").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("\"\x1d\"").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("\"\x1e\"").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("\"\x1f\"").parse(), std::invalid_argument); + CHECK_THROWS_AS(json::parser("\"\x00\"").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("\"\x01\"").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("\"\x02\"").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("\"\x03\"").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("\"\x04\"").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("\"\x05\"").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("\"\x06\"").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("\"\x07\"").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("\"\x08\"").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("\"\x09\"").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("\"\x0a\"").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("\"\x0b\"").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("\"\x0c\"").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("\"\x0d\"").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("\"\x0e\"").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("\"\x0f\"").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("\"\x10\"").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("\"\x11\"").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("\"\x12\"").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("\"\x13\"").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("\"\x14\"").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("\"\x15\"").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("\"\x16\"").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("\"\x17\"").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("\"\x18\"").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("\"\x19\"").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("\"\x1a\"").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("\"\x1b\"").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("\"\x1c\"").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("\"\x1d\"").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("\"\x1e\"").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("\"\x1f\"").parse(), json::parse_error); } SECTION("escaped") @@ -10017,58 +10209,59 @@ SECTION("invalid numbers") { - CHECK_THROWS_AS(json::parser("01").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("--1").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("1.").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("1E").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("1E-").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("1.E1").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("-1E").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("-0E#").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("-0E-#").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("-0#").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("-0.0:").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("-0.0Z").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("-0E123:").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("-0e0-:").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("-0e-:").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("-0f").parse(), std::invalid_argument); + CHECK_THROWS_AS(json::parser("01").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("--1").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("1.").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("1E").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("1E-").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("1.E1").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("-1E").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("-0E#").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("-0E-#").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("-0#").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("-0.0:").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("-0.0Z").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("-0E123:").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("-0e0-:").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("-0e-:").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("-0f").parse(), json::parse_error); // numbers must not begin with "+" - CHECK_THROWS_AS(json::parser("+1").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("+0").parse(), std::invalid_argument); + CHECK_THROWS_AS(json::parser("+1").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("+0").parse(), json::parse_error); CHECK_THROWS_WITH(json::parser("01").parse(), - "parse error - unexpected number literal; expected end of input"); - CHECK_THROWS_WITH(json::parser("--1").parse(), "parse error - unexpected '-'"); + "[except.201] parse error: unexpected '1' at byte 2; expected end of input"); + CHECK_THROWS_WITH(json::parser("--1").parse(), + "[except.201] parse error: unexpected '-' at byte 1; expected JSON value"); CHECK_THROWS_WITH(json::parser("1.").parse(), - "parse error - unexpected '.'; expected end of input"); + "[except.201] parse error: unexpected '.' at byte 2; expected end of input"); CHECK_THROWS_WITH(json::parser("1E").parse(), - "parse error - unexpected 'E'; expected end of input"); + "[except.201] parse error: unexpected 'E' at byte 2; expected end of input"); CHECK_THROWS_WITH(json::parser("1E-").parse(), - "parse error - unexpected 'E'; expected end of input"); + "[except.201] parse error: unexpected 'E' at byte 2; expected end of input"); CHECK_THROWS_WITH(json::parser("1.E1").parse(), - "parse error - unexpected '.'; expected end of input"); + "[except.201] parse error: unexpected '.' at byte 2; expected end of input"); CHECK_THROWS_WITH(json::parser("-1E").parse(), - "parse error - unexpected 'E'; expected end of input"); + "[except.201] parse error: unexpected 'E' at byte 3; expected end of input"); CHECK_THROWS_WITH(json::parser("-0E#").parse(), - "parse error - unexpected 'E'; expected end of input"); + "[except.201] parse error: unexpected 'E' at byte 3; expected end of input"); CHECK_THROWS_WITH(json::parser("-0E-#").parse(), - "parse error - unexpected 'E'; expected end of input"); + "[except.201] parse error: unexpected 'E' at byte 3; expected end of input"); CHECK_THROWS_WITH(json::parser("-0#").parse(), - "parse error - unexpected '#'; expected end of input"); + "[except.201] parse error: unexpected '#' at byte 3; expected end of input"); CHECK_THROWS_WITH(json::parser("-0.0:").parse(), - "parse error - unexpected ':'; expected end of input"); + "[except.201] parse error: unexpected ':' at byte 5; expected end of input"); CHECK_THROWS_WITH(json::parser("-0.0Z").parse(), - "parse error - unexpected 'Z'; expected end of input"); + "[except.201] parse error: unexpected 'Z' at byte 5; expected end of input"); CHECK_THROWS_WITH(json::parser("-0E123:").parse(), - "parse error - unexpected ':'; expected end of input"); + "[except.201] parse error: unexpected ':' at byte 7; expected end of input"); CHECK_THROWS_WITH(json::parser("-0e0-:").parse(), - "parse error - unexpected '-'; expected end of input"); + "[except.201] parse error: unexpected '-' at byte 5; expected end of input"); CHECK_THROWS_WITH(json::parser("-0e-:").parse(), - "parse error - unexpected 'e'; expected end of input"); + "[except.201] parse error: unexpected 'e' at byte 3; expected end of input"); CHECK_THROWS_WITH(json::parser("-0f").parse(), - "parse error - unexpected 'f'; expected end of input"); + "[except.201] parse error: unexpected 'f' at byte 3; expected end of input"); } } } @@ -10076,135 +10269,150 @@ SECTION("parse errors") { // unexpected end of number - CHECK_THROWS_AS(json::parser("0.").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("-").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("--").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("-0.").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("-.").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("-:").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("0.:").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("e.").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("1e.").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("1e/").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("1e:").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("1E.").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("1E/").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("1E:").parse(), std::invalid_argument); + CHECK_THROWS_AS(json::parser("0.").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("-").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("--").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("-0.").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("-.").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("-:").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("0.:").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("e.").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("1e.").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("1e/").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("1e:").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("1E.").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("1E/").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("1E:").parse(), json::parse_error); CHECK_THROWS_WITH(json::parser("0.").parse(), - "parse error - unexpected '.'; expected end of input"); - CHECK_THROWS_WITH(json::parser("-").parse(), "parse error - unexpected '-'"); + "[except.201] parse error: unexpected '.' at byte 2; expected end of input"); + CHECK_THROWS_WITH(json::parser("-").parse(), + "[except.201] parse error: unexpected '-' at byte 1; expected JSON value"); CHECK_THROWS_WITH(json::parser("--").parse(), - "parse error - unexpected '-'"); + "[except.201] parse error: unexpected '-' at byte 1; expected JSON value"); CHECK_THROWS_WITH(json::parser("-0.").parse(), - "parse error - unexpected '.'; expected end of input"); + "[except.201] parse error: unexpected '.' at byte 3; expected end of input"); CHECK_THROWS_WITH(json::parser("-.").parse(), - "parse error - unexpected '-'"); + "[except.201] parse error: unexpected '-' at byte 1; expected JSON value"); CHECK_THROWS_WITH(json::parser("-:").parse(), - "parse error - unexpected '-'"); + "[except.201] parse error: unexpected '-' at byte 1; expected JSON value"); CHECK_THROWS_WITH(json::parser("0.:").parse(), - "parse error - unexpected '.'; expected end of input"); + "[except.201] parse error: unexpected '.' at byte 2; expected end of input"); CHECK_THROWS_WITH(json::parser("e.").parse(), - "parse error - unexpected 'e'"); + "[except.201] parse error: unexpected 'e' at byte 1; expected JSON value"); CHECK_THROWS_WITH(json::parser("1e.").parse(), - "parse error - unexpected 'e'; expected end of input"); + "[except.201] parse error: unexpected 'e' at byte 2; expected end of input"); CHECK_THROWS_WITH(json::parser("1e/").parse(), - "parse error - unexpected 'e'; expected end of input"); + "[except.201] parse error: unexpected 'e' at byte 2; expected end of input"); CHECK_THROWS_WITH(json::parser("1e:").parse(), - "parse error - unexpected 'e'; expected end of input"); + "[except.201] parse error: unexpected 'e' at byte 2; expected end of input"); CHECK_THROWS_WITH(json::parser("1E.").parse(), - "parse error - unexpected 'E'; expected end of input"); + "[except.201] parse error: unexpected 'E' at byte 2; expected end of input"); CHECK_THROWS_WITH(json::parser("1E/").parse(), - "parse error - unexpected 'E'; expected end of input"); + "[except.201] parse error: unexpected 'E' at byte 2; expected end of input"); CHECK_THROWS_WITH(json::parser("1E:").parse(), - "parse error - unexpected 'E'; expected end of input"); + "[except.201] parse error: unexpected 'E' at byte 2; expected end of input"); // unexpected end of null - CHECK_THROWS_AS(json::parser("n").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("nu").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("nul").parse(), std::invalid_argument); - CHECK_THROWS_WITH(json::parser("n").parse(), "parse error - unexpected 'n'"); + CHECK_THROWS_AS(json::parser("n").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("nu").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("nul").parse(), json::parse_error); + CHECK_THROWS_WITH(json::parser("n").parse(), + "[except.201] parse error: unexpected 'n' at byte 1; expected JSON value"); CHECK_THROWS_WITH(json::parser("nu").parse(), - "parse error - unexpected 'n'"); + "[except.201] parse error: unexpected 'n' at byte 1; expected JSON value"); CHECK_THROWS_WITH(json::parser("nul").parse(), - "parse error - unexpected 'n'"); + "[except.201] parse error: unexpected 'n' at byte 1; expected JSON value"); // unexpected end of true - CHECK_THROWS_AS(json::parser("t").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("tr").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("tru").parse(), std::invalid_argument); - CHECK_THROWS_WITH(json::parser("t").parse(), "parse error - unexpected 't'"); + CHECK_THROWS_AS(json::parser("t").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("tr").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("tru").parse(), json::parse_error); + CHECK_THROWS_WITH(json::parser("t").parse(), + "[except.201] parse error: unexpected 't' at byte 1; expected JSON value"); CHECK_THROWS_WITH(json::parser("tr").parse(), - "parse error - unexpected 't'"); + "[except.201] parse error: unexpected 't' at byte 1; expected JSON value"); CHECK_THROWS_WITH(json::parser("tru").parse(), - "parse error - unexpected 't'"); + "[except.201] parse error: unexpected 't' at byte 1; expected JSON value"); // unexpected end of false - CHECK_THROWS_AS(json::parser("f").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("fa").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("fal").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("fals").parse(), std::invalid_argument); - CHECK_THROWS_WITH(json::parser("f").parse(), "parse error - unexpected 'f'"); + CHECK_THROWS_AS(json::parser("f").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("fa").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("fal").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("fals").parse(), json::parse_error); + CHECK_THROWS_WITH(json::parser("f").parse(), + "[except.201] parse error: unexpected 'f' at byte 1; expected JSON value"); CHECK_THROWS_WITH(json::parser("fa").parse(), - "parse error - unexpected 'f'"); + "[except.201] parse error: unexpected 'f' at byte 1; expected JSON value"); CHECK_THROWS_WITH(json::parser("fal").parse(), - "parse error - unexpected 'f'"); + "[except.201] parse error: unexpected 'f' at byte 1; expected JSON value"); CHECK_THROWS_WITH(json::parser("fals").parse(), - "parse error - unexpected 'f'"); + "[except.201] parse error: unexpected 'f' at byte 1; expected JSON value"); // missing/unexpected end of array - CHECK_THROWS_AS(json::parser("[").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("[1").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("[1,").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("[1,]").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("]").parse(), std::invalid_argument); + CHECK_THROWS_AS(json::parser("[").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("[,").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("[1").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("[1,").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("[1,]").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("]").parse(), json::parse_error); CHECK_THROWS_WITH(json::parser("[").parse(), - "parse error - unexpected end of input"); + "[except.201] parse error: unexpected end of input at byte 2; expected JSON value"); + CHECK_THROWS_WITH(json::parser("[,").parse(), + "[except.201] parse error: unexpected ',' at byte 2; expected JSON value"); CHECK_THROWS_WITH(json::parser("[1").parse(), - "parse error - unexpected end of input; expected ']'"); + "[except.201] parse error: unexpected end of input at byte 3; expected ']'"); CHECK_THROWS_WITH(json::parser("[1,").parse(), - "parse error - unexpected end of input"); + "[except.201] parse error: unexpected end of input at byte 4; expected JSON value"); CHECK_THROWS_WITH(json::parser("[1,]").parse(), - "parse error - unexpected ']'"); - CHECK_THROWS_WITH(json::parser("]").parse(), "parse error - unexpected ']'"); + "[except.201] parse error: unexpected ']' at byte 4; expected JSON value"); + CHECK_THROWS_WITH(json::parser("]").parse(), + "[except.201] parse error: unexpected ']' at byte 1; expected JSON value"); // missing/unexpected end of object - CHECK_THROWS_AS(json::parser("{").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("{\"foo\"").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("{\"foo\":").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("{\"foo\":}").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("{\"foo\":1,}").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("}").parse(), std::invalid_argument); + CHECK_THROWS_AS(json::parser("{").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("{,").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("{\"foo\"").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("{\"foo\":").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("{\"foo\":}").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("{\"foo\":1").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("{\"foo\":1,}").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("}").parse(), json::parse_error); CHECK_THROWS_WITH(json::parser("{").parse(), - "parse error - unexpected end of input; expected string literal"); + "[except.201] parse error: unexpected end of input at byte 2; expected string literal"); + CHECK_THROWS_WITH(json::parser("{,").parse(), + "[except.201] parse error: unexpected ',' at byte 2; expected JSON value"); CHECK_THROWS_WITH(json::parser("{\"foo\"").parse(), - "parse error - unexpected end of input; expected ':'"); + "[except.201] parse error: unexpected end of input at byte 7; expected ':'"); CHECK_THROWS_WITH(json::parser("{\"foo\":").parse(), - "parse error - unexpected end of input"); + "[except.201] parse error: unexpected end of input at byte 8; expected JSON value"); CHECK_THROWS_WITH(json::parser("{\"foo\":}").parse(), - "parse error - unexpected '}'"); + "[except.201] parse error: unexpected '}' at byte 8; expected JSON value"); + CHECK_THROWS_WITH(json::parser("{\"foo\":1").parse(), + "[except.201] parse error: unexpected end of input at byte 9; expected '}'"); CHECK_THROWS_WITH(json::parser("{\"foo\":1,}").parse(), - "parse error - unexpected '}'; expected string literal"); - CHECK_THROWS_WITH(json::parser("}").parse(), "parse error - unexpected '}'"); + "[except.201] parse error: unexpected '}' at byte 10; expected string literal"); + CHECK_THROWS_WITH(json::parser("}").parse(), + "[except.201] parse error: unexpected '}' at byte 1; expected JSON value"); // missing/unexpected end of string - CHECK_THROWS_AS(json::parser("\"").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("\"\\\"").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("\"\\u\"").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("\"\\u0\"").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("\"\\u01\"").parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser("\"\\u012\"").parse(), std::invalid_argument); + CHECK_THROWS_AS(json::parser("\"").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("\"\\\"").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("\"\\u\"").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("\"\\u0\"").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("\"\\u01\"").parse(), json::parse_error); + CHECK_THROWS_AS(json::parser("\"\\u012\"").parse(), json::parse_error); CHECK_THROWS_WITH(json::parser("\"").parse(), - "parse error - unexpected '\"'"); + "[except.201] parse error: unexpected '\"' at byte 1; expected JSON value"); CHECK_THROWS_WITH(json::parser("\"\\\"").parse(), - "parse error - unexpected '\"'"); + "[except.201] parse error: unexpected '\"' at byte 1; expected JSON value"); CHECK_THROWS_WITH(json::parser("\"\\u\"").parse(), - "parse error - unexpected '\"'"); + "[except.201] parse error: unexpected '\"' at byte 1; expected JSON value"); CHECK_THROWS_WITH(json::parser("\"\\u0\"").parse(), - "parse error - unexpected '\"'"); + "[except.201] parse error: unexpected '\"' at byte 1; expected JSON value"); CHECK_THROWS_WITH(json::parser("\"\\u01\"").parse(), - "parse error - unexpected '\"'"); + "[except.201] parse error: unexpected '\"' at byte 1; expected JSON value"); CHECK_THROWS_WITH(json::parser("\"\\u012\"").parse(), - "parse error - unexpected '\"'"); + "[except.201] parse error: unexpected '\"' at byte 1; expected JSON value"); // invalid escapes for (int c = 1; c < 128; ++c) @@ -10236,8 +10444,9 @@ // any other combination of backslash and character is invalid default: { - CHECK_THROWS_AS(json::parser(s).parse(), std::invalid_argument); - CHECK_THROWS_WITH(json::parser(s).parse(), "parse error - unexpected '\"'"); + CHECK_THROWS_AS(json::parser(s).parse(), json::parse_error); + CHECK_THROWS_WITH(json::parser(s).parse(), + "[except.201] parse error: unexpected '\"' at byte 1; expected JSON value"); break; } } @@ -10302,32 +10511,37 @@ } else { - CHECK_THROWS_AS(json::parser(s1).parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser(s2).parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser(s3).parse(), std::invalid_argument); - CHECK_THROWS_AS(json::parser(s4).parse(), std::invalid_argument); + CHECK_THROWS_AS(json::parser(s1).parse(), json::parse_error); + CHECK_THROWS_AS(json::parser(s2).parse(), json::parse_error); + CHECK_THROWS_AS(json::parser(s3).parse(), json::parse_error); + CHECK_THROWS_AS(json::parser(s4).parse(), json::parse_error); - CHECK_THROWS_WITH(json::parser(s1).parse(), "parse error - unexpected '\"'"); - CHECK_THROWS_WITH(json::parser(s2).parse(), "parse error - unexpected '\"'"); - CHECK_THROWS_WITH(json::parser(s3).parse(), "parse error - unexpected '\"'"); - CHECK_THROWS_WITH(json::parser(s4).parse(), "parse error - unexpected '\"'"); + CHECK_THROWS_WITH(json::parser(s1).parse(), + "[except.201] parse error: unexpected '\"' at byte 1; expected JSON value"); + CHECK_THROWS_WITH(json::parser(s2).parse(), + "[except.201] parse error: unexpected '\"' at byte 1; expected JSON value"); + CHECK_THROWS_WITH(json::parser(s3).parse(), + "[except.201] parse error: unexpected '\"' at byte 1; expected JSON value"); + CHECK_THROWS_WITH(json::parser(s4).parse(), + "[except.201] parse error: unexpected '\"' at byte 1; expected JSON value"); } } } // missing part of a surrogate pair - CHECK_THROWS_AS(json::parse("\"\\uD80C\""), std::invalid_argument); - CHECK_THROWS_WITH(json::parse("\"\\uD80C\""), "missing low surrogate"); + CHECK_THROWS_AS(json::parse("\"\\uD80C\""), json::parse_error); + CHECK_THROWS_WITH(json::parse("\"\\uD80C\""), + "[except.204] parse error: unexpected '\"\\uD80C\"' at byte 1; missing low surrogate"); // invalid surrogate pair - CHECK_THROWS_AS(json::parse("\"\\uD80C\\uD80C\""), std::invalid_argument); - CHECK_THROWS_AS(json::parse("\"\\uD80C\\u0000\""), std::invalid_argument); - CHECK_THROWS_AS(json::parse("\"\\uD80C\\uFFFF\""), std::invalid_argument); + CHECK_THROWS_AS(json::parse("\"\\uD80C\\uD80C\""), json::parse_error); + CHECK_THROWS_AS(json::parse("\"\\uD80C\\u0000\""), json::parse_error); + CHECK_THROWS_AS(json::parse("\"\\uD80C\\uFFFF\""), json::parse_error); CHECK_THROWS_WITH(json::parse("\"\\uD80C\\uD80C\""), - "missing or wrong low surrogate"); + "[except.202] parse error: unexpected '\"\\uD80C\\uD80C\"' at byte 1; missing or wrong low surrogate"); CHECK_THROWS_WITH(json::parse("\"\\uD80C\\u0000\""), - "missing or wrong low surrogate"); + "[except.202] parse error: unexpected '\"\\uD80C\\u0000\"' at byte 1; missing or wrong low surrogate"); CHECK_THROWS_WITH(json::parse("\"\\uD80C\\uFFFF\""), - "missing or wrong low surrogate"); + "[except.202] parse error: unexpected '\"\\uD80C\\uFFFF\"' at byte 1; missing or wrong low surrogate"); } SECTION("callback function") @@ -10970,8 +11184,9 @@ SECTION("sorting an object") { json j({{"one", 1}, {"two", 2}}); - CHECK_THROWS_AS(std::sort(j.begin(), j.end()), std::domain_error); - CHECK_THROWS_WITH(std::sort(j.begin(), j.end()), "cannot use offsets with object iterators"); + CHECK_THROWS_AS(std::sort(j.begin(), j.end()), json::invalid_iterator); + CHECK_THROWS_WITH(std::sort(j.begin(), j.end()), + "[except.109] cannot use offsets with object iterators"); } } @@ -11927,7 +12142,7 @@ CAPTURE(filename); json j; std::ifstream f(filename); - CHECK_THROWS_AS(j << f, std::invalid_argument); + CHECK_THROWS_AS(j << f, json::parse_error); } } @@ -12321,6 +12536,9 @@ // string to store the code point as unescaped character sequence std::string unescaped_string; + // a lexer to call "to_unicode" + json::lexer l(""); + if (cp < 0x10000u) { // code points in the Basic Multilingual Plane can be @@ -12334,7 +12552,7 @@ // they are checked with codepoint_to_unicode. if (cp > 0x1f and cp != 0x22 and cp != 0x5c) { - unescaped_string = json::lexer::to_unicode(cp); + unescaped_string = l.to_unicode(cp); } } else @@ -12346,7 +12564,7 @@ const auto codepoint2 = 0xdc00u + ((cp - 0x10000u) & 0x3ffu); escaped_string = codepoint_to_unicode(codepoint1); escaped_string += codepoint_to_unicode(codepoint2); - unescaped_string += json::lexer::to_unicode(codepoint1, codepoint2); + unescaped_string += l.to_unicode(codepoint1, codepoint2); } // all other code points are valid and must not yield parse errors @@ -12419,8 +12637,8 @@ SECTION("error for incomplete/wrong BOM") { - CHECK_THROWS_AS(json::parse("\xef\xbb"), std::invalid_argument); - CHECK_THROWS_AS(json::parse("\xef\xbb\xbb"), std::invalid_argument); + CHECK_THROWS_AS(json::parse("\xef\xbb"), json::parse_error); + CHECK_THROWS_AS(json::parse("\xef\xbb\xbb"), json::parse_error); } } @@ -12428,20 +12646,23 @@ { SECTION("errors") { - CHECK_THROWS_AS(json::json_pointer("foo"), std::domain_error); - CHECK_THROWS_WITH(json::json_pointer("foo"), "JSON pointer must be empty or begin with '/'"); + CHECK_THROWS_AS(json::json_pointer("foo"), json::extension_error); + CHECK_THROWS_WITH(json::json_pointer("foo"), + "[except.403] JSON pointer must be empty or begin with '/'"); - CHECK_THROWS_AS(json::json_pointer("/~~"), std::domain_error); - CHECK_THROWS_WITH(json::json_pointer("/~~"), "escape error: '~' must be followed with '0' or '1'"); + CHECK_THROWS_AS(json::json_pointer("/~~"), json::extension_error); + CHECK_THROWS_WITH(json::json_pointer("/~~"), + "[except.404] escape error: '~' must be followed with '0' or '1'"); - CHECK_THROWS_AS(json::json_pointer("/~"), std::domain_error); - CHECK_THROWS_WITH(json::json_pointer("/~"), "escape error: '~' must be followed with '0' or '1'"); + CHECK_THROWS_AS(json::json_pointer("/~"), json::extension_error); + CHECK_THROWS_WITH(json::json_pointer("/~"), + "[except.404] escape error: '~' must be followed with '0' or '1'"); json::json_pointer p; - CHECK_THROWS_AS(p.top(), std::domain_error); - CHECK_THROWS_WITH(p.top(), "JSON pointer has no parent"); - CHECK_THROWS_AS(p.pop_back(), std::domain_error); - CHECK_THROWS_WITH(p.pop_back(), "JSON pointer has no parent"); + CHECK_THROWS_AS(p.top(), json::extension_error); + CHECK_THROWS_WITH(p.top(), "[except.401] JSON pointer has no parent"); + CHECK_THROWS_AS(p.pop_back(), json::extension_error); + CHECK_THROWS_WITH(p.pop_back(), "[except.401] JSON pointer has no parent"); } SECTION("examples from RFC 6901") @@ -12501,17 +12722,20 @@ CHECK(j[json::json_pointer("/m~0n")] == j["m~n"]); // unescaped access - CHECK_THROWS_AS(j[json::json_pointer("/a/b")], std::out_of_range); - CHECK_THROWS_WITH(j[json::json_pointer("/a/b")], "unresolved reference token 'b'"); + CHECK_THROWS_AS(j[json::json_pointer("/a/b")], json::extension_error); + CHECK_THROWS_WITH(j[json::json_pointer("/a/b")], + "[except.405] unresolved reference token 'b'"); // "/a/b" works for JSON {"a": {"b": 42}} CHECK(json({{"a", {{"b", 42}}}})[json::json_pointer("/a/b")] == json(42)); // unresolved access json j_primitive = 1; - CHECK_THROWS_AS(j_primitive["/foo"_json_pointer], std::out_of_range); - CHECK_THROWS_WITH(j_primitive["/foo"_json_pointer], "unresolved reference token 'foo'"); - CHECK_THROWS_AS(j_primitive.at("/foo"_json_pointer), std::out_of_range); - CHECK_THROWS_WITH(j_primitive.at("/foo"_json_pointer), "unresolved reference token 'foo'"); + CHECK_THROWS_AS(j_primitive["/foo"_json_pointer], json::extension_error); + CHECK_THROWS_WITH(j_primitive["/foo"_json_pointer], + "[except.405] unresolved reference token 'foo'"); + CHECK_THROWS_AS(j_primitive.at("/foo"_json_pointer), json::extension_error); + CHECK_THROWS_WITH(j_primitive.at("/foo"_json_pointer), + "[except.405] unresolved reference token 'foo'"); } SECTION("const access") @@ -12574,10 +12798,12 @@ // unresolved access const json j_primitive = 1; - CHECK_THROWS_AS(j_primitive["/foo"_json_pointer], std::out_of_range); - CHECK_THROWS_WITH(j_primitive["/foo"_json_pointer], "unresolved reference token 'foo'"); - CHECK_THROWS_AS(j_primitive.at("/foo"_json_pointer), std::out_of_range); - CHECK_THROWS_WITH(j_primitive.at("/foo"_json_pointer), "unresolved reference token 'foo'"); + CHECK_THROWS_AS(j_primitive["/foo"_json_pointer], json::extension_error); + CHECK_THROWS_WITH(j_primitive["/foo"_json_pointer], + "[except.405] unresolved reference token 'foo'"); + CHECK_THROWS_AS(j_primitive.at("/foo"_json_pointer), json::extension_error); + CHECK_THROWS_WITH(j_primitive.at("/foo"_json_pointer), + "[except.405] unresolved reference token 'foo'"); } SECTION("user-defined string literal") @@ -12632,31 +12858,35 @@ CHECK(j == json({1, 13, 3, 33, nullptr, 55})); // error with leading 0 - CHECK_THROWS_AS(j["/01"_json_pointer], std::domain_error); - CHECK_THROWS_WITH(j["/01"_json_pointer], "array index must not begin with '0'"); - CHECK_THROWS_AS(j_const["/01"_json_pointer], std::domain_error); - CHECK_THROWS_WITH(j_const["/01"_json_pointer], "array index must not begin with '0'"); - CHECK_THROWS_AS(j.at("/01"_json_pointer), std::domain_error); - CHECK_THROWS_WITH(j.at("/01"_json_pointer), "array index must not begin with '0'"); - CHECK_THROWS_AS(j_const.at("/01"_json_pointer), std::domain_error); - CHECK_THROWS_WITH(j_const.at("/01"_json_pointer), "array index must not begin with '0'"); + CHECK_THROWS_AS(j["/01"_json_pointer], json::extension_error); + CHECK_THROWS_WITH(j["/01"_json_pointer], "[except.402] array index must not begin with '0'"); + CHECK_THROWS_AS(j_const["/01"_json_pointer], json::extension_error); + CHECK_THROWS_WITH(j_const["/01"_json_pointer], "[except.402] array index must not begin with '0'"); + CHECK_THROWS_AS(j.at("/01"_json_pointer), json::extension_error); + CHECK_THROWS_WITH(j.at("/01"_json_pointer), "[except.402] array index must not begin with '0'"); + CHECK_THROWS_AS(j_const.at("/01"_json_pointer), json::extension_error); + CHECK_THROWS_WITH(j_const.at("/01"_json_pointer), + "[except.402] array index must not begin with '0'"); // error with incorrect numbers - CHECK_THROWS_AS(j["/one"_json_pointer] = 1, std::invalid_argument); + CHECK_THROWS_AS(j["/one"_json_pointer] = 1, json::extension_error); + CHECK_THROWS_WITH(j["/one"_json_pointer], + "[except.402] array index is 'one', but must be a number"); // assign to "-" j["/-"_json_pointer] = 99; CHECK(j == json({1, 13, 3, 33, nullptr, 55, 99})); // error when using "-" in const object - CHECK_THROWS_AS(j_const["/-"_json_pointer], std::out_of_range); - CHECK_THROWS_WITH(j_const["/-"_json_pointer], "array index '-' (3) is out of range"); + CHECK_THROWS_AS(j_const["/-"_json_pointer], json::extension_error); + CHECK_THROWS_WITH(j_const["/-"_json_pointer], "[except.406] array index '-' (3) is out of range"); // error when using "-" with at - CHECK_THROWS_AS(j.at("/-"_json_pointer), std::out_of_range); - CHECK_THROWS_WITH(j.at("/-"_json_pointer), "array index '-' (7) is out of range"); - CHECK_THROWS_AS(j_const.at("/-"_json_pointer), std::out_of_range); - CHECK_THROWS_WITH(j_const.at("/-"_json_pointer), "array index '-' (3) is out of range"); + CHECK_THROWS_AS(j.at("/-"_json_pointer), json::extension_error); + CHECK_THROWS_WITH(j.at("/-"_json_pointer), "[except.406] array index '-' (7) is out of range"); + CHECK_THROWS_AS(j_const.at("/-"_json_pointer), json::extension_error); + CHECK_THROWS_WITH(j_const.at("/-"_json_pointer), + "[except.406] array index '-' (3) is out of range"); } SECTION("const access") @@ -12677,10 +12907,10 @@ CHECK_THROWS_WITH(j.at("/5"_json_pointer), "array index 5 is out of range"); // assign to "-" - CHECK_THROWS_AS(j["/-"_json_pointer], std::out_of_range); - CHECK_THROWS_WITH(j["/-"_json_pointer], "array index '-' (3) is out of range"); - CHECK_THROWS_AS(j.at("/-"_json_pointer), std::out_of_range); - CHECK_THROWS_WITH(j.at("/-"_json_pointer), "array index '-' (3) is out of range"); + CHECK_THROWS_AS(j["/-"_json_pointer], json::extension_error); + CHECK_THROWS_WITH(j["/-"_json_pointer], "[except.406] array index '-' (3) is out of range"); + CHECK_THROWS_AS(j.at("/-"_json_pointer), json::extension_error); + CHECK_THROWS_WITH(j.at("/-"_json_pointer), "[except.406] array index '-' (3) is out of range"); } } @@ -12736,17 +12966,18 @@ CHECK(j_flatten.unflatten() == j); // error for nonobjects - CHECK_THROWS_AS(json(1).unflatten(), std::domain_error); - CHECK_THROWS_WITH(json(1).unflatten(), "only objects can be unflattened"); + CHECK_THROWS_AS(json(1).unflatten(), json::extension_error); + CHECK_THROWS_WITH(json(1).unflatten(), "[except.412] only objects can be unflattened"); // error for nonprimitve values - CHECK_THROWS_AS(json({{"/1", {1, 2, 3}}}).unflatten(), std::domain_error); - CHECK_THROWS_WITH(json({{"/1", {1, 2, 3}}}).unflatten(), "values in object must be primitive"); + CHECK_THROWS_AS(json({{"/1", {1, 2, 3}}}).unflatten(), json::extension_error); + CHECK_THROWS_WITH(json({{"/1", {1, 2, 3}}}).unflatten(), + "[except.413] values in object must be primitive"); // error for conflicting values json j_error = {{"", 42}, {"/foo", 17}}; - CHECK_THROWS_AS(j_error.unflatten(), std::domain_error); - CHECK_THROWS_WITH(j_error.unflatten(), "invalid value to unflatten"); + CHECK_THROWS_AS(j_error.unflatten(), json::extension_error); + CHECK_THROWS_WITH(j_error.unflatten(), "[except.411] invalid value to unflatten"); // explicit roundtrip check CHECK(j.flatten().unflatten() == j); @@ -13084,8 +13315,8 @@ )"_json; // check that evaluation throws - CHECK_THROWS_AS(doc.patch(patch), std::domain_error); - CHECK_THROWS_WITH(doc.patch(patch), "unsuccessful: " + patch[0].dump()); + CHECK_THROWS_AS(doc.patch(patch), json::extension_error); + CHECK_THROWS_WITH(doc.patch(patch), "[except.410] unsuccessful: " + patch[0].dump()); } SECTION("A.10. Adding a Nested Member Object") @@ -13224,8 +13455,8 @@ )"_json; // check that evaluation throws - CHECK_THROWS_AS(doc.patch(patch), std::domain_error); - CHECK_THROWS_WITH(doc.patch(patch), "unsuccessful: " + patch[0].dump()); + CHECK_THROWS_AS(doc.patch(patch), json::extension_error); + CHECK_THROWS_WITH(doc.patch(patch), "[except.410] unsuccessful: " + patch[0].dump()); } SECTION("A.16. Adding an Array Value") @@ -13414,40 +13645,40 @@ { json j; json patch = {{"op", "add"}, {"path", ""}, {"value", 1}}; - CHECK_THROWS_AS(j.patch(patch), std::invalid_argument); - CHECK_THROWS_WITH(j.patch(patch), "JSON patch must be an array of objects"); + CHECK_THROWS_AS(j.patch(patch), json::extension_error); + CHECK_THROWS_WITH(j.patch(patch), "[except.407] JSON patch must be an array of objects"); } SECTION("not an array of objects") { json j; json patch = {"op", "add", "path", "", "value", 1}; - CHECK_THROWS_AS(j.patch(patch), std::invalid_argument); - CHECK_THROWS_WITH(j.patch(patch), "JSON patch must be an array of objects"); + CHECK_THROWS_AS(j.patch(patch), json::extension_error); + CHECK_THROWS_WITH(j.patch(patch), "[except.407] JSON patch must be an array of objects"); } SECTION("missing 'op'") { json j; json patch = {{{"foo", "bar"}}}; - CHECK_THROWS_AS(j.patch(patch), std::invalid_argument); - CHECK_THROWS_WITH(j.patch(patch), "operation must have member 'op'"); + CHECK_THROWS_AS(j.patch(patch), json::extension_error); + CHECK_THROWS_WITH(j.patch(patch), "[except.408] operation must have string member 'op'"); } SECTION("non-string 'op'") { json j; json patch = {{{"op", 1}}}; - CHECK_THROWS_AS(j.patch(patch), std::invalid_argument); - CHECK_THROWS_WITH(j.patch(patch), "operation must have string member 'op'"); + CHECK_THROWS_AS(j.patch(patch), json::extension_error); + CHECK_THROWS_WITH(j.patch(patch), "[except.408] operation must have string member 'op'"); } SECTION("invalid operation") { json j; json patch = {{{"op", "foo"}, {"path", ""}}}; - CHECK_THROWS_AS(j.patch(patch), std::invalid_argument); - CHECK_THROWS_WITH(j.patch(patch), "operation value 'foo' is invalid"); + CHECK_THROWS_AS(j.patch(patch), json::extension_error); + CHECK_THROWS_WITH(j.patch(patch), "[except.409] operation value 'foo' is invalid"); } } @@ -13457,32 +13688,32 @@ { json j; json patch = {{{"op", "add"}}}; - CHECK_THROWS_AS(j.patch(patch), std::invalid_argument); - CHECK_THROWS_WITH(j.patch(patch), "operation 'add' must have member 'path'"); + CHECK_THROWS_AS(j.patch(patch), json::extension_error); + CHECK_THROWS_WITH(j.patch(patch), "[except.408] operation 'add' must have string member 'path'"); } SECTION("non-string 'path'") { json j; json patch = {{{"op", "add"}, {"path", 1}}}; - CHECK_THROWS_AS(j.patch(patch), std::invalid_argument); - CHECK_THROWS_WITH(j.patch(patch), "operation 'add' must have string member 'path'"); + CHECK_THROWS_AS(j.patch(patch), json::extension_error); + CHECK_THROWS_WITH(j.patch(patch), "[except.408] operation 'add' must have string member 'path'"); } SECTION("missing 'value'") { json j; json patch = {{{"op", "add"}, {"path", ""}}}; - CHECK_THROWS_AS(j.patch(patch), std::invalid_argument); - CHECK_THROWS_WITH(j.patch(patch), "operation 'add' must have member 'value'"); + CHECK_THROWS_AS(j.patch(patch), json::extension_error); + CHECK_THROWS_WITH(j.patch(patch), "[except.408] operation 'add' must have string member 'value'"); } SECTION("invalid array index") { json j = {1, 2}; json patch = {{{"op", "add"}, {"path", "/4"}, {"value", 4}}}; - CHECK_THROWS_AS(j.patch(patch), std::out_of_range); - CHECK_THROWS_WITH(j.patch(patch), "array index 4 is out of range"); + CHECK_THROWS_AS(j.patch(patch), json::extension_error); + CHECK_THROWS_WITH(j.patch(patch), "[except.406] array index 4 is out of range"); } } @@ -13492,16 +13723,16 @@ { json j; json patch = {{{"op", "remove"}}}; - CHECK_THROWS_AS(j.patch(patch), std::invalid_argument); - CHECK_THROWS_WITH(j.patch(patch), "operation 'remove' must have member 'path'"); + CHECK_THROWS_AS(j.patch(patch), json::extension_error); + CHECK_THROWS_WITH(j.patch(patch), "[except.408] operation 'remove' must have string member 'path'"); } SECTION("non-string 'path'") { json j; json patch = {{{"op", "remove"}, {"path", 1}}}; - CHECK_THROWS_AS(j.patch(patch), std::invalid_argument); - CHECK_THROWS_WITH(j.patch(patch), "operation 'remove' must have string member 'path'"); + CHECK_THROWS_AS(j.patch(patch), json::extension_error); + CHECK_THROWS_WITH(j.patch(patch), "[except.408] operation 'remove' must have string member 'path'"); } SECTION("nonexisting target location (array)") @@ -13524,8 +13755,8 @@ { json j = "string"; json patch = {{{"op", "remove"}, {"path", ""}}}; - CHECK_THROWS_AS(j.patch(patch), std::domain_error); - CHECK_THROWS_WITH(j.patch(patch), "JSON pointer has no parent"); + CHECK_THROWS_AS(j.patch(patch), json::extension_error); + CHECK_THROWS_WITH(j.patch(patch), "[except.401] JSON pointer has no parent"); } } @@ -13535,24 +13766,27 @@ { json j; json patch = {{{"op", "replace"}}}; - CHECK_THROWS_AS(j.patch(patch), std::invalid_argument); - CHECK_THROWS_WITH(j.patch(patch), "operation 'replace' must have member 'path'"); + CHECK_THROWS_AS(j.patch(patch), json::extension_error); + CHECK_THROWS_WITH(j.patch(patch), + "[except.408] operation 'replace' must have string member 'path'"); } SECTION("non-string 'path'") { json j; json patch = {{{"op", "replace"}, {"path", 1}}}; - CHECK_THROWS_AS(j.patch(patch), std::invalid_argument); - CHECK_THROWS_WITH(j.patch(patch), "operation 'replace' must have string member 'path'"); + CHECK_THROWS_AS(j.patch(patch), json::extension_error); + CHECK_THROWS_WITH(j.patch(patch), + "[except.408] operation 'replace' must have string member 'path'"); } SECTION("missing 'value'") { json j; json patch = {{{"op", "replace"}, {"path", ""}}}; - CHECK_THROWS_AS(j.patch(patch), std::invalid_argument); - CHECK_THROWS_WITH(j.patch(patch), "operation 'replace' must have member 'value'"); + CHECK_THROWS_AS(j.patch(patch), json::extension_error); + CHECK_THROWS_WITH(j.patch(patch), + "[except.408] operation 'replace' must have string member 'value'"); } SECTION("nonexisting target location (array)") @@ -13578,32 +13812,32 @@ { json j; json patch = {{{"op", "move"}}}; - CHECK_THROWS_AS(j.patch(patch), std::invalid_argument); - CHECK_THROWS_WITH(j.patch(patch), "operation 'move' must have member 'path'"); + CHECK_THROWS_AS(j.patch(patch), json::extension_error); + CHECK_THROWS_WITH(j.patch(patch), "[except.408] operation 'move' must have string member 'path'"); } SECTION("non-string 'path'") { json j; json patch = {{{"op", "move"}, {"path", 1}}}; - CHECK_THROWS_AS(j.patch(patch), std::invalid_argument); - CHECK_THROWS_WITH(j.patch(patch), "operation 'move' must have string member 'path'"); + CHECK_THROWS_AS(j.patch(patch), json::extension_error); + CHECK_THROWS_WITH(j.patch(patch), "[except.408] operation 'move' must have string member 'path'"); } SECTION("missing 'from'") { json j; json patch = {{{"op", "move"}, {"path", ""}}}; - CHECK_THROWS_AS(j.patch(patch), std::invalid_argument); - CHECK_THROWS_WITH(j.patch(patch), "operation 'move' must have member 'from'"); + CHECK_THROWS_AS(j.patch(patch), json::extension_error); + CHECK_THROWS_WITH(j.patch(patch), "[except.408] operation 'move' must have string member 'from'"); } SECTION("non-string 'from'") { json j; json patch = {{{"op", "move"}, {"path", ""}, {"from", 1}}}; - CHECK_THROWS_AS(j.patch(patch), std::invalid_argument); - CHECK_THROWS_WITH(j.patch(patch), "operation 'move' must have string member 'from'"); + CHECK_THROWS_AS(j.patch(patch), json::extension_error); + CHECK_THROWS_WITH(j.patch(patch), "[except.408] operation 'move' must have string member 'from'"); } SECTION("nonexisting from location (array)") @@ -13629,32 +13863,32 @@ { json j; json patch = {{{"op", "copy"}}}; - CHECK_THROWS_AS(j.patch(patch), std::invalid_argument); - CHECK_THROWS_WITH(j.patch(patch), "operation 'copy' must have member 'path'"); + CHECK_THROWS_AS(j.patch(patch), json::extension_error); + CHECK_THROWS_WITH(j.patch(patch), "[except.408] operation 'copy' must have string member 'path'"); } SECTION("non-string 'path'") { json j; json patch = {{{"op", "copy"}, {"path", 1}}}; - CHECK_THROWS_AS(j.patch(patch), std::invalid_argument); - CHECK_THROWS_WITH(j.patch(patch), "operation 'copy' must have string member 'path'"); + CHECK_THROWS_AS(j.patch(patch), json::extension_error); + CHECK_THROWS_WITH(j.patch(patch), "[except.408] operation 'copy' must have string member 'path'"); } SECTION("missing 'from'") { json j; json patch = {{{"op", "copy"}, {"path", ""}}}; - CHECK_THROWS_AS(j.patch(patch), std::invalid_argument); - CHECK_THROWS_WITH(j.patch(patch), "operation 'copy' must have member 'from'"); + CHECK_THROWS_AS(j.patch(patch), json::extension_error); + CHECK_THROWS_WITH(j.patch(patch), "[except.408] operation 'copy' must have string member 'from'"); } SECTION("non-string 'from'") { json j; json patch = {{{"op", "copy"}, {"path", ""}, {"from", 1}}}; - CHECK_THROWS_AS(j.patch(patch), std::invalid_argument); - CHECK_THROWS_WITH(j.patch(patch), "operation 'copy' must have string member 'from'"); + CHECK_THROWS_AS(j.patch(patch), json::extension_error); + CHECK_THROWS_WITH(j.patch(patch), "[except.408] operation 'copy' must have string member 'from'"); } SECTION("nonexisting from location (array)") @@ -13680,24 +13914,24 @@ { json j; json patch = {{{"op", "test"}}}; - CHECK_THROWS_AS(j.patch(patch), std::invalid_argument); - CHECK_THROWS_WITH(j.patch(patch), "operation 'test' must have member 'path'"); + CHECK_THROWS_AS(j.patch(patch), json::extension_error); + CHECK_THROWS_WITH(j.patch(patch), "[except.408] operation 'test' must have string member 'path'"); } SECTION("non-string 'path'") { json j; json patch = {{{"op", "test"}, {"path", 1}}}; - CHECK_THROWS_AS(j.patch(patch), std::invalid_argument); - CHECK_THROWS_WITH(j.patch(patch), "operation 'test' must have string member 'path'"); + CHECK_THROWS_AS(j.patch(patch), json::extension_error); + CHECK_THROWS_WITH(j.patch(patch), "[except.408] operation 'test' must have string member 'path'"); } SECTION("missing 'value'") { json j; json patch = {{{"op", "test"}, {"path", ""}}}; - CHECK_THROWS_AS(j.patch(patch), std::invalid_argument); - CHECK_THROWS_WITH(j.patch(patch), "operation 'test' must have member 'value'"); + CHECK_THROWS_AS(j.patch(patch), json::extension_error); + CHECK_THROWS_WITH(j.patch(patch), "[except.408] operation 'test' must have string member 'value'"); } } } @@ -13889,8 +14123,8 @@ )"_json; // the test will fail - CHECK_THROWS_AS(doc.patch(patch), std::domain_error); - CHECK_THROWS_WITH(doc.patch(patch), "unsuccessful: " + patch[0].dump()); + CHECK_THROWS_AS(doc.patch(patch), json::extension_error); + CHECK_THROWS_WITH(doc.patch(patch), "[except.410] unsuccessful: " + patch[0].dump()); } } }