Added class hierarchy for user-defined exceptions (#244). Integrated parse exceptions 101-103. Parse exceptions include the byte count of the last read character to locate the position of the error (#301).
This commit is contained in:
parent
7b8fd864e2
commit
c085e3bac2
9 changed files with 650 additions and 252 deletions
|
@ -58,6 +58,7 @@ doxygen: create_output create_links
|
||||||
$(SED) -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer >@@g' html/*.html
|
$(SED) -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer >@@g' html/*.html
|
||||||
$(SED) -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer >@@g' html/*.html
|
$(SED) -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer >@@g' html/*.html
|
||||||
$(SED) -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType JSONSerializer >@@g' html/*.html
|
$(SED) -i 's@< ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType JSONSerializer >@@g' html/*.html
|
||||||
|
$(SED) -i 's@template<template< typename U, typename V, typename... Args > class ObjectType = std::map, template< typename U, typename... Args > class ArrayType = std::vector, class StringType = std::string, class BooleanType = bool, class NumberIntegerType = std::int64_t, class NumberUnsignedType = std::uint64_t, class NumberFloatType = double, template< typename U > class AllocatorType = std::allocator, template< typename T, typename SFINAE=void > class JSONSerializer = adl_serializer>@@g' html/*.html
|
||||||
|
|
||||||
upload: clean doxygen check_output
|
upload: clean doxygen check_output
|
||||||
cd html ; ../scripts/git-update-ghpages nlohmann/json
|
cd html ; ../scripts/git-update-ghpages nlohmann/json
|
||||||
|
|
209
src/json.hpp
209
src/json.hpp
|
@ -1088,6 +1088,178 @@ class basic_json
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
////////////////
|
||||||
|
// exceptions //
|
||||||
|
////////////////
|
||||||
|
|
||||||
|
/// @name exceptions
|
||||||
|
/// Classes to implement user-defined exceptions.
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@brief general exception of the @ref basic_json class
|
||||||
|
|
||||||
|
Extension of std::exception objects with a member @a id for exception ids.
|
||||||
|
|
||||||
|
name / id | example massage | description
|
||||||
|
------------------------------ | --------------- | -------------------------
|
||||||
|
json.exception.[parse_error](@ref parse_error).101 | `"parse error at 2: unexpected end of input; expected string literal"` | This error indicates a syntax error while deserializing a JSON text. The error message describes that an unexpected token (character) was encountered, and the member @ref parse_error::byte indicates the error position.
|
||||||
|
json.exception.[parse_error](@ref parse_error).102 | `"parse error at 14: missing or wrong low surrogate"` | JSON uses the `\uxxxx` format to describe Unicode characters. Code points above above 0xFFFF are split into two `\uxxxx` entries ("surrogate pairs"). This error indicates that the surrogate pair is incomplete or contains an invalid code point.
|
||||||
|
json.exception.[parse_error](@ref parse_error).103 | `"parse error: code points above 0x10FFFF are invalid"` | Unicode supports code points up to 0x10FFFF. Code points above 0x10FFFF are invalid.
|
||||||
|
json.exception.[parse_error](@ref parse_error).104 | "parse error: JSON patch must be an array of objects" | [RFC 6902](https://tools.ietf.org/html/rfc6902) requires a JSON Patch document to be a JSON documentthat represents an array of objects.
|
||||||
|
json.exception.[parse_error](@ref parse_error).105 | "parse error: operation must have string member 'op'" | An operation of a JSON Patch document must contain Operation objects MUST have exactly one "op" member, whose value indicates the operation to perform. Its value MUST be one of "add", "remove", "replace", "move", "copy", or "test"; other values are errors.
|
||||||
|
json.exception.[parse_error](@ref parse_error).106 | "parse error: array index must not begin with '0'" | An array index in a JSON Pointer ([RFC 6901](https://tools.ietf.org/html/rfc6901)) may be `0` or any number wihtout a leading `0`.
|
||||||
|
json.exception.[parse_error](@ref parse_error).107 | "parse error: JSON pointer must be empty or begin with '/'" | A JSON Pointer must be a Unicode string containing a sequence of zero or more reference tokens, each prefixed by a `/` character.
|
||||||
|
json.exception.[parse_error](@ref parse_error).108 | "parse error: escape character '~' must be followed with '0' or '1'" | In a JSON Pointer, only `~0` and `~1` are valid escape sequences.
|
||||||
|
json.exception.[parse_error](@ref parse_error).109 | "parse error: array index 'one' is not a number" | A JSON Pointer array index must be a number.
|
||||||
|
json.exception.[invalid_iterator](@ref invalid_iterator).201 | "iterators are not compatible" | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid.
|
||||||
|
json.exception.[invalid_iterator](@ref invalid_iterator).202 | "iterator does not fit current value" | In an erase or insert function, the passed iterator @a pos does not belong to the JSON value for which the function was called. It hence does not define a valid position for the deletion/insertion.
|
||||||
|
json.exception.[invalid_iterator](@ref invalid_iterator).203 | "iterators do not fit current value" | Either iterator passed to function @ref erase(IteratorType first, IteratorType last) does not belong to the JSON value from which values shall be erased. It hence does not define a valid range to delete values from.
|
||||||
|
json.exception.[invalid_iterator](@ref invalid_iterator).204 | "iterators out of range" | When an iterator range for a primitive type (number, boolean, or string) is passed to a constructor or an erase function, this range has to be exactly (@ref begin(), @ref end()), because this is the only way the single stored value is expressed. All other ranges are invalid.
|
||||||
|
json.exception.[invalid_iterator](@ref invalid_iterator).205 | "iterator out of range" | When an iterator for a primitive type (number, boolean, or string) is passed to an erase function, the iterator has to be the @ref begin() iterator, because it is the only way to address the stored value. All other iterators are invalid.
|
||||||
|
json.exception.[invalid_iterator](@ref invalid_iterator).206 | "cannot construct with iterators from null" | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) belong to a JSON null value and hence to not define a valid range.
|
||||||
|
json.exception.[invalid_iterator](@ref invalid_iterator).207 | "cannot use key() for non-object iterators" | The key() member function can only be used on iterators belonging to a JSON object, because other types do not have a concept of a key.
|
||||||
|
json.exception.[invalid_iterator](@ref invalid_iterator).208 | "cannot use operator[] for object iterators" | The operator[] to specify a concrete offset cannot be used on iterators belonging to a JSON object, because JSON objects are unordered.
|
||||||
|
json.exception.[invalid_iterator](@ref invalid_iterator).209 | "cannot use offsets with object iterators" | The offset operators (+, -, +=, -=) cannot be used on iterators belonging to a JSON object, because JSON objects are unordered.
|
||||||
|
json.exception.[invalid_iterator](@ref invalid_iterator).210 | "iterators do not fit" | The iterator range passed to the insert function are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid.
|
||||||
|
json.exception.[invalid_iterator](@ref invalid_iterator).211 | "passed iterators may not belong to container" | The iterator range passed to the insert function must not be a subrange of the container to insert to.
|
||||||
|
json.exception.[invalid_iterator](@ref invalid_iterator).212 | "cannot compare iterators of different containers" | When two iterators are compared, they must belong to the same container.
|
||||||
|
json.exception.[invalid_iterator](@ref invalid_iterator).213 | "cannot compare order of object iterators" | The order of object iterators cannot be compated, because JSON objects are unordered.
|
||||||
|
json.exception.[invalid_iterator](@ref invalid_iterator).214 | "cannot get value" | Cannot get value for iterator: Either the iterator belongs to a null value or it is an iterator to a primitive type (number, boolean, or string), but the iterator is different to @ref begin().
|
||||||
|
json.exception.[type_error](@ref type_error).301 | "cannot create object from initializer list" | To create an object from an initializer list, the initializer list must consist only of a list of pairs whose first element is a string. When this constraint is violated, an array is created instead.
|
||||||
|
json.exception.[type_error](@ref type_error).302 | "type must be object, but is array" | During implicit or explicit value conversion, the JSON type must be compatible to the target type. For instance, a JSON string can only be converted into string types, but not into numbers or boolean types.
|
||||||
|
json.exception.[type_error](@ref type_error).303 | "incompatible ReferenceType for get_ref, actual type is object" | To retrieve a reference to a value stored in a @ref basic_json object with @ref get_ref, the type of the reference must match the value type. For instance, for a JSON array, the @a ReferenceType must be @ref array_t&.
|
||||||
|
json.exception.[type_error](@ref type_error).304 | "cannot use at() with string" | The @ref at() member functions can only be executed for certain JSON types.
|
||||||
|
json.exception.[type_error](@ref type_error).305 | "cannot use operator[] with string" | The @ref operator[] member functions can only be executed for certain JSON types.
|
||||||
|
json.exception.[type_error](@ref type_error).306 | "cannot use value() with string" | The @ref value() member functions can only be executed for certain JSON types.
|
||||||
|
json.exception.[type_error](@ref type_error).307 | "cannot use erase() with string" | The @ref erase() member functions can only be executed for certain JSON types.
|
||||||
|
json.exception.[type_error](@ref type_error).308 | "cannot use push_back() with string" | The @ref push_back() and @ref operator+= member functions can only be executed for certain JSON types.
|
||||||
|
json.exception.[type_error](@ref type_error).309 | "cannot use insert() with" | The @ref insert() member functions can only be executed for certain JSON types.
|
||||||
|
json.exception.[type_error](@ref type_error).310 | "cannot use swap() with number" | The @ref swap() member functions can only be executed for certain JSON types.
|
||||||
|
json.exception.[type_error](@ref type_error).313 | "invalid value to unflatten" | The @ref unflatten function converts an object whose keys are JSON Pointers back into an arbitrary nested JSON value. The JSON Pointers must not overlap, because then the resulting value would not be well defined.
|
||||||
|
json.exception.[type_error](@ref type_error).314 | "only objects can be unflattened" | The @ref unflatten function only works for an object whose keys are JSON Pointers.
|
||||||
|
json.exception.[type_error](@ref type_error).315 | "values in object must be primitive" | The @ref unflatten function only works for an object whose keys are JSON Pointers and whose values are primitive.
|
||||||
|
json.exception.[out_of_range](@ref out_of_range).401 | "array index 3 is out of range" | The provided array index @a i is larger than @a size-1.
|
||||||
|
json.exception.[out_of_range](@ref out_of_range).402 | "array index '-' (3) is out of range" | The special array index `-` in a JSON Pointer never describes a valid element of the array, but the index past the end.
|
||||||
|
json.exception.[out_of_range](@ref out_of_range).403 | "key 'foo' not found" | The provided key was not found in the JSON object.
|
||||||
|
json.exception.[out_of_range](@ref out_of_range).404 | "unresolved reference token 'foo'" | A reference token in a JSON Pointer could not be resolved.
|
||||||
|
json.exception.[out_of_range](@ref out_of_range).405 | "JSON pointer has no parent" | The JSON Patch operations 'remove' and 'add' can not be applied to the root element of the JSON value.
|
||||||
|
json.exception.other.500 | "unsuccessful" | A JSON Patch operation 'test' failed.
|
||||||
|
|
||||||
|
@since version 3.0.0
|
||||||
|
*/
|
||||||
|
class exception : public std::exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// create exception with id an explanatory string
|
||||||
|
exception(int id_, const std::string& ename, const std::string& what_arg_)
|
||||||
|
: id(id_),
|
||||||
|
what_arg("[json.exception." + ename + "." + std::to_string(id_) + "] " + what_arg_)
|
||||||
|
{}
|
||||||
|
|
||||||
|
/// returns the explanatory string
|
||||||
|
virtual const char* what() const noexcept
|
||||||
|
{
|
||||||
|
return what_arg.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// the id of the exception
|
||||||
|
const int id;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/// the explanatory string
|
||||||
|
const std::string what_arg;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@brief exception indicating a parse error
|
||||||
|
|
||||||
|
This excpetion is thrown by the library when a parse error occurs. Parse
|
||||||
|
errors can occur during the deserialization of JSON text as well as when
|
||||||
|
using JSON Patch.
|
||||||
|
|
||||||
|
Exceptions have ids 1xx.
|
||||||
|
|
||||||
|
@since version 3.0.0
|
||||||
|
*/
|
||||||
|
class parse_error : public exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/*!
|
||||||
|
@brief create a parse error exception
|
||||||
|
@param[in] id_ the id of the exception
|
||||||
|
@param[in] byte_ the byte index where the error occured (or 0 if
|
||||||
|
the position cannot be determined)
|
||||||
|
@param[in] what_arg_ the explanatory string
|
||||||
|
*/
|
||||||
|
parse_error(int id_, size_t byte_, const std::string& what_arg_)
|
||||||
|
: exception(id_, "parse_error", "parse error" +
|
||||||
|
(byte_ != 0 ? (" at " + std::to_string(byte_)) : "") +
|
||||||
|
": " + what_arg_),
|
||||||
|
byte(byte_)
|
||||||
|
{}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@brief byte index of the parse error
|
||||||
|
|
||||||
|
The byte index of the last read character in the input file.
|
||||||
|
|
||||||
|
@note For an input with n bytes, 1 is the index of the first character
|
||||||
|
and n+1 is the index of the terminating null byte or the end of
|
||||||
|
file.
|
||||||
|
*/
|
||||||
|
const size_t byte;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@brief exception indicating errors with iterators
|
||||||
|
|
||||||
|
Exceptions have ids 2xx.
|
||||||
|
|
||||||
|
@since version 3.0.0
|
||||||
|
*/
|
||||||
|
class invalid_iterator : public exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
invalid_iterator(int id_, const std::string& what_arg_)
|
||||||
|
: exception(id_, "invalid_iterator", what_arg_)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@brief exception indicating executing a member function with a wrong type
|
||||||
|
|
||||||
|
Exceptions have ids 3xx.
|
||||||
|
|
||||||
|
@since version 3.0.0
|
||||||
|
*/
|
||||||
|
class type_error : public exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
type_error(int id_, const std::string& what_arg_)
|
||||||
|
: exception(id_, "type_error", what_arg_)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@brief exception indicating access out of the defined range
|
||||||
|
|
||||||
|
Exceptions have ids 4xx.
|
||||||
|
|
||||||
|
@since version 3.0.0
|
||||||
|
*/
|
||||||
|
class out_of_range : public exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
out_of_range(int id_, const std::string& what_arg_)
|
||||||
|
: exception(id_, "out_of_range", what_arg_)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief returns the allocator associated with the container
|
@brief returns the allocator associated with the container
|
||||||
*/
|
*/
|
||||||
|
@ -6801,6 +6973,9 @@ class basic_json
|
||||||
|
|
||||||
@return result of the deserialization
|
@return result of the deserialization
|
||||||
|
|
||||||
|
@throw parse_error.101 if a parse error occurs; example: `""unexpected end
|
||||||
|
of input; expected string literal""`
|
||||||
|
|
||||||
@complexity Linear in the length of the input. The parser is a predictive
|
@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
|
LL(1) parser. The complexity can be higher if the parser callback function
|
||||||
@a cb has a super-linear complexity.
|
@a cb has a super-linear complexity.
|
||||||
|
@ -9707,17 +9882,17 @@ class basic_json
|
||||||
@return string representation of the code point; the length of the
|
@return string representation of the code point; the length of the
|
||||||
result string is between 1 and 4 characters.
|
result string is between 1 and 4 characters.
|
||||||
|
|
||||||
@throw std::out_of_range if code point is > 0x10ffff; example: `"code
|
@throw parse_error.102 if the low surrogate is invalid; example:
|
||||||
points above 0x10FFFF are invalid"`
|
|
||||||
@throw std::invalid_argument if the low surrogate is invalid; example:
|
|
||||||
`""missing or wrong low surrogate""`
|
`""missing or wrong low surrogate""`
|
||||||
|
@throw parse_error.103 if code point is > 0x10ffff; example: `"code
|
||||||
|
points above 0x10FFFF are invalid"`
|
||||||
|
|
||||||
@complexity Constant.
|
@complexity Constant.
|
||||||
|
|
||||||
@see <http://en.wikipedia.org/wiki/UTF-8#Sample_code>
|
@see <http://en.wikipedia.org/wiki/UTF-8#Sample_code>
|
||||||
*/
|
*/
|
||||||
static string_t to_unicode(const std::size_t codepoint1,
|
string_t to_unicode(const std::size_t codepoint1,
|
||||||
const std::size_t codepoint2 = 0)
|
const std::size_t codepoint2 = 0) const
|
||||||
{
|
{
|
||||||
// calculate the code point from the given code points
|
// calculate the code point from the given code points
|
||||||
std::size_t codepoint = codepoint1;
|
std::size_t codepoint = codepoint1;
|
||||||
|
@ -9740,7 +9915,7 @@ class basic_json
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
JSON_THROW(std::invalid_argument("missing or wrong low surrogate"));
|
JSON_THROW(parse_error(102, get_position(), "missing or wrong low surrogate"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9774,7 +9949,7 @@ class basic_json
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
JSON_THROW(std::out_of_range("code points above 0x10FFFF are invalid"));
|
JSON_THROW(parse_error(103, get_position(), "code points above 0x10FFFF are invalid"));
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -10034,6 +10209,7 @@ basic_json_parser_6:
|
||||||
goto basic_json_parser_6;
|
goto basic_json_parser_6;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
|
position += static_cast<size_t>((m_cursor - m_start));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
basic_json_parser_9:
|
basic_json_parser_9:
|
||||||
|
@ -10889,6 +11065,7 @@ basic_json_parser_74:
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
position += static_cast<size_t>((m_cursor - m_start));
|
||||||
return last_token_type;
|
return last_token_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11044,7 +11221,8 @@ basic_json_parser_74:
|
||||||
|
|
||||||
@return string value of current token without opening and closing
|
@return string value of current token without opening and closing
|
||||||
quotes
|
quotes
|
||||||
@throw std::out_of_range if to_unicode fails
|
@throw parse_error.102 if to_unicode fails
|
||||||
|
@throw parse_error.103 if to_unicode fails
|
||||||
*/
|
*/
|
||||||
string_t get_string() const
|
string_t get_string() const
|
||||||
{
|
{
|
||||||
|
@ -11130,7 +11308,7 @@ basic_json_parser_74:
|
||||||
// make sure there is a subsequent unicode
|
// make sure there is a subsequent unicode
|
||||||
if ((i + 6 >= m_limit) or * (i + 5) != '\\' or * (i + 6) != 'u')
|
if ((i + 6 >= m_limit) or * (i + 5) != '\\' or * (i + 6) != 'u')
|
||||||
{
|
{
|
||||||
JSON_THROW(std::invalid_argument("missing low surrogate"));
|
JSON_THROW(parse_error(102, get_position(), "missing low surrogate"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// get code yyyy from uxxxx\uyyyy
|
// get code yyyy from uxxxx\uyyyy
|
||||||
|
@ -11143,7 +11321,7 @@ basic_json_parser_74:
|
||||||
else if (codepoint >= 0xDC00 and codepoint <= 0xDFFF)
|
else if (codepoint >= 0xDC00 and codepoint <= 0xDFFF)
|
||||||
{
|
{
|
||||||
// we found a lone low surrogate
|
// we found a lone low surrogate
|
||||||
JSON_THROW(std::invalid_argument("missing high surrogate"));
|
JSON_THROW(parse_error(102, get_position(), "missing high surrogate"));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -11398,6 +11576,11 @@ basic_json_parser_74:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constexpr size_t get_position() const
|
||||||
|
{
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// optional input stream
|
/// optional input stream
|
||||||
std::istream* m_stream = nullptr;
|
std::istream* m_stream = nullptr;
|
||||||
|
@ -11417,6 +11600,8 @@ basic_json_parser_74:
|
||||||
const lexer_char_t* m_limit = nullptr;
|
const lexer_char_t* m_limit = nullptr;
|
||||||
/// the last token type
|
/// the last token type
|
||||||
token_type last_token_type = token_type::end_of_input;
|
token_type last_token_type = token_type::end_of_input;
|
||||||
|
/// current position in the input (read bytes)
|
||||||
|
size_t position = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -11678,7 +11863,7 @@ basic_json_parser_74:
|
||||||
"'") :
|
"'") :
|
||||||
lexer::token_type_name(last_token));
|
lexer::token_type_name(last_token));
|
||||||
error_msg += "; expected " + lexer::token_type_name(t);
|
error_msg += "; expected " + lexer::token_type_name(t);
|
||||||
JSON_THROW(std::invalid_argument(error_msg));
|
JSON_THROW(parse_error(101, m_lexer.get_position(), error_msg));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11690,7 +11875,7 @@ basic_json_parser_74:
|
||||||
error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token_string() +
|
error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token_string() +
|
||||||
"'") :
|
"'") :
|
||||||
lexer::token_type_name(last_token));
|
lexer::token_type_name(last_token));
|
||||||
JSON_THROW(std::invalid_argument(error_msg));
|
JSON_THROW(parse_error(101, m_lexer.get_position(), error_msg));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1088,6 +1088,178 @@ class basic_json
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
////////////////
|
||||||
|
// exceptions //
|
||||||
|
////////////////
|
||||||
|
|
||||||
|
/// @name exceptions
|
||||||
|
/// Classes to implement user-defined exceptions.
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@brief general exception of the @ref basic_json class
|
||||||
|
|
||||||
|
Extension of std::exception objects with a member @a id for exception ids.
|
||||||
|
|
||||||
|
name / id | example massage | description
|
||||||
|
------------------------------ | --------------- | -------------------------
|
||||||
|
json.exception.[parse_error](@ref parse_error).101 | `"parse error at 2: unexpected end of input; expected string literal"` | This error indicates a syntax error while deserializing a JSON text. The error message describes that an unexpected token (character) was encountered, and the member @ref parse_error::byte indicates the error position.
|
||||||
|
json.exception.[parse_error](@ref parse_error).102 | `"parse error at 14: missing or wrong low surrogate"` | JSON uses the `\uxxxx` format to describe Unicode characters. Code points above above 0xFFFF are split into two `\uxxxx` entries ("surrogate pairs"). This error indicates that the surrogate pair is incomplete or contains an invalid code point.
|
||||||
|
json.exception.[parse_error](@ref parse_error).103 | `"parse error: code points above 0x10FFFF are invalid"` | Unicode supports code points up to 0x10FFFF. Code points above 0x10FFFF are invalid.
|
||||||
|
json.exception.[parse_error](@ref parse_error).104 | "parse error: JSON patch must be an array of objects" | [RFC 6902](https://tools.ietf.org/html/rfc6902) requires a JSON Patch document to be a JSON documentthat represents an array of objects.
|
||||||
|
json.exception.[parse_error](@ref parse_error).105 | "parse error: operation must have string member 'op'" | An operation of a JSON Patch document must contain Operation objects MUST have exactly one "op" member, whose value indicates the operation to perform. Its value MUST be one of "add", "remove", "replace", "move", "copy", or "test"; other values are errors.
|
||||||
|
json.exception.[parse_error](@ref parse_error).106 | "parse error: array index must not begin with '0'" | An array index in a JSON Pointer ([RFC 6901](https://tools.ietf.org/html/rfc6901)) may be `0` or any number wihtout a leading `0`.
|
||||||
|
json.exception.[parse_error](@ref parse_error).107 | "parse error: JSON pointer must be empty or begin with '/'" | A JSON Pointer must be a Unicode string containing a sequence of zero or more reference tokens, each prefixed by a `/` character.
|
||||||
|
json.exception.[parse_error](@ref parse_error).108 | "parse error: escape character '~' must be followed with '0' or '1'" | In a JSON Pointer, only `~0` and `~1` are valid escape sequences.
|
||||||
|
json.exception.[parse_error](@ref parse_error).109 | "parse error: array index 'one' is not a number" | A JSON Pointer array index must be a number.
|
||||||
|
json.exception.[invalid_iterator](@ref invalid_iterator).201 | "iterators are not compatible" | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid.
|
||||||
|
json.exception.[invalid_iterator](@ref invalid_iterator).202 | "iterator does not fit current value" | In an erase or insert function, the passed iterator @a pos does not belong to the JSON value for which the function was called. It hence does not define a valid position for the deletion/insertion.
|
||||||
|
json.exception.[invalid_iterator](@ref invalid_iterator).203 | "iterators do not fit current value" | Either iterator passed to function @ref erase(IteratorType first, IteratorType last) does not belong to the JSON value from which values shall be erased. It hence does not define a valid range to delete values from.
|
||||||
|
json.exception.[invalid_iterator](@ref invalid_iterator).204 | "iterators out of range" | When an iterator range for a primitive type (number, boolean, or string) is passed to a constructor or an erase function, this range has to be exactly (@ref begin(), @ref end()), because this is the only way the single stored value is expressed. All other ranges are invalid.
|
||||||
|
json.exception.[invalid_iterator](@ref invalid_iterator).205 | "iterator out of range" | When an iterator for a primitive type (number, boolean, or string) is passed to an erase function, the iterator has to be the @ref begin() iterator, because it is the only way to address the stored value. All other iterators are invalid.
|
||||||
|
json.exception.[invalid_iterator](@ref invalid_iterator).206 | "cannot construct with iterators from null" | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) belong to a JSON null value and hence to not define a valid range.
|
||||||
|
json.exception.[invalid_iterator](@ref invalid_iterator).207 | "cannot use key() for non-object iterators" | The key() member function can only be used on iterators belonging to a JSON object, because other types do not have a concept of a key.
|
||||||
|
json.exception.[invalid_iterator](@ref invalid_iterator).208 | "cannot use operator[] for object iterators" | The operator[] to specify a concrete offset cannot be used on iterators belonging to a JSON object, because JSON objects are unordered.
|
||||||
|
json.exception.[invalid_iterator](@ref invalid_iterator).209 | "cannot use offsets with object iterators" | The offset operators (+, -, +=, -=) cannot be used on iterators belonging to a JSON object, because JSON objects are unordered.
|
||||||
|
json.exception.[invalid_iterator](@ref invalid_iterator).210 | "iterators do not fit" | The iterator range passed to the insert function are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid.
|
||||||
|
json.exception.[invalid_iterator](@ref invalid_iterator).211 | "passed iterators may not belong to container" | The iterator range passed to the insert function must not be a subrange of the container to insert to.
|
||||||
|
json.exception.[invalid_iterator](@ref invalid_iterator).212 | "cannot compare iterators of different containers" | When two iterators are compared, they must belong to the same container.
|
||||||
|
json.exception.[invalid_iterator](@ref invalid_iterator).213 | "cannot compare order of object iterators" | The order of object iterators cannot be compated, because JSON objects are unordered.
|
||||||
|
json.exception.[invalid_iterator](@ref invalid_iterator).214 | "cannot get value" | Cannot get value for iterator: Either the iterator belongs to a null value or it is an iterator to a primitive type (number, boolean, or string), but the iterator is different to @ref begin().
|
||||||
|
json.exception.[type_error](@ref type_error).301 | "cannot create object from initializer list" | To create an object from an initializer list, the initializer list must consist only of a list of pairs whose first element is a string. When this constraint is violated, an array is created instead.
|
||||||
|
json.exception.[type_error](@ref type_error).302 | "type must be object, but is array" | During implicit or explicit value conversion, the JSON type must be compatible to the target type. For instance, a JSON string can only be converted into string types, but not into numbers or boolean types.
|
||||||
|
json.exception.[type_error](@ref type_error).303 | "incompatible ReferenceType for get_ref, actual type is object" | To retrieve a reference to a value stored in a @ref basic_json object with @ref get_ref, the type of the reference must match the value type. For instance, for a JSON array, the @a ReferenceType must be @ref array_t&.
|
||||||
|
json.exception.[type_error](@ref type_error).304 | "cannot use at() with string" | The @ref at() member functions can only be executed for certain JSON types.
|
||||||
|
json.exception.[type_error](@ref type_error).305 | "cannot use operator[] with string" | The @ref operator[] member functions can only be executed for certain JSON types.
|
||||||
|
json.exception.[type_error](@ref type_error).306 | "cannot use value() with string" | The @ref value() member functions can only be executed for certain JSON types.
|
||||||
|
json.exception.[type_error](@ref type_error).307 | "cannot use erase() with string" | The @ref erase() member functions can only be executed for certain JSON types.
|
||||||
|
json.exception.[type_error](@ref type_error).308 | "cannot use push_back() with string" | The @ref push_back() and @ref operator+= member functions can only be executed for certain JSON types.
|
||||||
|
json.exception.[type_error](@ref type_error).309 | "cannot use insert() with" | The @ref insert() member functions can only be executed for certain JSON types.
|
||||||
|
json.exception.[type_error](@ref type_error).310 | "cannot use swap() with number" | The @ref swap() member functions can only be executed for certain JSON types.
|
||||||
|
json.exception.[type_error](@ref type_error).313 | "invalid value to unflatten" | The @ref unflatten function converts an object whose keys are JSON Pointers back into an arbitrary nested JSON value. The JSON Pointers must not overlap, because then the resulting value would not be well defined.
|
||||||
|
json.exception.[type_error](@ref type_error).314 | "only objects can be unflattened" | The @ref unflatten function only works for an object whose keys are JSON Pointers.
|
||||||
|
json.exception.[type_error](@ref type_error).315 | "values in object must be primitive" | The @ref unflatten function only works for an object whose keys are JSON Pointers and whose values are primitive.
|
||||||
|
json.exception.[out_of_range](@ref out_of_range).401 | "array index 3 is out of range" | The provided array index @a i is larger than @a size-1.
|
||||||
|
json.exception.[out_of_range](@ref out_of_range).402 | "array index '-' (3) is out of range" | The special array index `-` in a JSON Pointer never describes a valid element of the array, but the index past the end.
|
||||||
|
json.exception.[out_of_range](@ref out_of_range).403 | "key 'foo' not found" | The provided key was not found in the JSON object.
|
||||||
|
json.exception.[out_of_range](@ref out_of_range).404 | "unresolved reference token 'foo'" | A reference token in a JSON Pointer could not be resolved.
|
||||||
|
json.exception.[out_of_range](@ref out_of_range).405 | "JSON pointer has no parent" | The JSON Patch operations 'remove' and 'add' can not be applied to the root element of the JSON value.
|
||||||
|
json.exception.other.500 | "unsuccessful" | A JSON Patch operation 'test' failed.
|
||||||
|
|
||||||
|
@since version 3.0.0
|
||||||
|
*/
|
||||||
|
class exception : public std::exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// create exception with id an explanatory string
|
||||||
|
exception(int id_, const std::string& ename, const std::string& what_arg_)
|
||||||
|
: id(id_),
|
||||||
|
what_arg("[json.exception." + ename + "." + std::to_string(id_) + "] " + what_arg_)
|
||||||
|
{}
|
||||||
|
|
||||||
|
/// returns the explanatory string
|
||||||
|
virtual const char* what() const noexcept
|
||||||
|
{
|
||||||
|
return what_arg.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// the id of the exception
|
||||||
|
const int id;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/// the explanatory string
|
||||||
|
const std::string what_arg;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@brief exception indicating a parse error
|
||||||
|
|
||||||
|
This excpetion is thrown by the library when a parse error occurs. Parse
|
||||||
|
errors can occur during the deserialization of JSON text as well as when
|
||||||
|
using JSON Patch.
|
||||||
|
|
||||||
|
Exceptions have ids 1xx.
|
||||||
|
|
||||||
|
@since version 3.0.0
|
||||||
|
*/
|
||||||
|
class parse_error : public exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/*!
|
||||||
|
@brief create a parse error exception
|
||||||
|
@param[in] id_ the id of the exception
|
||||||
|
@param[in] byte_ the byte index where the error occured (or 0 if
|
||||||
|
the position cannot be determined)
|
||||||
|
@param[in] what_arg_ the explanatory string
|
||||||
|
*/
|
||||||
|
parse_error(int id_, size_t byte_, const std::string& what_arg_)
|
||||||
|
: exception(id_, "parse_error", "parse error" +
|
||||||
|
(byte_ != 0 ? (" at " + std::to_string(byte_)) : "") +
|
||||||
|
": " + what_arg_),
|
||||||
|
byte(byte_)
|
||||||
|
{}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@brief byte index of the parse error
|
||||||
|
|
||||||
|
The byte index of the last read character in the input file.
|
||||||
|
|
||||||
|
@note For an input with n bytes, 1 is the index of the first character
|
||||||
|
and n+1 is the index of the terminating null byte or the end of
|
||||||
|
file.
|
||||||
|
*/
|
||||||
|
const size_t byte;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@brief exception indicating errors with iterators
|
||||||
|
|
||||||
|
Exceptions have ids 2xx.
|
||||||
|
|
||||||
|
@since version 3.0.0
|
||||||
|
*/
|
||||||
|
class invalid_iterator : public exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
invalid_iterator(int id_, const std::string& what_arg_)
|
||||||
|
: exception(id_, "invalid_iterator", what_arg_)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@brief exception indicating executing a member function with a wrong type
|
||||||
|
|
||||||
|
Exceptions have ids 3xx.
|
||||||
|
|
||||||
|
@since version 3.0.0
|
||||||
|
*/
|
||||||
|
class type_error : public exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
type_error(int id_, const std::string& what_arg_)
|
||||||
|
: exception(id_, "type_error", what_arg_)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@brief exception indicating access out of the defined range
|
||||||
|
|
||||||
|
Exceptions have ids 4xx.
|
||||||
|
|
||||||
|
@since version 3.0.0
|
||||||
|
*/
|
||||||
|
class out_of_range : public exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
out_of_range(int id_, const std::string& what_arg_)
|
||||||
|
: exception(id_, "out_of_range", what_arg_)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief returns the allocator associated with the container
|
@brief returns the allocator associated with the container
|
||||||
*/
|
*/
|
||||||
|
@ -6801,6 +6973,9 @@ class basic_json
|
||||||
|
|
||||||
@return result of the deserialization
|
@return result of the deserialization
|
||||||
|
|
||||||
|
@throw parse_error.101 if a parse error occurs; example: `""unexpected end
|
||||||
|
of input; expected string literal""`
|
||||||
|
|
||||||
@complexity Linear in the length of the input. The parser is a predictive
|
@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
|
LL(1) parser. The complexity can be higher if the parser callback function
|
||||||
@a cb has a super-linear complexity.
|
@a cb has a super-linear complexity.
|
||||||
|
@ -9707,17 +9882,17 @@ class basic_json
|
||||||
@return string representation of the code point; the length of the
|
@return string representation of the code point; the length of the
|
||||||
result string is between 1 and 4 characters.
|
result string is between 1 and 4 characters.
|
||||||
|
|
||||||
@throw std::out_of_range if code point is > 0x10ffff; example: `"code
|
@throw parse_error.102 if the low surrogate is invalid; example:
|
||||||
points above 0x10FFFF are invalid"`
|
|
||||||
@throw std::invalid_argument if the low surrogate is invalid; example:
|
|
||||||
`""missing or wrong low surrogate""`
|
`""missing or wrong low surrogate""`
|
||||||
|
@throw parse_error.103 if code point is > 0x10ffff; example: `"code
|
||||||
|
points above 0x10FFFF are invalid"`
|
||||||
|
|
||||||
@complexity Constant.
|
@complexity Constant.
|
||||||
|
|
||||||
@see <http://en.wikipedia.org/wiki/UTF-8#Sample_code>
|
@see <http://en.wikipedia.org/wiki/UTF-8#Sample_code>
|
||||||
*/
|
*/
|
||||||
static string_t to_unicode(const std::size_t codepoint1,
|
string_t to_unicode(const std::size_t codepoint1,
|
||||||
const std::size_t codepoint2 = 0)
|
const std::size_t codepoint2 = 0) const
|
||||||
{
|
{
|
||||||
// calculate the code point from the given code points
|
// calculate the code point from the given code points
|
||||||
std::size_t codepoint = codepoint1;
|
std::size_t codepoint = codepoint1;
|
||||||
|
@ -9740,7 +9915,7 @@ class basic_json
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
JSON_THROW(std::invalid_argument("missing or wrong low surrogate"));
|
JSON_THROW(parse_error(102, get_position(), "missing or wrong low surrogate"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9774,7 +9949,7 @@ class basic_json
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
JSON_THROW(std::out_of_range("code points above 0x10FFFF are invalid"));
|
JSON_THROW(parse_error(103, get_position(), "code points above 0x10FFFF are invalid"));
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -9869,7 +10044,7 @@ class basic_json
|
||||||
|
|
||||||
// ignore whitespace
|
// ignore whitespace
|
||||||
ws = [ \t\n\r]+;
|
ws = [ \t\n\r]+;
|
||||||
ws { continue; }
|
ws { position += static_cast<size_t>((m_cursor - m_start)); continue; }
|
||||||
|
|
||||||
// structural characters
|
// structural characters
|
||||||
"[" { last_token_type = token_type::begin_array; break; }
|
"[" { last_token_type = token_type::begin_array; break; }
|
||||||
|
@ -9923,6 +10098,7 @@ class basic_json
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
position += static_cast<size_t>((m_cursor - m_start));
|
||||||
return last_token_type;
|
return last_token_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10078,7 +10254,8 @@ class basic_json
|
||||||
|
|
||||||
@return string value of current token without opening and closing
|
@return string value of current token without opening and closing
|
||||||
quotes
|
quotes
|
||||||
@throw std::out_of_range if to_unicode fails
|
@throw parse_error.102 if to_unicode fails
|
||||||
|
@throw parse_error.103 if to_unicode fails
|
||||||
*/
|
*/
|
||||||
string_t get_string() const
|
string_t get_string() const
|
||||||
{
|
{
|
||||||
|
@ -10164,7 +10341,7 @@ class basic_json
|
||||||
// make sure there is a subsequent unicode
|
// make sure there is a subsequent unicode
|
||||||
if ((i + 6 >= m_limit) or * (i + 5) != '\\' or * (i + 6) != 'u')
|
if ((i + 6 >= m_limit) or * (i + 5) != '\\' or * (i + 6) != 'u')
|
||||||
{
|
{
|
||||||
JSON_THROW(std::invalid_argument("missing low surrogate"));
|
JSON_THROW(parse_error(102, get_position(), "missing low surrogate"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// get code yyyy from uxxxx\uyyyy
|
// get code yyyy from uxxxx\uyyyy
|
||||||
|
@ -10177,7 +10354,7 @@ class basic_json
|
||||||
else if (codepoint >= 0xDC00 and codepoint <= 0xDFFF)
|
else if (codepoint >= 0xDC00 and codepoint <= 0xDFFF)
|
||||||
{
|
{
|
||||||
// we found a lone low surrogate
|
// we found a lone low surrogate
|
||||||
JSON_THROW(std::invalid_argument("missing high surrogate"));
|
JSON_THROW(parse_error(102, get_position(), "missing high surrogate"));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -10432,6 +10609,11 @@ class basic_json
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constexpr size_t get_position() const
|
||||||
|
{
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// optional input stream
|
/// optional input stream
|
||||||
std::istream* m_stream = nullptr;
|
std::istream* m_stream = nullptr;
|
||||||
|
@ -10451,6 +10633,8 @@ class basic_json
|
||||||
const lexer_char_t* m_limit = nullptr;
|
const lexer_char_t* m_limit = nullptr;
|
||||||
/// the last token type
|
/// the last token type
|
||||||
token_type last_token_type = token_type::end_of_input;
|
token_type last_token_type = token_type::end_of_input;
|
||||||
|
/// current position in the input (read bytes)
|
||||||
|
size_t position = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -10712,7 +10896,7 @@ class basic_json
|
||||||
"'") :
|
"'") :
|
||||||
lexer::token_type_name(last_token));
|
lexer::token_type_name(last_token));
|
||||||
error_msg += "; expected " + lexer::token_type_name(t);
|
error_msg += "; expected " + lexer::token_type_name(t);
|
||||||
JSON_THROW(std::invalid_argument(error_msg));
|
JSON_THROW(parse_error(101, m_lexer.get_position(), error_msg));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10724,7 +10908,7 @@ class basic_json
|
||||||
error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token_string() +
|
error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token_string() +
|
||||||
"'") :
|
"'") :
|
||||||
lexer::token_type_name(last_token));
|
lexer::token_type_name(last_token));
|
||||||
JSON_THROW(std::invalid_argument(error_msg));
|
JSON_THROW(parse_error(101, m_lexer.get_position(), error_msg));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -190,8 +190,10 @@ TEST_CASE("lexer class")
|
||||||
|
|
||||||
SECTION("to_unicode")
|
SECTION("to_unicode")
|
||||||
{
|
{
|
||||||
CHECK(json::lexer::to_unicode(0x1F4A9) == "💩");
|
// lexer to call to_unicode on
|
||||||
CHECK_THROWS_AS(json::lexer::to_unicode(0x200000), std::out_of_range);
|
json::lexer dummy_lexer(reinterpret_cast<const json::lexer::lexer_char_t*>(""), 0);
|
||||||
CHECK_THROWS_WITH(json::lexer::to_unicode(0x200000), "code points above 0x10FFFF are invalid");
|
CHECK(dummy_lexer.to_unicode(0x1F4A9) == "💩");
|
||||||
|
CHECK_THROWS_AS(dummy_lexer.to_unicode(0x200000), json::parse_error);
|
||||||
|
CHECK_THROWS_WITH(dummy_lexer.to_unicode(0x200000), "[json.exception.parse_error.103] parse error: code points above 0x10FFFF are invalid");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,52 +89,56 @@ TEST_CASE("parser class")
|
||||||
SECTION("errors")
|
SECTION("errors")
|
||||||
{
|
{
|
||||||
// error: tab in string
|
// error: tab in string
|
||||||
CHECK_THROWS_AS(json::parser("\"\t\"").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("\"\t\"").parse(), json::parse_error);
|
||||||
CHECK_THROWS_WITH(json::parser("\"\t\"").parse(), "parse error - unexpected '\"'");
|
CHECK_THROWS_WITH(json::parser("\"\t\"").parse(),
|
||||||
|
"[json.exception.parse_error.101] parse error at 1: parse error - unexpected '\"'");
|
||||||
// error: newline in string
|
// error: newline in string
|
||||||
CHECK_THROWS_AS(json::parser("\"\n\"").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("\"\n\"").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("\"\r\"").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("\"\r\"").parse(), json::parse_error);
|
||||||
CHECK_THROWS_WITH(json::parser("\"\n\"").parse(), "parse error - unexpected '\"'");
|
CHECK_THROWS_WITH(json::parser("\"\n\"").parse(),
|
||||||
CHECK_THROWS_WITH(json::parser("\"\r\"").parse(), "parse error - unexpected '\"'");
|
"[json.exception.parse_error.101] parse error at 1: parse error - unexpected '\"'");
|
||||||
|
CHECK_THROWS_WITH(json::parser("\"\r\"").parse(),
|
||||||
|
"[json.exception.parse_error.101] parse error at 1: parse error - unexpected '\"'");
|
||||||
// error: backspace in string
|
// error: backspace in string
|
||||||
CHECK_THROWS_AS(json::parser("\"\b\"").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("\"\b\"").parse(), json::parse_error);
|
||||||
CHECK_THROWS_WITH(json::parser("\"\b\"").parse(), "parse error - unexpected '\"'");
|
CHECK_THROWS_WITH(json::parser("\"\b\"").parse(),
|
||||||
|
"[json.exception.parse_error.101] parse error at 1: parse error - unexpected '\"'");
|
||||||
// improve code coverage
|
// improve code coverage
|
||||||
CHECK_THROWS_AS(json::parser("\uFF01").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("\uFF01").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("[-4:1,]").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("[-4:1,]").parse(), json::parse_error);
|
||||||
// unescaped control characters
|
// unescaped control characters
|
||||||
CHECK_THROWS_AS(json::parser("\"\x00\"").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("\"\x00\"").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("\"\x01\"").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("\"\x01\"").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("\"\x02\"").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("\"\x02\"").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("\"\x03\"").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("\"\x03\"").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("\"\x04\"").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("\"\x04\"").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("\"\x05\"").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("\"\x05\"").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("\"\x06\"").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("\"\x06\"").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("\"\x07\"").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("\"\x07\"").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("\"\x08\"").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("\"\x08\"").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("\"\x09\"").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("\"\x09\"").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("\"\x0a\"").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("\"\x0a\"").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("\"\x0b\"").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("\"\x0b\"").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("\"\x0c\"").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("\"\x0c\"").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("\"\x0d\"").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("\"\x0d\"").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("\"\x0e\"").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("\"\x0e\"").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("\"\x0f\"").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("\"\x0f\"").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("\"\x10\"").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("\"\x10\"").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("\"\x11\"").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("\"\x11\"").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("\"\x12\"").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("\"\x12\"").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("\"\x13\"").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("\"\x13\"").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("\"\x14\"").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("\"\x14\"").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("\"\x15\"").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("\"\x15\"").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("\"\x16\"").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("\"\x16\"").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("\"\x17\"").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("\"\x17\"").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("\"\x18\"").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("\"\x18\"").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("\"\x19\"").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("\"\x19\"").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("\"\x1a\"").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("\"\x1a\"").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("\"\x1b\"").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("\"\x1b\"").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("\"\x1c\"").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("\"\x1c\"").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("\"\x1d\"").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("\"\x1d\"").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("\"\x1e\"").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("\"\x1e\"").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("\"\x1f\"").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("\"\x1f\"").parse(), json::parse_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("escaped")
|
SECTION("escaped")
|
||||||
|
@ -277,60 +281,61 @@ TEST_CASE("parser class")
|
||||||
|
|
||||||
SECTION("invalid numbers")
|
SECTION("invalid numbers")
|
||||||
{
|
{
|
||||||
CHECK_THROWS_AS(json::parser("01").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("01").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("--1").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("--1").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("1.").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("1.").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("1E").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("1E").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("1E-").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("1E-").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("1.E1").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("1.E1").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("-1E").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("-1E").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("-0E#").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("-0E#").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("-0E-#").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("-0E-#").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("-0#").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("-0#").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("-0.0:").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("-0.0:").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("-0.0Z").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("-0.0Z").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("-0E123:").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("-0E123:").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("-0e0-:").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("-0e0-:").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("-0e-:").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("-0e-:").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("-0f").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("-0f").parse(), json::parse_error);
|
||||||
|
|
||||||
// numbers must not begin with "+"
|
// numbers must not begin with "+"
|
||||||
CHECK_THROWS_AS(json::parser("+1").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("+1").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("+0").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("+0").parse(), json::parse_error);
|
||||||
|
|
||||||
CHECK_THROWS_WITH(json::parser("01").parse(),
|
CHECK_THROWS_WITH(json::parser("01").parse(),
|
||||||
"parse error - unexpected '01'");
|
"[json.exception.parse_error.101] parse error at 2: parse error - unexpected '01'");
|
||||||
CHECK_THROWS_WITH(json::parser("-01").parse(),
|
CHECK_THROWS_WITH(json::parser("-01").parse(),
|
||||||
"parse error - unexpected '-01'");
|
"[json.exception.parse_error.101] parse error at 3: parse error - unexpected '-01'");
|
||||||
CHECK_THROWS_WITH(json::parser("--1").parse(), "parse error - unexpected '-'");
|
CHECK_THROWS_WITH(json::parser("--1").parse(),
|
||||||
|
"[json.exception.parse_error.101] parse error at 1: parse error - unexpected '-'");
|
||||||
CHECK_THROWS_WITH(json::parser("1.").parse(),
|
CHECK_THROWS_WITH(json::parser("1.").parse(),
|
||||||
"parse error - unexpected '.'; expected end of input");
|
"[json.exception.parse_error.101] parse error at 2: parse error - unexpected '.'; expected end of input");
|
||||||
CHECK_THROWS_WITH(json::parser("1E").parse(),
|
CHECK_THROWS_WITH(json::parser("1E").parse(),
|
||||||
"parse error - unexpected 'E'; expected end of input");
|
"[json.exception.parse_error.101] parse error at 2: parse error - unexpected 'E'; expected end of input");
|
||||||
CHECK_THROWS_WITH(json::parser("1E-").parse(),
|
CHECK_THROWS_WITH(json::parser("1E-").parse(),
|
||||||
"parse error - unexpected 'E'; expected end of input");
|
"[json.exception.parse_error.101] parse error at 2: parse error - unexpected 'E'; expected end of input");
|
||||||
CHECK_THROWS_WITH(json::parser("1.E1").parse(),
|
CHECK_THROWS_WITH(json::parser("1.E1").parse(),
|
||||||
"parse error - unexpected '.'; expected end of input");
|
"[json.exception.parse_error.101] parse error at 2: parse error - unexpected '.'; expected end of input");
|
||||||
CHECK_THROWS_WITH(json::parser("-1E").parse(),
|
CHECK_THROWS_WITH(json::parser("-1E").parse(),
|
||||||
"parse error - unexpected 'E'; expected end of input");
|
"[json.exception.parse_error.101] parse error at 3: parse error - unexpected 'E'; expected end of input");
|
||||||
CHECK_THROWS_WITH(json::parser("-0E#").parse(),
|
CHECK_THROWS_WITH(json::parser("-0E#").parse(),
|
||||||
"parse error - unexpected 'E'; expected end of input");
|
"[json.exception.parse_error.101] parse error at 3: parse error - unexpected 'E'; expected end of input");
|
||||||
CHECK_THROWS_WITH(json::parser("-0E-#").parse(),
|
CHECK_THROWS_WITH(json::parser("-0E-#").parse(),
|
||||||
"parse error - unexpected 'E'; expected end of input");
|
"[json.exception.parse_error.101] parse error at 3: parse error - unexpected 'E'; expected end of input");
|
||||||
CHECK_THROWS_WITH(json::parser("-0#").parse(),
|
CHECK_THROWS_WITH(json::parser("-0#").parse(),
|
||||||
"parse error - unexpected '#'; expected end of input");
|
"[json.exception.parse_error.101] parse error at 3: parse error - unexpected '#'; expected end of input");
|
||||||
CHECK_THROWS_WITH(json::parser("-0.0:").parse(),
|
CHECK_THROWS_WITH(json::parser("-0.0:").parse(),
|
||||||
"parse error - unexpected ':'; expected end of input");
|
"[json.exception.parse_error.101] parse error at 5: parse error - unexpected ':'; expected end of input");
|
||||||
CHECK_THROWS_WITH(json::parser("-0.0Z").parse(),
|
CHECK_THROWS_WITH(json::parser("-0.0Z").parse(),
|
||||||
"parse error - unexpected 'Z'; expected end of input");
|
"[json.exception.parse_error.101] parse error at 5: parse error - unexpected 'Z'; expected end of input");
|
||||||
CHECK_THROWS_WITH(json::parser("-0E123:").parse(),
|
CHECK_THROWS_WITH(json::parser("-0E123:").parse(),
|
||||||
"parse error - unexpected ':'; expected end of input");
|
"[json.exception.parse_error.101] parse error at 7: parse error - unexpected ':'; expected end of input");
|
||||||
CHECK_THROWS_WITH(json::parser("-0e0-:").parse(),
|
CHECK_THROWS_WITH(json::parser("-0e0-:").parse(),
|
||||||
"parse error - unexpected '-'; expected end of input");
|
"[json.exception.parse_error.101] parse error at 5: parse error - unexpected '-'; expected end of input");
|
||||||
CHECK_THROWS_WITH(json::parser("-0e-:").parse(),
|
CHECK_THROWS_WITH(json::parser("-0e-:").parse(),
|
||||||
"parse error - unexpected 'e'; expected end of input");
|
"[json.exception.parse_error.101] parse error at 3: parse error - unexpected 'e'; expected end of input");
|
||||||
CHECK_THROWS_WITH(json::parser("-0f").parse(),
|
CHECK_THROWS_WITH(json::parser("-0f").parse(),
|
||||||
"parse error - unexpected 'f'; expected end of input");
|
"[json.exception.parse_error.101] parse error at 3: parse error - unexpected 'f'; expected end of input");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -338,147 +343,150 @@ TEST_CASE("parser class")
|
||||||
SECTION("parse errors")
|
SECTION("parse errors")
|
||||||
{
|
{
|
||||||
// unexpected end of number
|
// unexpected end of number
|
||||||
CHECK_THROWS_AS(json::parser("0.").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("0.").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("-").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("-").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("--").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("--").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("-0.").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("-0.").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("-.").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("-.").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("-:").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("-:").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("0.:").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("0.:").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("e.").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("e.").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("1e.").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("1e.").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("1e/").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("1e/").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("1e:").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("1e:").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("1E.").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("1E.").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("1E/").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("1E/").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("1E:").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("1E:").parse(), json::parse_error);
|
||||||
CHECK_THROWS_WITH(json::parser("0.").parse(),
|
CHECK_THROWS_WITH(json::parser("0.").parse(),
|
||||||
"parse error - unexpected '.'; expected end of input");
|
"[json.exception.parse_error.101] parse error at 2: parse error - unexpected '.'; expected end of input");
|
||||||
CHECK_THROWS_WITH(json::parser("-").parse(), "parse error - unexpected '-'");
|
CHECK_THROWS_WITH(json::parser("-").parse(),
|
||||||
|
"[json.exception.parse_error.101] parse error at 1: parse error - unexpected '-'");
|
||||||
CHECK_THROWS_WITH(json::parser("--").parse(),
|
CHECK_THROWS_WITH(json::parser("--").parse(),
|
||||||
"parse error - unexpected '-'");
|
"[json.exception.parse_error.101] parse error at 1: parse error - unexpected '-'");
|
||||||
CHECK_THROWS_WITH(json::parser("-0.").parse(),
|
CHECK_THROWS_WITH(json::parser("-0.").parse(),
|
||||||
"parse error - unexpected '.'; expected end of input");
|
"[json.exception.parse_error.101] parse error at 3: parse error - unexpected '.'; expected end of input");
|
||||||
CHECK_THROWS_WITH(json::parser("-.").parse(),
|
CHECK_THROWS_WITH(json::parser("-.").parse(),
|
||||||
"parse error - unexpected '-'");
|
"[json.exception.parse_error.101] parse error at 1: parse error - unexpected '-'");
|
||||||
CHECK_THROWS_WITH(json::parser("-:").parse(),
|
CHECK_THROWS_WITH(json::parser("-:").parse(),
|
||||||
"parse error - unexpected '-'");
|
"[json.exception.parse_error.101] parse error at 1: parse error - unexpected '-'");
|
||||||
CHECK_THROWS_WITH(json::parser("0.:").parse(),
|
CHECK_THROWS_WITH(json::parser("0.:").parse(),
|
||||||
"parse error - unexpected '.'; expected end of input");
|
"[json.exception.parse_error.101] parse error at 2: parse error - unexpected '.'; expected end of input");
|
||||||
CHECK_THROWS_WITH(json::parser("e.").parse(),
|
CHECK_THROWS_WITH(json::parser("e.").parse(),
|
||||||
"parse error - unexpected 'e'");
|
"[json.exception.parse_error.101] parse error at 1: parse error - unexpected 'e'");
|
||||||
CHECK_THROWS_WITH(json::parser("1e.").parse(),
|
CHECK_THROWS_WITH(json::parser("1e.").parse(),
|
||||||
"parse error - unexpected 'e'; expected end of input");
|
"[json.exception.parse_error.101] parse error at 2: parse error - unexpected 'e'; expected end of input");
|
||||||
CHECK_THROWS_WITH(json::parser("1e/").parse(),
|
CHECK_THROWS_WITH(json::parser("1e/").parse(),
|
||||||
"parse error - unexpected 'e'; expected end of input");
|
"[json.exception.parse_error.101] parse error at 2: parse error - unexpected 'e'; expected end of input");
|
||||||
CHECK_THROWS_WITH(json::parser("1e:").parse(),
|
CHECK_THROWS_WITH(json::parser("1e:").parse(),
|
||||||
"parse error - unexpected 'e'; expected end of input");
|
"[json.exception.parse_error.101] parse error at 2: parse error - unexpected 'e'; expected end of input");
|
||||||
CHECK_THROWS_WITH(json::parser("1E.").parse(),
|
CHECK_THROWS_WITH(json::parser("1E.").parse(),
|
||||||
"parse error - unexpected 'E'; expected end of input");
|
"[json.exception.parse_error.101] parse error at 2: parse error - unexpected 'E'; expected end of input");
|
||||||
CHECK_THROWS_WITH(json::parser("1E/").parse(),
|
CHECK_THROWS_WITH(json::parser("1E/").parse(),
|
||||||
"parse error - unexpected 'E'; expected end of input");
|
"[json.exception.parse_error.101] parse error at 2: parse error - unexpected 'E'; expected end of input");
|
||||||
CHECK_THROWS_WITH(json::parser("1E:").parse(),
|
CHECK_THROWS_WITH(json::parser("1E:").parse(),
|
||||||
"parse error - unexpected 'E'; expected end of input");
|
"[json.exception.parse_error.101] parse error at 2: parse error - unexpected 'E'; expected end of input");
|
||||||
|
|
||||||
// unexpected end of null
|
// unexpected end of null
|
||||||
CHECK_THROWS_AS(json::parser("n").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("n").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("nu").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("nu").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("nul").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("nul").parse(), json::parse_error);
|
||||||
CHECK_THROWS_WITH(json::parser("n").parse(), "parse error - unexpected 'n'");
|
CHECK_THROWS_WITH(json::parser("n").parse(), "[json.exception.parse_error.101] parse error at 1: parse error - unexpected 'n'");
|
||||||
CHECK_THROWS_WITH(json::parser("nu").parse(),
|
CHECK_THROWS_WITH(json::parser("nu").parse(),
|
||||||
"parse error - unexpected 'n'");
|
"[json.exception.parse_error.101] parse error at 1: parse error - unexpected 'n'");
|
||||||
CHECK_THROWS_WITH(json::parser("nul").parse(),
|
CHECK_THROWS_WITH(json::parser("nul").parse(),
|
||||||
"parse error - unexpected 'n'");
|
"[json.exception.parse_error.101] parse error at 1: parse error - unexpected 'n'");
|
||||||
|
|
||||||
// unexpected end of true
|
// unexpected end of true
|
||||||
CHECK_THROWS_AS(json::parser("t").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("t").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("tr").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("tr").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("tru").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("tru").parse(), json::parse_error);
|
||||||
CHECK_THROWS_WITH(json::parser("t").parse(), "parse error - unexpected 't'");
|
CHECK_THROWS_WITH(json::parser("t").parse(), "[json.exception.parse_error.101] parse error at 1: parse error - unexpected 't'");
|
||||||
CHECK_THROWS_WITH(json::parser("tr").parse(),
|
CHECK_THROWS_WITH(json::parser("tr").parse(),
|
||||||
"parse error - unexpected 't'");
|
"[json.exception.parse_error.101] parse error at 1: parse error - unexpected 't'");
|
||||||
CHECK_THROWS_WITH(json::parser("tru").parse(),
|
CHECK_THROWS_WITH(json::parser("tru").parse(),
|
||||||
"parse error - unexpected 't'");
|
"[json.exception.parse_error.101] parse error at 1: parse error - unexpected 't'");
|
||||||
|
|
||||||
// unexpected end of false
|
// unexpected end of false
|
||||||
CHECK_THROWS_AS(json::parser("f").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("f").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("fa").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("fa").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("fal").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("fal").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("fals").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("fals").parse(), json::parse_error);
|
||||||
CHECK_THROWS_WITH(json::parser("f").parse(), "parse error - unexpected 'f'");
|
CHECK_THROWS_WITH(json::parser("f").parse(), "[json.exception.parse_error.101] parse error at 1: parse error - unexpected 'f'");
|
||||||
CHECK_THROWS_WITH(json::parser("fa").parse(),
|
CHECK_THROWS_WITH(json::parser("fa").parse(),
|
||||||
"parse error - unexpected 'f'");
|
"[json.exception.parse_error.101] parse error at 1: parse error - unexpected 'f'");
|
||||||
CHECK_THROWS_WITH(json::parser("fal").parse(),
|
CHECK_THROWS_WITH(json::parser("fal").parse(),
|
||||||
"parse error - unexpected 'f'");
|
"[json.exception.parse_error.101] parse error at 1: parse error - unexpected 'f'");
|
||||||
CHECK_THROWS_WITH(json::parser("fals").parse(),
|
CHECK_THROWS_WITH(json::parser("fals").parse(),
|
||||||
"parse error - unexpected 'f'");
|
"[json.exception.parse_error.101] parse error at 1: parse error - unexpected 'f'");
|
||||||
|
|
||||||
// missing/unexpected end of array
|
// missing/unexpected end of array
|
||||||
CHECK_THROWS_AS(json::parser("[").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("[").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("[1").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("[1").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("[1,").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("[1,").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("[1,]").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("[1,]").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("]").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("]").parse(), json::parse_error);
|
||||||
CHECK_THROWS_WITH(json::parser("[").parse(),
|
CHECK_THROWS_WITH(json::parser("[").parse(),
|
||||||
"parse error - unexpected end of input");
|
"[json.exception.parse_error.101] parse error at 2: parse error - unexpected end of input");
|
||||||
CHECK_THROWS_WITH(json::parser("[1").parse(),
|
CHECK_THROWS_WITH(json::parser("[1").parse(),
|
||||||
"parse error - unexpected end of input; expected ']'");
|
"[json.exception.parse_error.101] parse error at 3: parse error - unexpected end of input; expected ']'");
|
||||||
CHECK_THROWS_WITH(json::parser("[1,").parse(),
|
CHECK_THROWS_WITH(json::parser("[1,").parse(),
|
||||||
"parse error - unexpected end of input");
|
"[json.exception.parse_error.101] parse error at 4: parse error - unexpected end of input");
|
||||||
CHECK_THROWS_WITH(json::parser("[1,]").parse(),
|
CHECK_THROWS_WITH(json::parser("[1,]").parse(),
|
||||||
"parse error - unexpected ']'");
|
"[json.exception.parse_error.101] parse error at 4: parse error - unexpected ']'");
|
||||||
CHECK_THROWS_WITH(json::parser("]").parse(), "parse error - unexpected ']'");
|
CHECK_THROWS_WITH(json::parser("]").parse(),
|
||||||
|
"[json.exception.parse_error.101] parse error at 1: parse error - unexpected ']'");
|
||||||
|
|
||||||
// missing/unexpected end of object
|
// missing/unexpected end of object
|
||||||
CHECK_THROWS_AS(json::parser("{").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("{").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("{\"foo\"").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("{\"foo\"").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("{\"foo\":").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("{\"foo\":").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("{\"foo\":}").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("{\"foo\":}").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("{\"foo\":1,}").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("{\"foo\":1,}").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("}").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("}").parse(), json::parse_error);
|
||||||
CHECK_THROWS_WITH(json::parser("{").parse(),
|
CHECK_THROWS_WITH(json::parser("{").parse(),
|
||||||
"parse error - unexpected end of input; expected string literal");
|
"[json.exception.parse_error.101] parse error at 2: parse error - unexpected end of input; expected string literal");
|
||||||
CHECK_THROWS_WITH(json::parser("{\"foo\"").parse(),
|
CHECK_THROWS_WITH(json::parser("{\"foo\"").parse(),
|
||||||
"parse error - unexpected end of input; expected ':'");
|
"[json.exception.parse_error.101] parse error at 7: parse error - unexpected end of input; expected ':'");
|
||||||
CHECK_THROWS_WITH(json::parser("{\"foo\":").parse(),
|
CHECK_THROWS_WITH(json::parser("{\"foo\":").parse(),
|
||||||
"parse error - unexpected end of input");
|
"[json.exception.parse_error.101] parse error at 8: parse error - unexpected end of input");
|
||||||
CHECK_THROWS_WITH(json::parser("{\"foo\":}").parse(),
|
CHECK_THROWS_WITH(json::parser("{\"foo\":}").parse(),
|
||||||
"parse error - unexpected '}'");
|
"[json.exception.parse_error.101] parse error at 8: parse error - unexpected '}'");
|
||||||
CHECK_THROWS_WITH(json::parser("{\"foo\":1,}").parse(),
|
CHECK_THROWS_WITH(json::parser("{\"foo\":1,}").parse(),
|
||||||
"parse error - unexpected '}'; expected string literal");
|
"[json.exception.parse_error.101] parse error at 10: parse error - unexpected '}'; expected string literal");
|
||||||
CHECK_THROWS_WITH(json::parser("}").parse(), "parse error - unexpected '}'");
|
CHECK_THROWS_WITH(json::parser("}").parse(),
|
||||||
|
"[json.exception.parse_error.101] parse error at 1: parse error - unexpected '}'");
|
||||||
|
|
||||||
// missing/unexpected end of string
|
// missing/unexpected end of string
|
||||||
CHECK_THROWS_AS(json::parser("\"").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("\"").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("\"\\\"").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("\"\\\"").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("\"\\u\"").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("\"\\u\"").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("\"\\u0\"").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("\"\\u0\"").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("\"\\u01\"").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("\"\\u01\"").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("\"\\u012\"").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("\"\\u012\"").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("\"\\u").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("\"\\u").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("\"\\u0").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("\"\\u0").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("\"\\u01").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("\"\\u01").parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser("\"\\u012").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("\"\\u012").parse(), json::parse_error);
|
||||||
CHECK_THROWS_WITH(json::parser("\"").parse(),
|
CHECK_THROWS_WITH(json::parser("\"").parse(),
|
||||||
"parse error - unexpected '\"'");
|
"[json.exception.parse_error.101] parse error at 1: parse error - unexpected '\"'");
|
||||||
CHECK_THROWS_WITH(json::parser("\"\\\"").parse(),
|
CHECK_THROWS_WITH(json::parser("\"\\\"").parse(),
|
||||||
"parse error - unexpected '\"'");
|
"[json.exception.parse_error.101] parse error at 1: parse error - unexpected '\"'");
|
||||||
CHECK_THROWS_WITH(json::parser("\"\\u\"").parse(),
|
CHECK_THROWS_WITH(json::parser("\"\\u\"").parse(),
|
||||||
"parse error - unexpected '\"'");
|
"[json.exception.parse_error.101] parse error at 1: parse error - unexpected '\"'");
|
||||||
CHECK_THROWS_WITH(json::parser("\"\\u0\"").parse(),
|
CHECK_THROWS_WITH(json::parser("\"\\u0\"").parse(),
|
||||||
"parse error - unexpected '\"'");
|
"[json.exception.parse_error.101] parse error at 1: parse error - unexpected '\"'");
|
||||||
CHECK_THROWS_WITH(json::parser("\"\\u01\"").parse(),
|
CHECK_THROWS_WITH(json::parser("\"\\u01\"").parse(),
|
||||||
"parse error - unexpected '\"'");
|
"[json.exception.parse_error.101] parse error at 1: parse error - unexpected '\"'");
|
||||||
CHECK_THROWS_WITH(json::parser("\"\\u012\"").parse(),
|
CHECK_THROWS_WITH(json::parser("\"\\u012\"").parse(),
|
||||||
"parse error - unexpected '\"'");
|
"[json.exception.parse_error.101] parse error at 1: parse error - unexpected '\"'");
|
||||||
CHECK_THROWS_WITH(json::parser("\"\\u").parse(),
|
CHECK_THROWS_WITH(json::parser("\"\\u").parse(),
|
||||||
"parse error - unexpected '\"'");
|
"[json.exception.parse_error.101] parse error at 1: parse error - unexpected '\"'");
|
||||||
CHECK_THROWS_WITH(json::parser("\"\\u0").parse(),
|
CHECK_THROWS_WITH(json::parser("\"\\u0").parse(),
|
||||||
"parse error - unexpected '\"'");
|
"[json.exception.parse_error.101] parse error at 1: parse error - unexpected '\"'");
|
||||||
CHECK_THROWS_WITH(json::parser("\"\\u01").parse(),
|
CHECK_THROWS_WITH(json::parser("\"\\u01").parse(),
|
||||||
"parse error - unexpected '\"'");
|
"[json.exception.parse_error.101] parse error at 1: parse error - unexpected '\"'");
|
||||||
CHECK_THROWS_WITH(json::parser("\"\\u012").parse(),
|
CHECK_THROWS_WITH(json::parser("\"\\u012").parse(),
|
||||||
"parse error - unexpected '\"'");
|
"[json.exception.parse_error.101] parse error at 1: parse error - unexpected '\"'");
|
||||||
|
|
||||||
// invalid escapes
|
// invalid escapes
|
||||||
for (int c = 1; c < 128; ++c)
|
for (int c = 1; c < 128; ++c)
|
||||||
|
@ -510,8 +518,9 @@ TEST_CASE("parser class")
|
||||||
// any other combination of backslash and character is invalid
|
// any other combination of backslash and character is invalid
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
CHECK_THROWS_AS(json::parser(s.c_str()).parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser(s.c_str()).parse(), json::parse_error);
|
||||||
CHECK_THROWS_WITH(json::parser(s.c_str()).parse(), "parse error - unexpected '\"'");
|
CHECK_THROWS_WITH(json::parser(s.c_str()).parse(),
|
||||||
|
"[json.exception.parse_error.101] parse error at 1: parse error - unexpected '\"'");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -576,40 +585,49 @@ TEST_CASE("parser class")
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CHECK_THROWS_AS(json::parser(s1.c_str()).parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser(s1.c_str()).parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser(s2.c_str()).parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser(s2.c_str()).parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser(s3.c_str()).parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser(s3.c_str()).parse(), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parser(s4.c_str()).parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser(s4.c_str()).parse(), json::parse_error);
|
||||||
|
|
||||||
CHECK_THROWS_WITH(json::parser(s1.c_str()).parse(), "parse error - unexpected '\"'");
|
CHECK_THROWS_WITH(json::parser(s1.c_str()).parse(),
|
||||||
CHECK_THROWS_WITH(json::parser(s2.c_str()).parse(), "parse error - unexpected '\"'");
|
"[json.exception.parse_error.101] parse error at 1: parse error - unexpected '\"'");
|
||||||
CHECK_THROWS_WITH(json::parser(s3.c_str()).parse(), "parse error - unexpected '\"'");
|
CHECK_THROWS_WITH(json::parser(s2.c_str()).parse(),
|
||||||
CHECK_THROWS_WITH(json::parser(s4.c_str()).parse(), "parse error - unexpected '\"'");
|
"[json.exception.parse_error.101] parse error at 1: parse error - unexpected '\"'");
|
||||||
|
CHECK_THROWS_WITH(json::parser(s3.c_str()).parse(),
|
||||||
|
"[json.exception.parse_error.101] parse error at 1: parse error - unexpected '\"'");
|
||||||
|
CHECK_THROWS_WITH(json::parser(s4.c_str()).parse(),
|
||||||
|
"[json.exception.parse_error.101] parse error at 1: parse error - unexpected '\"'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// missing part of a surrogate pair
|
// missing part of a surrogate pair
|
||||||
CHECK_THROWS_AS(json::parse("\"\\uD80C\""), std::invalid_argument);
|
CHECK_THROWS_AS(json::parse("\"\\uD80C\""), json::parse_error);
|
||||||
CHECK_THROWS_WITH(json::parse("\"\\uD80C\""), "missing low surrogate");
|
CHECK_THROWS_WITH(json::parse("\"\\uD80C\""),
|
||||||
|
"[json.exception.parse_error.102] parse error at 8: missing low surrogate");
|
||||||
// invalid surrogate pair
|
// invalid surrogate pair
|
||||||
CHECK_THROWS_AS(json::parse("\"\\uD80C\\uD80C\""), std::invalid_argument);
|
CHECK_THROWS_AS(json::parse("\"\\uD80C\\uD80C\""), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parse("\"\\uD80C\\u0000\""), std::invalid_argument);
|
CHECK_THROWS_AS(json::parse("\"\\uD80C\\u0000\""), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parse("\"\\uD80C\\uFFFF\""), std::invalid_argument);
|
CHECK_THROWS_AS(json::parse("\"\\uD80C\\uFFFF\""), json::parse_error);
|
||||||
CHECK_THROWS_WITH(json::parse("\"\\uD80C\\uD80C\""),
|
CHECK_THROWS_WITH(json::parse("\"\\uD80C\\uD80C\""),
|
||||||
"missing or wrong low surrogate");
|
"[json.exception.parse_error.102] parse error at 14: missing or wrong low surrogate");
|
||||||
CHECK_THROWS_WITH(json::parse("\"\\uD80C\\u0000\""),
|
CHECK_THROWS_WITH(json::parse("\"\\uD80C\\u0000\""),
|
||||||
"missing or wrong low surrogate");
|
"[json.exception.parse_error.102] parse error at 14: missing or wrong low surrogate");
|
||||||
CHECK_THROWS_WITH(json::parse("\"\\uD80C\\uFFFF\""),
|
CHECK_THROWS_WITH(json::parse("\"\\uD80C\\uFFFF\""),
|
||||||
"missing or wrong low surrogate");
|
"[json.exception.parse_error.102] parse error at 14: missing or wrong low surrogate");
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("tests found by mutate++")
|
SECTION("tests found by mutate++")
|
||||||
{
|
{
|
||||||
// test case to make sure no comma preceeds the first key
|
// test case to make sure no comma preceeds the first key
|
||||||
CHECK_THROWS_AS(json::parser("{,\"key\": false}").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("{,\"key\": false}").parse(), json::parse_error);
|
||||||
|
CHECK_THROWS_WITH(json::parser("{,\"key\": false}").parse(),
|
||||||
|
"[json.exception.parse_error.101] parse error at 2: parse error - unexpected ','");
|
||||||
// test case to make sure an object is properly closed
|
// test case to make sure an object is properly closed
|
||||||
CHECK_THROWS_AS(json::parser("[{\"key\": false true]").parse(), std::invalid_argument);
|
CHECK_THROWS_AS(json::parser("[{\"key\": false true]").parse(), json::parse_error);
|
||||||
|
CHECK_THROWS_WITH(json::parser("[{\"key\": false true]").parse(),
|
||||||
|
"[json.exception.parse_error.101] parse error at 19: parse error - unexpected true literal; expected '}'");
|
||||||
|
|
||||||
// test case to make sure the callback is properly evaluated after reading a key
|
// test case to make sure the callback is properly evaluated after reading a key
|
||||||
{
|
{
|
||||||
|
|
|
@ -90,15 +90,17 @@ TEST_CASE("deserialization")
|
||||||
std::stringstream ss1, ss2;
|
std::stringstream ss1, ss2;
|
||||||
ss1 << "[\"foo\",1,2,3,false,{\"one\":1}";
|
ss1 << "[\"foo\",1,2,3,false,{\"one\":1}";
|
||||||
ss2 << "[\"foo\",1,2,3,false,{\"one\":1}";
|
ss2 << "[\"foo\",1,2,3,false,{\"one\":1}";
|
||||||
CHECK_THROWS_AS(json::parse(ss1), std::invalid_argument);
|
CHECK_THROWS_AS(json::parse(ss1), json::parse_error);
|
||||||
CHECK_THROWS_WITH(json::parse(ss2), "parse error - unexpected end of input; expected ']'");
|
CHECK_THROWS_WITH(json::parse(ss2),
|
||||||
|
"[json.exception.parse_error.101] parse error at 30: parse error - unexpected end of input; expected ']'");
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("string")
|
SECTION("string")
|
||||||
{
|
{
|
||||||
json::string_t s = "[\"foo\",1,2,3,false,{\"one\":1}";
|
json::string_t s = "[\"foo\",1,2,3,false,{\"one\":1}";
|
||||||
CHECK_THROWS_AS(json::parse(s), std::invalid_argument);
|
CHECK_THROWS_AS(json::parse(s), json::parse_error);
|
||||||
CHECK_THROWS_WITH(json::parse(s), "parse error - unexpected end of input; expected ']'");
|
CHECK_THROWS_WITH(json::parse(s),
|
||||||
|
"[json.exception.parse_error.101] parse error at 29: parse error - unexpected end of input; expected ']'");
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("operator<<")
|
SECTION("operator<<")
|
||||||
|
@ -107,8 +109,9 @@ TEST_CASE("deserialization")
|
||||||
ss1 << "[\"foo\",1,2,3,false,{\"one\":1}";
|
ss1 << "[\"foo\",1,2,3,false,{\"one\":1}";
|
||||||
ss2 << "[\"foo\",1,2,3,false,{\"one\":1}";
|
ss2 << "[\"foo\",1,2,3,false,{\"one\":1}";
|
||||||
json j;
|
json j;
|
||||||
CHECK_THROWS_AS(j << ss1, std::invalid_argument);
|
CHECK_THROWS_AS(j << ss1, json::parse_error);
|
||||||
CHECK_THROWS_WITH(j << ss2, "parse error - unexpected end of input; expected ']'");
|
CHECK_THROWS_WITH(j << ss2,
|
||||||
|
"[json.exception.parse_error.101] parse error at 30: parse error - unexpected end of input; expected ']'");
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("operator>>")
|
SECTION("operator>>")
|
||||||
|
@ -117,15 +120,16 @@ TEST_CASE("deserialization")
|
||||||
ss1 << "[\"foo\",1,2,3,false,{\"one\":1}";
|
ss1 << "[\"foo\",1,2,3,false,{\"one\":1}";
|
||||||
ss2 << "[\"foo\",1,2,3,false,{\"one\":1}";
|
ss2 << "[\"foo\",1,2,3,false,{\"one\":1}";
|
||||||
json j;
|
json j;
|
||||||
CHECK_THROWS_AS(ss1 >> j, std::invalid_argument);
|
CHECK_THROWS_AS(ss1 >> j, json::parse_error);
|
||||||
CHECK_THROWS_WITH(ss2 >> j, "parse error - unexpected end of input; expected ']'");
|
CHECK_THROWS_WITH(ss2 >> j,
|
||||||
|
"[json.exception.parse_error.101] parse error at 30: parse error - unexpected end of input; expected ']'");
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("user-defined string literal")
|
SECTION("user-defined string literal")
|
||||||
{
|
{
|
||||||
CHECK_THROWS_AS("[\"foo\",1,2,3,false,{\"one\":1}"_json, std::invalid_argument);
|
CHECK_THROWS_AS("[\"foo\",1,2,3,false,{\"one\":1}"_json, json::parse_error);
|
||||||
CHECK_THROWS_WITH("[\"foo\",1,2,3,false,{\"one\":1}"_json,
|
CHECK_THROWS_WITH("[\"foo\",1,2,3,false,{\"one\":1}"_json,
|
||||||
"parse error - unexpected end of input; expected ']'");
|
"[json.exception.parse_error.101] parse error at 29: parse error - unexpected end of input; expected ']'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,7 +182,7 @@ TEST_CASE("deserialization")
|
||||||
SECTION("empty container")
|
SECTION("empty container")
|
||||||
{
|
{
|
||||||
std::vector<uint8_t> v;
|
std::vector<uint8_t> v;
|
||||||
CHECK_THROWS_AS(json::parse(v), std::invalid_argument);
|
CHECK_THROWS_AS(json::parse(v), json::parse_error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,7 +227,7 @@ TEST_CASE("deserialization")
|
||||||
SECTION("with empty range")
|
SECTION("with empty range")
|
||||||
{
|
{
|
||||||
std::vector<uint8_t> v;
|
std::vector<uint8_t> v;
|
||||||
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), std::invalid_argument);
|
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,91 +237,91 @@ TEST_CASE("deserialization")
|
||||||
SECTION("case 1")
|
SECTION("case 1")
|
||||||
{
|
{
|
||||||
uint8_t v[] = {'\"', 'a', 'a', 'a', 'a', 'a', 'a', '\\', 'u'};
|
uint8_t v[] = {'\"', 'a', 'a', 'a', 'a', 'a', 'a', '\\', 'u'};
|
||||||
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), std::invalid_argument);
|
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("case 2")
|
SECTION("case 2")
|
||||||
{
|
{
|
||||||
uint8_t v[] = {'\"', 'a', 'a', 'a', 'a', 'a', 'a', '\\', 'u', '1'};
|
uint8_t v[] = {'\"', 'a', 'a', 'a', 'a', 'a', 'a', '\\', 'u', '1'};
|
||||||
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), std::invalid_argument);
|
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("case 3")
|
SECTION("case 3")
|
||||||
{
|
{
|
||||||
uint8_t v[] = {'\"', 'a', 'a', 'a', 'a', 'a', 'a', '\\', 'u', '1', '1', '1', '1', '1', '1', '1', '1'};
|
uint8_t v[] = {'\"', 'a', 'a', 'a', 'a', 'a', 'a', '\\', 'u', '1', '1', '1', '1', '1', '1', '1', '1'};
|
||||||
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), std::invalid_argument);
|
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("case 4")
|
SECTION("case 4")
|
||||||
{
|
{
|
||||||
uint8_t v[] = {'\"', 'a', 'a', 'a', 'a', 'a', 'a', 'u', '1', '1', '1', '1', '1', '1', '1', '1', '\\'};
|
uint8_t v[] = {'\"', 'a', 'a', 'a', 'a', 'a', 'a', 'u', '1', '1', '1', '1', '1', '1', '1', '1', '\\'};
|
||||||
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), std::invalid_argument);
|
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("case 5")
|
SECTION("case 5")
|
||||||
{
|
{
|
||||||
uint8_t v[] = {'\"', 0x7F, 0xC1};
|
uint8_t v[] = {'\"', 0x7F, 0xC1};
|
||||||
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), std::invalid_argument);
|
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("case 6")
|
SECTION("case 6")
|
||||||
{
|
{
|
||||||
uint8_t v[] = {'\"', 0x7F, 0xDF, 0x7F};
|
uint8_t v[] = {'\"', 0x7F, 0xDF, 0x7F};
|
||||||
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), std::invalid_argument);
|
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("case 7")
|
SECTION("case 7")
|
||||||
{
|
{
|
||||||
uint8_t v[] = {'\"', 0x7F, 0xDF, 0xC0};
|
uint8_t v[] = {'\"', 0x7F, 0xDF, 0xC0};
|
||||||
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), std::invalid_argument);
|
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("case 8")
|
SECTION("case 8")
|
||||||
{
|
{
|
||||||
uint8_t v[] = {'\"', 0x7F, 0xE0, 0x9F};
|
uint8_t v[] = {'\"', 0x7F, 0xE0, 0x9F};
|
||||||
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), std::invalid_argument);
|
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("case 9")
|
SECTION("case 9")
|
||||||
{
|
{
|
||||||
uint8_t v[] = {'\"', 0x7F, 0xEF, 0xC0};
|
uint8_t v[] = {'\"', 0x7F, 0xEF, 0xC0};
|
||||||
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), std::invalid_argument);
|
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("case 10")
|
SECTION("case 10")
|
||||||
{
|
{
|
||||||
uint8_t v[] = {'\"', 0x7F, 0xED, 0x7F};
|
uint8_t v[] = {'\"', 0x7F, 0xED, 0x7F};
|
||||||
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), std::invalid_argument);
|
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("case 11")
|
SECTION("case 11")
|
||||||
{
|
{
|
||||||
uint8_t v[] = {'\"', 0x7F, 0xF0, 0x8F};
|
uint8_t v[] = {'\"', 0x7F, 0xF0, 0x8F};
|
||||||
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), std::invalid_argument);
|
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("case 12")
|
SECTION("case 12")
|
||||||
{
|
{
|
||||||
uint8_t v[] = {'\"', 0x7F, 0xF0, 0xC0};
|
uint8_t v[] = {'\"', 0x7F, 0xF0, 0xC0};
|
||||||
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), std::invalid_argument);
|
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("case 13")
|
SECTION("case 13")
|
||||||
{
|
{
|
||||||
uint8_t v[] = {'\"', 0x7F, 0xF3, 0x7F};
|
uint8_t v[] = {'\"', 0x7F, 0xF3, 0x7F};
|
||||||
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), std::invalid_argument);
|
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("case 14")
|
SECTION("case 14")
|
||||||
{
|
{
|
||||||
uint8_t v[] = {'\"', 0x7F, 0xF3, 0xC0};
|
uint8_t v[] = {'\"', 0x7F, 0xF3, 0xC0};
|
||||||
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), std::invalid_argument);
|
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("case 15")
|
SECTION("case 15")
|
||||||
{
|
{
|
||||||
uint8_t v[] = {'\"', 0x7F, 0xF4, 0x7F};
|
uint8_t v[] = {'\"', 0x7F, 0xF4, 0x7F};
|
||||||
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), std::invalid_argument);
|
CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -579,8 +579,9 @@ TEST_CASE("regression tests")
|
||||||
// ss is not at EOF; this yielded an error before the fix
|
// ss is not at EOF; this yielded an error before the fix
|
||||||
// (threw basic_string::append). No, it should just throw
|
// (threw basic_string::append). No, it should just throw
|
||||||
// a parse error because of the EOF.
|
// a parse error because of the EOF.
|
||||||
CHECK_THROWS_AS(j << ss, std::invalid_argument);
|
CHECK_THROWS_AS(j << ss, json::parse_error);
|
||||||
CHECK_THROWS_WITH(j << ss, "parse error - unexpected end of input");
|
CHECK_THROWS_WITH(j << ss,
|
||||||
|
"[json.exception.parse_error.101] parse error at 1: parse error - unexpected end of input");
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("issue #389 - Integer-overflow (OSS-Fuzz issue 267)")
|
SECTION("issue #389 - Integer-overflow (OSS-Fuzz issue 267)")
|
||||||
|
@ -778,7 +779,7 @@ TEST_CASE("regression tests")
|
||||||
SECTION("issue #452 - Heap-buffer-overflow (OSS-Fuzz issue 585)")
|
SECTION("issue #452 - Heap-buffer-overflow (OSS-Fuzz issue 585)")
|
||||||
{
|
{
|
||||||
std::vector<uint8_t> vec = {'-', '0', '1', '2', '2', '7', '4'};
|
std::vector<uint8_t> vec = {'-', '0', '1', '2', '2', '7', '4'};
|
||||||
CHECK_THROWS_AS(json::parse(vec), std::invalid_argument);
|
CHECK_THROWS_AS(json::parse(vec), json::parse_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("issue #454 - doubles are printed as integers")
|
SECTION("issue #454 - doubles are printed as integers")
|
||||||
|
|
|
@ -79,7 +79,7 @@ TEST_CASE("compliance tests from json.org")
|
||||||
CAPTURE(filename);
|
CAPTURE(filename);
|
||||||
json j;
|
json j;
|
||||||
std::ifstream f(filename);
|
std::ifstream f(filename);
|
||||||
CHECK_THROWS_AS(j << f, std::invalid_argument);
|
CHECK_THROWS_AS(j << f, json::parse_error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -757,7 +757,7 @@ TEST_CASE("nst's JSONTestSuite")
|
||||||
CAPTURE(filename);
|
CAPTURE(filename);
|
||||||
std::ifstream f(filename);
|
std::ifstream f(filename);
|
||||||
json j;
|
json j;
|
||||||
CHECK_THROWS_AS(j << f, std::invalid_argument);
|
CHECK_THROWS_AS(j << f, json::parse_error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -810,7 +810,7 @@ TEST_CASE("nst's JSONTestSuite")
|
||||||
CAPTURE(filename);
|
CAPTURE(filename);
|
||||||
std::ifstream f(filename);
|
std::ifstream f(filename);
|
||||||
json j;
|
json j;
|
||||||
CHECK_THROWS_AS(j << f, std::invalid_argument);
|
CHECK_THROWS_AS(j << f, json::parse_error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,9 @@ TEST_CASE("Unicode", "[hide]")
|
||||||
{
|
{
|
||||||
SECTION("full enumeration of Unicode code points")
|
SECTION("full enumeration of Unicode code points")
|
||||||
{
|
{
|
||||||
|
// lexer to call to_unicode on
|
||||||
|
json::lexer dummy_lexer(reinterpret_cast<const json::lexer::lexer_char_t*>(""), 0);
|
||||||
|
|
||||||
// create an escaped string from a code point
|
// create an escaped string from a code point
|
||||||
const auto codepoint_to_unicode = [](std::size_t cp)
|
const auto codepoint_to_unicode = [](std::size_t cp)
|
||||||
{
|
{
|
||||||
|
@ -85,7 +88,7 @@ TEST_CASE("Unicode", "[hide]")
|
||||||
// they are checked with codepoint_to_unicode.
|
// they are checked with codepoint_to_unicode.
|
||||||
if (cp > 0x1f and cp != 0x22 and cp != 0x5c)
|
if (cp > 0x1f and cp != 0x22 and cp != 0x5c)
|
||||||
{
|
{
|
||||||
unescaped_string = json::lexer::to_unicode(cp);
|
unescaped_string = dummy_lexer.to_unicode(cp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -97,7 +100,7 @@ TEST_CASE("Unicode", "[hide]")
|
||||||
const auto codepoint2 = 0xdc00u + ((cp - 0x10000u) & 0x3ffu);
|
const auto codepoint2 = 0xdc00u + ((cp - 0x10000u) & 0x3ffu);
|
||||||
escaped_string = codepoint_to_unicode(codepoint1);
|
escaped_string = codepoint_to_unicode(codepoint1);
|
||||||
escaped_string += codepoint_to_unicode(codepoint2);
|
escaped_string += codepoint_to_unicode(codepoint2);
|
||||||
unescaped_string += json::lexer::to_unicode(codepoint1, codepoint2);
|
unescaped_string += dummy_lexer.to_unicode(codepoint1, codepoint2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// all other code points are valid and must not yield parse errors
|
// all other code points are valid and must not yield parse errors
|
||||||
|
@ -170,7 +173,7 @@ TEST_CASE("Unicode", "[hide]")
|
||||||
|
|
||||||
SECTION("error for incomplete/wrong BOM")
|
SECTION("error for incomplete/wrong BOM")
|
||||||
{
|
{
|
||||||
CHECK_THROWS_AS(json::parse("\xef\xbb"), std::invalid_argument);
|
CHECK_THROWS_AS(json::parse("\xef\xbb"), json::parse_error);
|
||||||
CHECK_THROWS_AS(json::parse("\xef\xbb\xbb"), std::invalid_argument);
|
CHECK_THROWS_AS(json::parse("\xef\xbb\xbb"), json::parse_error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue