diff --git a/Makefile b/Makefile index bfb62349..135db65a 100644 --- a/Makefile +++ b/Makefile @@ -12,6 +12,7 @@ SRCS = include/nlohmann/json.hpp \ include/nlohmann/detail/input/json_sax.hpp \ include/nlohmann/detail/input/lexer.hpp \ include/nlohmann/detail/input/parser.hpp \ + include/nlohmann/detail/input/position_t.hpp \ include/nlohmann/detail/iterators/internal_iterator.hpp \ include/nlohmann/detail/iterators/iter_impl.hpp \ include/nlohmann/detail/iterators/iteration_proxy.hpp \ diff --git a/doc/examples/json_pointer.output b/doc/examples/json_pointer.output index 33e2cc68..9e027d6d 100644 --- a/doc/examples/json_pointer.output +++ b/doc/examples/json_pointer.output @@ -1,3 +1,3 @@ -[json.exception.parse_error.107] parse error at 1: JSON pointer must be empty or begin with '/' - was: 'foo' +[json.exception.parse_error.107] parse error at byte 1: JSON pointer must be empty or begin with '/' - was: 'foo' [json.exception.parse_error.108] parse error: escape character '~' must be followed with '0' or '1' [json.exception.parse_error.108] parse error: escape character '~' must be followed with '0' or '1' diff --git a/doc/examples/parse_error.output b/doc/examples/parse_error.output index 96ab5bb5..fe366ff8 100644 --- a/doc/examples/parse_error.output +++ b/doc/examples/parse_error.output @@ -1,3 +1,3 @@ -message: [json.exception.parse_error.101] parse error at 8: syntax error - unexpected ']'; expected '[', '{', or a literal +message: [json.exception.parse_error.101] parse error at line 1, column 8: syntax error while parsing value - unexpected ']'; expected '[', '{', or a literal exception id: 101 byte position of error: 8 diff --git a/include/nlohmann/detail/exceptions.hpp b/include/nlohmann/detail/exceptions.hpp index d3d4c224..dd046804 100644 --- a/include/nlohmann/detail/exceptions.hpp +++ b/include/nlohmann/detail/exceptions.hpp @@ -4,6 +4,8 @@ #include // runtime_error #include // to_string +#include + namespace nlohmann { namespace detail @@ -114,15 +116,23 @@ class parse_error : public exception /*! @brief create a parse error exception @param[in] id_ the id of the exception - @param[in] byte_ the byte index where the error occurred (or 0 if the - position cannot be determined) + @param[in] position the position where the error occurred (or with + chars_read_total=0 if the position cannot be + determined) @param[in] what_arg the explanatory string @return parse_error object */ + static parse_error create(int id_, const position_t& pos, const std::string& what_arg) + { + std::string w = exception::name("parse_error", id_) + "parse error" + + position_string(pos) + ": " + what_arg; + return parse_error(id_, pos.chars_read_total, w.c_str()); + } + static parse_error create(int id_, std::size_t byte_, const std::string& what_arg) { std::string w = exception::name("parse_error", id_) + "parse error" + - (byte_ != 0 ? (" at " + std::to_string(byte_)) : "") + + (byte_ != 0 ? (" at byte " + std::to_string(byte_)) : "") + ": " + what_arg; return parse_error(id_, byte_, w.c_str()); } @@ -141,6 +151,12 @@ class parse_error : public exception private: parse_error(int id_, std::size_t byte_, const char* what_arg) : exception(id_, what_arg), byte(byte_) {} + + static std::string position_string(const position_t& pos) + { + return " at line " + std::to_string(pos.lines_read + 1) + + ", column " + std::to_string(pos.chars_read_current_line); + } }; /*! diff --git a/include/nlohmann/detail/input/json_sax.hpp b/include/nlohmann/detail/input/json_sax.hpp index ca2ce30a..153f75d2 100644 --- a/include/nlohmann/detail/input/json_sax.hpp +++ b/include/nlohmann/detail/input/json_sax.hpp @@ -113,7 +113,7 @@ struct json_sax @brief a parse error occurred @param[in] position the position in the input where the error occurs @param[in] last_token the last read token - @param[in] error_msg a detailed error message + @param[in] ex an exception object describing the error @return whether parsing should proceed (must return false) */ virtual bool parse_error(std::size_t position, diff --git a/include/nlohmann/detail/input/lexer.hpp b/include/nlohmann/detail/input/lexer.hpp index 362b4f23..dd474525 100644 --- a/include/nlohmann/detail/input/lexer.hpp +++ b/include/nlohmann/detail/input/lexer.hpp @@ -10,6 +10,7 @@ #include #include +#include namespace nlohmann { @@ -396,39 +397,194 @@ class lexer // invalid control characters case 0x00: + { + error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000"; + return token_type::parse_error; + } + case 0x01: + { + error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001"; + return token_type::parse_error; + } + case 0x02: + { + error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002"; + return token_type::parse_error; + } + case 0x03: + { + error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003"; + return token_type::parse_error; + } + case 0x04: + { + error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004"; + return token_type::parse_error; + } + case 0x05: + { + error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005"; + return token_type::parse_error; + } + case 0x06: + { + error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006"; + return token_type::parse_error; + } + case 0x07: + { + error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007"; + return token_type::parse_error; + } + case 0x08: + { + error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b"; + return token_type::parse_error; + } + case 0x09: + { + error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t"; + return token_type::parse_error; + } + case 0x0A: + { + error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n"; + return token_type::parse_error; + } + case 0x0B: + { + error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B"; + return token_type::parse_error; + } + case 0x0C: + { + error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f"; + return token_type::parse_error; + } + case 0x0D: + { + error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r"; + return token_type::parse_error; + } + case 0x0E: + { + error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E"; + return token_type::parse_error; + } + case 0x0F: + { + error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F"; + return token_type::parse_error; + } + case 0x10: + { + error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010"; + return token_type::parse_error; + } + case 0x11: + { + error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011"; + return token_type::parse_error; + } + case 0x12: + { + error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012"; + return token_type::parse_error; + } + case 0x13: + { + error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013"; + return token_type::parse_error; + } + case 0x14: + { + error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014"; + return token_type::parse_error; + } + case 0x15: + { + error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015"; + return token_type::parse_error; + } + case 0x16: + { + error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016"; + return token_type::parse_error; + } + case 0x17: + { + error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017"; + return token_type::parse_error; + } + case 0x18: + { + error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018"; + return token_type::parse_error; + } + case 0x19: + { + error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019"; + return token_type::parse_error; + } + case 0x1A: + { + error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A"; + return token_type::parse_error; + } + case 0x1B: + { + error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B"; + return token_type::parse_error; + } + case 0x1C: + { + error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C"; + return token_type::parse_error; + } + case 0x1D: + { + error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D"; + return token_type::parse_error; + } + case 0x1E: + { + error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E"; + return token_type::parse_error; + } + case 0x1F: { - error_message = "invalid string: control character must be escaped"; + error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F"; return token_type::parse_error; } @@ -1085,7 +1241,9 @@ scan_number_done: */ std::char_traits::int_type get() { - ++chars_read; + ++position.chars_read_total; + ++position.chars_read_current_line; + if (next_unget) { // just reset the next_unget variable and work with current @@ -1100,6 +1258,13 @@ scan_number_done: { token_string.push_back(std::char_traits::to_char_type(current)); } + + if (current == '\n') + { + ++position.lines_read; + ++position.chars_read_current_line = 0; + } + return current; } @@ -1107,14 +1272,29 @@ scan_number_done: @brief unget current character (read it again on next get) We implement unget by setting variable next_unget to true. The input is not - changed - we just simulate ungetting by modifying chars_read and - token_string. The next call to get() will behave as if the unget character - is read again. + changed - we just simulate ungetting by modifying chars_read_total, + chars_read_current_line, and token_string. The next call to get() will + behave as if the unget character is read again. */ void unget() { next_unget = true; - --chars_read; + + --position.chars_read_total; + + // in case we "unget" a newline, we have to also decrement the lines_read + if (position.chars_read_current_line == 0) + { + if (position.lines_read > 0) + { + --position.lines_read; + } + } + else + { + --position.chars_read_current_line; + } + if (JSON_LIKELY(current != std::char_traits::eof())) { assert(token_string.size() != 0); @@ -1162,9 +1342,9 @@ scan_number_done: ///////////////////// /// return position of last read token - constexpr std::size_t get_position() const noexcept + constexpr position_t get_position() const noexcept { - return chars_read; + return position; } /// return the last read token (for errors only). Will never contain EOF @@ -1224,7 +1404,7 @@ scan_number_done: token_type scan() { // initially, skip the BOM - if (chars_read == 0 and not skip_bom()) + if (position.chars_read_total == 0 and not skip_bom()) { error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given"; return token_type::parse_error; @@ -1302,8 +1482,8 @@ scan_number_done: /// whether the next get() call should just return current bool next_unget = false; - /// the number of characters read - std::size_t chars_read = 0; + /// the start position of the current token + position_t position; /// raw input token string (for error messages) std::vector token_string {}; diff --git a/include/nlohmann/detail/input/parser.hpp b/include/nlohmann/detail/input/parser.hpp index c354a7b5..ac19bb8c 100644 --- a/include/nlohmann/detail/input/parser.hpp +++ b/include/nlohmann/detail/input/parser.hpp @@ -91,7 +91,8 @@ class parser { sdp.parse_error(m_lexer.get_position(), m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input))); + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::end_of_input, "value"))); } // in case of an error, return discarded value @@ -119,7 +120,8 @@ class parser { sdp.parse_error(m_lexer.get_position(), m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input))); + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::end_of_input, "value"))); } // in case of an error, return discarded value @@ -154,7 +156,8 @@ class parser { return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input))); + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::end_of_input, "value"))); } return result; @@ -199,7 +202,8 @@ class parser { return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string))); + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::value_string, "object key"))); } if (JSON_UNLIKELY(not sax->key(m_lexer.get_string()))) { @@ -211,7 +215,8 @@ class parser { return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator))); + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::name_separator, "object separator"))); } // remember we are now inside an object @@ -325,14 +330,16 @@ class parser // using "uninitialized" to avoid "expected" message return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized))); + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::uninitialized, "value"))); } default: // the last token was unexpected { return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value))); + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::literal_or_value, "value"))); } } } @@ -380,7 +387,8 @@ class parser { return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array))); + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::end_array, "array"))); } } else // object @@ -393,7 +401,8 @@ class parser { return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string))); + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::value_string, "object key"))); } else { @@ -408,7 +417,8 @@ class parser { return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator))); + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::name_separator, "object separator"))); } // parse values @@ -437,7 +447,8 @@ class parser { return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object))); + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::end_object, "object"))); } } } @@ -450,9 +461,17 @@ class parser return (last_token = m_lexer.scan()); } - std::string exception_message(const token_type expected) + std::string exception_message(const token_type expected, const std::string& context) { - std::string error_msg = "syntax error - "; + std::string error_msg = "syntax error "; + + if (not context.empty()) + { + error_msg += "while parsing " + context + " "; + } + + error_msg += "- "; + if (last_token == token_type::parse_error) { error_msg += std::string(m_lexer.get_error_message()) + "; last read: '" + diff --git a/include/nlohmann/detail/input/position_t.hpp b/include/nlohmann/detail/input/position_t.hpp new file mode 100644 index 00000000..37f4ab15 --- /dev/null +++ b/include/nlohmann/detail/input/position_t.hpp @@ -0,0 +1,27 @@ +#pragma once + +#include // size_t + +namespace nlohmann +{ +namespace detail +{ +/// struct to capture the start position of the current token +struct position_t +{ + /// the total number of characters read + std::size_t chars_read_total = 0; + /// the number of characters read in the current line + std::size_t chars_read_current_line = 0; + /// the number of lines read + std::size_t lines_read = 0; + + /// conversion to size_t to preserve SAX interface + constexpr operator size_t() const + { + return chars_read_total; + } +}; + +} +} diff --git a/include/nlohmann/json.hpp b/include/nlohmann/json.hpp index f58cef14..619fd9e6 100644 --- a/include/nlohmann/json.hpp +++ b/include/nlohmann/json.hpp @@ -5999,6 +5999,8 @@ class basic_json @param[in] cb a parser callback function of type @ref parser_callback_t which is used to control the deserialization by filtering unwanted values (optional) + @param[in] allow_exceptions whether to throw exceptions in case of a + parse error (optional, true by default) @return result of the deserialization @@ -6394,7 +6396,7 @@ class basic_json vector in CBOR format.,to_cbor} @sa http://cbor.io - @sa @ref from_cbor(detail::input_adapter, const bool strict) for the + @sa @ref from_cbor(detail::input_adapter&&, const bool, const bool) for the analogous deserialization @sa @ref to_msgpack(const basic_json&) for the related MessagePack format @sa @ref to_ubjson(const basic_json&, const bool, const bool) for the @@ -6491,8 +6493,7 @@ class basic_json vector in MessagePack format.,to_msgpack} @sa http://msgpack.org - @sa @ref from_msgpack(const std::vector&, const size_t) for the - analogous deserialization + @sa @ref from_msgpack for the analogous deserialization @sa @ref to_cbor(const basic_json& for the related CBOR format @sa @ref to_ubjson(const basic_json&, const bool, const bool) for the related UBJSON format @@ -6589,7 +6590,7 @@ class basic_json vector in UBJSON format.,to_ubjson} @sa http://ubjson.org - @sa @ref from_ubjson(detail::input_adapter, const bool strict) for the + @sa @ref from_ubjson(detail::input_adapter&&, const bool, const bool) for the analogous deserialization @sa @ref to_cbor(const basic_json& for the related CBOR format @sa @ref to_msgpack(const basic_json&) for the related MessagePack format @@ -6704,14 +6705,14 @@ class basic_json @sa http://cbor.io @sa @ref to_cbor(const basic_json&) for the analogous serialization - @sa @ref from_msgpack(detail::input_adapter, const bool, const bool) for the + @sa @ref from_msgpack(detail::input_adapter&&, const bool, const bool) for the related MessagePack format - @sa @ref from_ubjson(detail::input_adapter, const bool, const bool) for the + @sa @ref from_ubjson(detail::input_adapter&&, const bool, const bool) for the related UBJSON format @since version 2.0.9; parameter @a start_index since 2.1.1; changed to consume input adapters, removed start_index parameter, and added - @a strict parameter since 3.0.0; added @allow_exceptions parameter + @a strict parameter since 3.0.0; added @a allow_exceptions parameter since 3.2.0 */ static basic_json from_cbor(detail::input_adapter&& i, @@ -6725,7 +6726,7 @@ class basic_json } /*! - @copydoc from_cbor(detail::input_adapter, const bool, const bool) + @copydoc from_cbor(detail::input_adapter&&, const bool, const bool) */ template::value, int> = 0> @@ -6807,14 +6808,14 @@ class basic_json @sa http://msgpack.org @sa @ref to_msgpack(const basic_json&) for the analogous serialization - @sa @ref from_cbor(detail::input_adapter, const bool, const bool) for the + @sa @ref from_cbor(detail::input_adapter&&, const bool, const bool) for the related CBOR format - @sa @ref from_ubjson(detail::input_adapter, const bool, const bool) for + @sa @ref from_ubjson(detail::input_adapter&&, const bool, const bool) for the related UBJSON format @since version 2.0.9; parameter @a start_index since 2.1.1; changed to consume input adapters, removed start_index parameter, and added - @a strict parameter since 3.0.0; added @allow_exceptions parameter + @a strict parameter since 3.0.0; added @a allow_exceptions parameter since 3.2.0 */ static basic_json from_msgpack(detail::input_adapter&& i, @@ -6828,7 +6829,7 @@ class basic_json } /*! - @copydoc from_msgpack(detail::input_adapter, const bool, const bool) + @copydoc from_msgpack(detail::input_adapter&&, const bool, const bool) */ template::value, int> = 0> @@ -6892,12 +6893,12 @@ class basic_json @sa http://ubjson.org @sa @ref to_ubjson(const basic_json&, const bool, const bool) for the analogous serialization - @sa @ref from_cbor(detail::input_adapter, const bool, const bool) for the + @sa @ref from_cbor(detail::input_adapter&&, const bool, const bool) for the related CBOR format - @sa @ref from_msgpack(detail::input_adapter, const bool, const bool) for + @sa @ref from_msgpack(detail::input_adapter&&, const bool, const bool) for the related MessagePack format - @since version 3.1.0; added @allow_exceptions parameter since 3.2.0 + @since version 3.1.0; added @a allow_exceptions parameter since 3.2.0 */ static basic_json from_ubjson(detail::input_adapter&& i, const bool strict = true, @@ -6910,7 +6911,7 @@ class basic_json } /*! - @copydoc from_ubjson(detail::input_adapter, const bool, const bool) + @copydoc from_ubjson(detail::input_adapter&&, const bool, const bool) */ template::value, int> = 0> diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index d4422c59..af1c8546 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -617,6 +617,36 @@ struct is_compatible_type #include // runtime_error #include // to_string +// #include + + +#include // size_t + +namespace nlohmann +{ +namespace detail +{ +/// struct to capture the start position of the current token +struct position_t +{ + /// the total number of characters read + std::size_t chars_read_total = 0; + /// the number of characters read in the current line + std::size_t chars_read_current_line = 0; + /// the number of lines read + std::size_t lines_read = 0; + + /// conversion to size_t to preserve SAX interface + constexpr operator size_t() const + { + return chars_read_total; + } +}; + +} +} + + namespace nlohmann { namespace detail @@ -727,15 +757,23 @@ class parse_error : public exception /*! @brief create a parse error exception @param[in] id_ the id of the exception - @param[in] byte_ the byte index where the error occurred (or 0 if the - position cannot be determined) + @param[in] position the position where the error occurred (or with + chars_read_total=0 if the position cannot be + determined) @param[in] what_arg the explanatory string @return parse_error object */ + static parse_error create(int id_, const position_t& pos, const std::string& what_arg) + { + std::string w = exception::name("parse_error", id_) + "parse error" + + position_string(pos) + ": " + what_arg; + return parse_error(id_, pos.chars_read_total, w.c_str()); + } + static parse_error create(int id_, std::size_t byte_, const std::string& what_arg) { std::string w = exception::name("parse_error", id_) + "parse error" + - (byte_ != 0 ? (" at " + std::to_string(byte_)) : "") + + (byte_ != 0 ? (" at byte " + std::to_string(byte_)) : "") + ": " + what_arg; return parse_error(id_, byte_, w.c_str()); } @@ -754,6 +792,12 @@ class parse_error : public exception private: parse_error(int id_, std::size_t byte_, const char* what_arg) : exception(id_, what_arg), byte(byte_) {} + + static std::string position_string(const position_t& pos) + { + return " at line " + std::to_string(pos.lines_read + 1) + + ", column " + std::to_string(pos.chars_read_current_line); + } }; /*! @@ -2279,6 +2323,8 @@ class input_adapter // #include +// #include + namespace nlohmann { @@ -2665,39 +2711,194 @@ class lexer // invalid control characters case 0x00: + { + error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000"; + return token_type::parse_error; + } + case 0x01: + { + error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001"; + return token_type::parse_error; + } + case 0x02: + { + error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002"; + return token_type::parse_error; + } + case 0x03: + { + error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003"; + return token_type::parse_error; + } + case 0x04: + { + error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004"; + return token_type::parse_error; + } + case 0x05: + { + error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005"; + return token_type::parse_error; + } + case 0x06: + { + error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006"; + return token_type::parse_error; + } + case 0x07: + { + error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007"; + return token_type::parse_error; + } + case 0x08: + { + error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b"; + return token_type::parse_error; + } + case 0x09: + { + error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t"; + return token_type::parse_error; + } + case 0x0A: + { + error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n"; + return token_type::parse_error; + } + case 0x0B: + { + error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B"; + return token_type::parse_error; + } + case 0x0C: + { + error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f"; + return token_type::parse_error; + } + case 0x0D: + { + error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r"; + return token_type::parse_error; + } + case 0x0E: + { + error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E"; + return token_type::parse_error; + } + case 0x0F: + { + error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F"; + return token_type::parse_error; + } + case 0x10: + { + error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010"; + return token_type::parse_error; + } + case 0x11: + { + error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011"; + return token_type::parse_error; + } + case 0x12: + { + error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012"; + return token_type::parse_error; + } + case 0x13: + { + error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013"; + return token_type::parse_error; + } + case 0x14: + { + error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014"; + return token_type::parse_error; + } + case 0x15: + { + error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015"; + return token_type::parse_error; + } + case 0x16: + { + error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016"; + return token_type::parse_error; + } + case 0x17: + { + error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017"; + return token_type::parse_error; + } + case 0x18: + { + error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018"; + return token_type::parse_error; + } + case 0x19: + { + error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019"; + return token_type::parse_error; + } + case 0x1A: + { + error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A"; + return token_type::parse_error; + } + case 0x1B: + { + error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B"; + return token_type::parse_error; + } + case 0x1C: + { + error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C"; + return token_type::parse_error; + } + case 0x1D: + { + error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D"; + return token_type::parse_error; + } + case 0x1E: + { + error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E"; + return token_type::parse_error; + } + case 0x1F: { - error_message = "invalid string: control character must be escaped"; + error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F"; return token_type::parse_error; } @@ -3354,7 +3555,9 @@ scan_number_done: */ std::char_traits::int_type get() { - ++chars_read; + ++position.chars_read_total; + ++position.chars_read_current_line; + if (next_unget) { // just reset the next_unget variable and work with current @@ -3369,6 +3572,13 @@ scan_number_done: { token_string.push_back(std::char_traits::to_char_type(current)); } + + if (current == '\n') + { + ++position.lines_read; + ++position.chars_read_current_line = 0; + } + return current; } @@ -3376,14 +3586,29 @@ scan_number_done: @brief unget current character (read it again on next get) We implement unget by setting variable next_unget to true. The input is not - changed - we just simulate ungetting by modifying chars_read and - token_string. The next call to get() will behave as if the unget character - is read again. + changed - we just simulate ungetting by modifying chars_read_total, + chars_read_current_line, and token_string. The next call to get() will + behave as if the unget character is read again. */ void unget() { next_unget = true; - --chars_read; + + --position.chars_read_total; + + // in case we "unget" a newline, we have to also decrement the lines_read + if (position.chars_read_current_line == 0) + { + if (position.lines_read > 0) + { + --position.lines_read; + } + } + else + { + --position.chars_read_current_line; + } + if (JSON_LIKELY(current != std::char_traits::eof())) { assert(token_string.size() != 0); @@ -3431,9 +3656,9 @@ scan_number_done: ///////////////////// /// return position of last read token - constexpr std::size_t get_position() const noexcept + constexpr position_t get_position() const noexcept { - return chars_read; + return position; } /// return the last read token (for errors only). Will never contain EOF @@ -3493,7 +3718,7 @@ scan_number_done: token_type scan() { // initially, skip the BOM - if (chars_read == 0 and not skip_bom()) + if (position.chars_read_total == 0 and not skip_bom()) { error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given"; return token_type::parse_error; @@ -3571,8 +3796,8 @@ scan_number_done: /// whether the next get() call should just return current bool next_unget = false; - /// the number of characters read - std::size_t chars_read = 0; + /// the start position of the current token + position_t position; /// raw input token string (for error messages) std::vector token_string {}; @@ -3873,7 +4098,7 @@ struct json_sax @brief a parse error occurred @param[in] position the position in the input where the error occurs @param[in] last_token the last read token - @param[in] error_msg a detailed error message + @param[in] ex an exception object describing the error @return whether parsing should proceed (must return false) */ virtual bool parse_error(std::size_t position, @@ -4541,7 +4766,8 @@ class parser { sdp.parse_error(m_lexer.get_position(), m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input))); + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::end_of_input, "value"))); } // in case of an error, return discarded value @@ -4569,7 +4795,8 @@ class parser { sdp.parse_error(m_lexer.get_position(), m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input))); + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::end_of_input, "value"))); } // in case of an error, return discarded value @@ -4604,7 +4831,8 @@ class parser { return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input))); + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::end_of_input, "value"))); } return result; @@ -4649,7 +4877,8 @@ class parser { return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string))); + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::value_string, "object key"))); } if (JSON_UNLIKELY(not sax->key(m_lexer.get_string()))) { @@ -4661,7 +4890,8 @@ class parser { return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator))); + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::name_separator, "object separator"))); } // remember we are now inside an object @@ -4775,14 +5005,16 @@ class parser // using "uninitialized" to avoid "expected" message return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized))); + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::uninitialized, "value"))); } default: // the last token was unexpected { return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value))); + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::literal_or_value, "value"))); } } } @@ -4830,7 +5062,8 @@ class parser { return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array))); + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::end_array, "array"))); } } else // object @@ -4843,7 +5076,8 @@ class parser { return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string))); + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::value_string, "object key"))); } else { @@ -4858,7 +5092,8 @@ class parser { return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator))); + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::name_separator, "object separator"))); } // parse values @@ -4887,7 +5122,8 @@ class parser { return sax->parse_error(m_lexer.get_position(), m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object))); + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::end_object, "object"))); } } } @@ -4900,9 +5136,17 @@ class parser return (last_token = m_lexer.scan()); } - std::string exception_message(const token_type expected) + std::string exception_message(const token_type expected, const std::string& context) { - std::string error_msg = "syntax error - "; + std::string error_msg = "syntax error "; + + if (not context.empty()) + { + error_msg += "while parsing " + context + " "; + } + + error_msg += "- "; + if (last_token == token_type::parse_error) { error_msg += std::string(m_lexer.get_error_message()) + "; last read: '" + @@ -17092,6 +17336,8 @@ class basic_json @param[in] cb a parser callback function of type @ref parser_callback_t which is used to control the deserialization by filtering unwanted values (optional) + @param[in] allow_exceptions whether to throw exceptions in case of a + parse error (optional, true by default) @return result of the deserialization @@ -17487,7 +17733,7 @@ class basic_json vector in CBOR format.,to_cbor} @sa http://cbor.io - @sa @ref from_cbor(detail::input_adapter, const bool strict) for the + @sa @ref from_cbor(detail::input_adapter&&, const bool, const bool) for the analogous deserialization @sa @ref to_msgpack(const basic_json&) for the related MessagePack format @sa @ref to_ubjson(const basic_json&, const bool, const bool) for the @@ -17584,8 +17830,7 @@ class basic_json vector in MessagePack format.,to_msgpack} @sa http://msgpack.org - @sa @ref from_msgpack(const std::vector&, const size_t) for the - analogous deserialization + @sa @ref from_msgpack for the analogous deserialization @sa @ref to_cbor(const basic_json& for the related CBOR format @sa @ref to_ubjson(const basic_json&, const bool, const bool) for the related UBJSON format @@ -17682,7 +17927,7 @@ class basic_json vector in UBJSON format.,to_ubjson} @sa http://ubjson.org - @sa @ref from_ubjson(detail::input_adapter, const bool strict) for the + @sa @ref from_ubjson(detail::input_adapter&&, const bool, const bool) for the analogous deserialization @sa @ref to_cbor(const basic_json& for the related CBOR format @sa @ref to_msgpack(const basic_json&) for the related MessagePack format @@ -17797,14 +18042,14 @@ class basic_json @sa http://cbor.io @sa @ref to_cbor(const basic_json&) for the analogous serialization - @sa @ref from_msgpack(detail::input_adapter, const bool, const bool) for the + @sa @ref from_msgpack(detail::input_adapter&&, const bool, const bool) for the related MessagePack format - @sa @ref from_ubjson(detail::input_adapter, const bool, const bool) for the + @sa @ref from_ubjson(detail::input_adapter&&, const bool, const bool) for the related UBJSON format @since version 2.0.9; parameter @a start_index since 2.1.1; changed to consume input adapters, removed start_index parameter, and added - @a strict parameter since 3.0.0; added @allow_exceptions parameter + @a strict parameter since 3.0.0; added @a allow_exceptions parameter since 3.2.0 */ static basic_json from_cbor(detail::input_adapter&& i, @@ -17818,7 +18063,7 @@ class basic_json } /*! - @copydoc from_cbor(detail::input_adapter, const bool, const bool) + @copydoc from_cbor(detail::input_adapter&&, const bool, const bool) */ template::value, int> = 0> @@ -17900,14 +18145,14 @@ class basic_json @sa http://msgpack.org @sa @ref to_msgpack(const basic_json&) for the analogous serialization - @sa @ref from_cbor(detail::input_adapter, const bool, const bool) for the + @sa @ref from_cbor(detail::input_adapter&&, const bool, const bool) for the related CBOR format - @sa @ref from_ubjson(detail::input_adapter, const bool, const bool) for + @sa @ref from_ubjson(detail::input_adapter&&, const bool, const bool) for the related UBJSON format @since version 2.0.9; parameter @a start_index since 2.1.1; changed to consume input adapters, removed start_index parameter, and added - @a strict parameter since 3.0.0; added @allow_exceptions parameter + @a strict parameter since 3.0.0; added @a allow_exceptions parameter since 3.2.0 */ static basic_json from_msgpack(detail::input_adapter&& i, @@ -17921,7 +18166,7 @@ class basic_json } /*! - @copydoc from_msgpack(detail::input_adapter, const bool, const bool) + @copydoc from_msgpack(detail::input_adapter&&, const bool, const bool) */ template::value, int> = 0> @@ -17985,12 +18230,12 @@ class basic_json @sa http://ubjson.org @sa @ref to_ubjson(const basic_json&, const bool, const bool) for the analogous serialization - @sa @ref from_cbor(detail::input_adapter, const bool, const bool) for the + @sa @ref from_cbor(detail::input_adapter&&, const bool, const bool) for the related CBOR format - @sa @ref from_msgpack(detail::input_adapter, const bool, const bool) for + @sa @ref from_msgpack(detail::input_adapter&&, const bool, const bool) for the related MessagePack format - @since version 3.1.0; added @allow_exceptions parameter since 3.2.0 + @since version 3.1.0; added @a allow_exceptions parameter since 3.2.0 */ static basic_json from_ubjson(detail::input_adapter&& i, const bool strict = true, @@ -18003,7 +18248,7 @@ class basic_json } /*! - @copydoc from_ubjson(detail::input_adapter, const bool, const bool) + @copydoc from_ubjson(detail::input_adapter&&, const bool, const bool) */ template::value, int> = 0> diff --git a/test/src/unit-cbor.cpp b/test/src/unit-cbor.cpp index 0d2ca939..62520a0b 100644 --- a/test/src/unit-cbor.cpp +++ b/test/src/unit-cbor.cpp @@ -831,14 +831,14 @@ TEST_CASE("CBOR") { CHECK_THROWS_AS(json::from_cbor(std::vector({0xf9})), json::parse_error&); CHECK_THROWS_WITH(json::from_cbor(std::vector({0xf9})), - "[json.exception.parse_error.110] parse error at 2: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 2: unexpected end of input"); CHECK(json::from_cbor(std::vector({0xf9}), true, false).is_discarded()); } SECTION("only one byte follows") { CHECK_THROWS_AS(json::from_cbor(std::vector({0xf9, 0x7c})), json::parse_error&); CHECK_THROWS_WITH(json::from_cbor(std::vector({0xf9, 0x7c})), - "[json.exception.parse_error.110] parse error at 3: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 3: unexpected end of input"); CHECK(json::from_cbor(std::vector({0xf9, 0x7c}), true, false).is_discarded()); } } @@ -1314,7 +1314,7 @@ TEST_CASE("CBOR") { CHECK_THROWS_AS(json::from_cbor(std::vector()), json::parse_error&); CHECK_THROWS_WITH(json::from_cbor(std::vector()), - "[json.exception.parse_error.110] parse error at 1: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 1: unexpected end of input"); CHECK(json::from_cbor(std::vector(), true, false).is_discarded()); } @@ -1346,53 +1346,53 @@ TEST_CASE("CBOR") CHECK_THROWS_AS(json::from_cbor(std::vector({0xBF, 0x61, 0X61})), json::parse_error&); CHECK_THROWS_WITH(json::from_cbor(std::vector({0x18})), - "[json.exception.parse_error.110] parse error at 2: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 2: unexpected end of input"); CHECK_THROWS_WITH(json::from_cbor(std::vector({0x19})), - "[json.exception.parse_error.110] parse error at 2: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 2: unexpected end of input"); CHECK_THROWS_WITH(json::from_cbor(std::vector({0x19, 0x00})), - "[json.exception.parse_error.110] parse error at 3: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 3: unexpected end of input"); CHECK_THROWS_WITH(json::from_cbor(std::vector({0x1a})), - "[json.exception.parse_error.110] parse error at 2: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 2: unexpected end of input"); CHECK_THROWS_WITH(json::from_cbor(std::vector({0x1a, 0x00})), - "[json.exception.parse_error.110] parse error at 3: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 3: unexpected end of input"); CHECK_THROWS_WITH(json::from_cbor(std::vector({0x1a, 0x00, 0x00})), - "[json.exception.parse_error.110] parse error at 4: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 4: unexpected end of input"); CHECK_THROWS_WITH(json::from_cbor(std::vector({0x1a, 0x00, 0x00, 0x00})), - "[json.exception.parse_error.110] parse error at 5: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 5: unexpected end of input"); CHECK_THROWS_WITH(json::from_cbor(std::vector({0x1b})), - "[json.exception.parse_error.110] parse error at 2: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 2: unexpected end of input"); CHECK_THROWS_WITH(json::from_cbor(std::vector({0x1b, 0x00})), - "[json.exception.parse_error.110] parse error at 3: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 3: unexpected end of input"); CHECK_THROWS_WITH(json::from_cbor(std::vector({0x1b, 0x00, 0x00})), - "[json.exception.parse_error.110] parse error at 4: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 4: unexpected end of input"); CHECK_THROWS_WITH(json::from_cbor(std::vector({0x1b, 0x00, 0x00, 0x00})), - "[json.exception.parse_error.110] parse error at 5: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 5: unexpected end of input"); CHECK_THROWS_WITH(json::from_cbor(std::vector({0x1b, 0x00, 0x00, 0x00, 0x00})), - "[json.exception.parse_error.110] parse error at 6: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 6: unexpected end of input"); CHECK_THROWS_WITH(json::from_cbor(std::vector({0x1b, 0x00, 0x00, 0x00, 0x00, 0x00})), - "[json.exception.parse_error.110] parse error at 7: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 7: unexpected end of input"); CHECK_THROWS_WITH(json::from_cbor(std::vector({0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})), - "[json.exception.parse_error.110] parse error at 8: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 8: unexpected end of input"); CHECK_THROWS_WITH(json::from_cbor(std::vector({0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})), - "[json.exception.parse_error.110] parse error at 9: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 9: unexpected end of input"); CHECK_THROWS_WITH(json::from_cbor(std::vector({0x62})), - "[json.exception.parse_error.110] parse error at 2: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 2: unexpected end of input"); CHECK_THROWS_WITH(json::from_cbor(std::vector({0x62, 0x60})), - "[json.exception.parse_error.110] parse error at 3: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 3: unexpected end of input"); CHECK_THROWS_WITH(json::from_cbor(std::vector({0x7F})), - "[json.exception.parse_error.110] parse error at 2: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 2: unexpected end of input"); CHECK_THROWS_WITH(json::from_cbor(std::vector({0x7F, 0x60})), - "[json.exception.parse_error.110] parse error at 3: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 3: unexpected end of input"); CHECK_THROWS_WITH(json::from_cbor(std::vector({0x82, 0x01})), - "[json.exception.parse_error.110] parse error at 3: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 3: unexpected end of input"); CHECK_THROWS_WITH(json::from_cbor(std::vector({0x9F, 0x01})), - "[json.exception.parse_error.110] parse error at 3: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 3: unexpected end of input"); CHECK_THROWS_WITH(json::from_cbor(std::vector({0xBF, 0x61, 0x61, 0xF5})), - "[json.exception.parse_error.110] parse error at 5: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 5: unexpected end of input"); CHECK_THROWS_WITH(json::from_cbor(std::vector({0xA1, 0x61, 0x61})), - "[json.exception.parse_error.110] parse error at 4: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 4: unexpected end of input"); CHECK_THROWS_WITH(json::from_cbor(std::vector({0xBF, 0x61, 0x61})), - "[json.exception.parse_error.110] parse error at 4: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 4: unexpected end of input"); CHECK(json::from_cbor(std::vector({0x18}), true, false).is_discarded()); CHECK(json::from_cbor(std::vector({0x19}), true, false).is_discarded()); @@ -1426,12 +1426,12 @@ TEST_CASE("CBOR") { CHECK_THROWS_AS(json::from_cbor(std::vector({0x1c})), json::parse_error&); CHECK_THROWS_WITH(json::from_cbor(std::vector({0x1c})), - "[json.exception.parse_error.112] parse error at 1: error reading CBOR; last byte: 0x1C"); + "[json.exception.parse_error.112] parse error at byte 1: error reading CBOR; last byte: 0x1C"); CHECK(json::from_cbor(std::vector({0x1c}), true, false).is_discarded()); CHECK_THROWS_AS(json::from_cbor(std::vector({0xf8})), json::parse_error&); CHECK_THROWS_WITH(json::from_cbor(std::vector({0xf8})), - "[json.exception.parse_error.112] parse error at 1: error reading CBOR; last byte: 0xF8"); + "[json.exception.parse_error.112] parse error at byte 1: error reading CBOR; last byte: 0xF8"); CHECK(json::from_cbor(std::vector({0xf8}), true, false).is_discarded()); } @@ -1491,7 +1491,7 @@ TEST_CASE("CBOR") { CHECK_THROWS_AS(json::from_cbor(std::vector({0xa1, 0xff, 0x01})), json::parse_error&); CHECK_THROWS_WITH(json::from_cbor(std::vector({0xa1, 0xff, 0x01})), - "[json.exception.parse_error.113] parse error at 2: expected a CBOR string; last byte: 0xFF"); + "[json.exception.parse_error.113] parse error at byte 2: expected a CBOR string; last byte: 0xFF"); CHECK(json::from_cbor(std::vector({0xa1, 0xff, 0x01}), true, false).is_discarded()); } @@ -1509,7 +1509,7 @@ TEST_CASE("CBOR") { CHECK_THROWS_AS(json::from_cbor(vec), json::parse_error&); CHECK_THROWS_WITH(json::from_cbor(vec), - "[json.exception.parse_error.110] parse error at 2: expected end of input"); + "[json.exception.parse_error.110] parse error at byte 2: expected end of input"); CHECK(json::from_cbor(vec, true, false).is_discarded()); } } diff --git a/test/src/unit-class_parser.cpp b/test/src/unit-class_parser.cpp index b467acd9..8d0b68d2 100644 --- a/test/src/unit-class_parser.cpp +++ b/test/src/unit-class_parser.cpp @@ -313,18 +313,18 @@ TEST_CASE("parser class") // error: tab in string CHECK_THROWS_AS(parser_helper("\"\t\""), json::parse_error&); CHECK_THROWS_WITH(parser_helper("\"\t\""), - "[json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: '\"'"); + "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t; last read: '\"'"); // error: newline in string CHECK_THROWS_AS(parser_helper("\"\n\""), json::parse_error&); CHECK_THROWS_AS(parser_helper("\"\r\""), json::parse_error&); CHECK_THROWS_WITH(parser_helper("\"\n\""), - "[json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: '\"'"); + "[json.exception.parse_error.101] parse error at line 2, column 0: syntax error while parsing value - invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n; last read: '\"'"); CHECK_THROWS_WITH(parser_helper("\"\r\""), - "[json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: '\"'"); + "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r; last read: '\"'"); // error: backspace in string CHECK_THROWS_AS(parser_helper("\"\b\""), json::parse_error&); CHECK_THROWS_WITH(parser_helper("\"\b\""), - "[json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: '\"'"); + "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b; last read: '\"'"); // improve code coverage CHECK_THROWS_AS(parser_helper("\uFF01"), json::parse_error&); CHECK_THROWS_AS(parser_helper("[-4:1,]"), json::parse_error&); @@ -361,38 +361,38 @@ TEST_CASE("parser class") CHECK_THROWS_AS(parser_helper("\"\x1d\""), json::parse_error&); CHECK_THROWS_AS(parser_helper("\"\x1e\""), json::parse_error&); CHECK_THROWS_AS(parser_helper("\"\x1f\""), json::parse_error&); - CHECK_THROWS_WITH(parser_helper("\"\x00\""), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid string: missing closing quote; last read: '\"'"); - CHECK_THROWS_WITH(parser_helper("\"\x01\""), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: '\"'"); - CHECK_THROWS_WITH(parser_helper("\"\x02\""), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: '\"'"); - CHECK_THROWS_WITH(parser_helper("\"\x03\""), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: '\"'"); - CHECK_THROWS_WITH(parser_helper("\"\x04\""), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: '\"'"); - CHECK_THROWS_WITH(parser_helper("\"\x05\""), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: '\"'"); - CHECK_THROWS_WITH(parser_helper("\"\x06\""), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: '\"'"); - CHECK_THROWS_WITH(parser_helper("\"\x07\""), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: '\"'"); - CHECK_THROWS_WITH(parser_helper("\"\x08\""), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: '\"'"); - CHECK_THROWS_WITH(parser_helper("\"\x09\""), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: '\"'"); - CHECK_THROWS_WITH(parser_helper("\"\x0a\""), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: '\"'"); - CHECK_THROWS_WITH(parser_helper("\"\x0b\""), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: '\"'"); - CHECK_THROWS_WITH(parser_helper("\"\x0c\""), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: '\"'"); - CHECK_THROWS_WITH(parser_helper("\"\x0d\""), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: '\"'"); - CHECK_THROWS_WITH(parser_helper("\"\x0e\""), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: '\"'"); - CHECK_THROWS_WITH(parser_helper("\"\x0f\""), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: '\"'"); - CHECK_THROWS_WITH(parser_helper("\"\x10\""), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: '\"'"); - CHECK_THROWS_WITH(parser_helper("\"\x11\""), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: '\"'"); - CHECK_THROWS_WITH(parser_helper("\"\x12\""), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: '\"'"); - CHECK_THROWS_WITH(parser_helper("\"\x13\""), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: '\"'"); - CHECK_THROWS_WITH(parser_helper("\"\x14\""), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: '\"'"); - CHECK_THROWS_WITH(parser_helper("\"\x15\""), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: '\"'"); - CHECK_THROWS_WITH(parser_helper("\"\x16\""), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: '\"'"); - CHECK_THROWS_WITH(parser_helper("\"\x17\""), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: '\"'"); - CHECK_THROWS_WITH(parser_helper("\"\x18\""), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: '\"'"); - CHECK_THROWS_WITH(parser_helper("\"\x19\""), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: '\"'"); - CHECK_THROWS_WITH(parser_helper("\"\x1a\""), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: '\"'"); - CHECK_THROWS_WITH(parser_helper("\"\x1b\""), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: '\"'"); - CHECK_THROWS_WITH(parser_helper("\"\x1c\""), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: '\"'"); - CHECK_THROWS_WITH(parser_helper("\"\x1d\""), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: '\"'"); - CHECK_THROWS_WITH(parser_helper("\"\x1e\""), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: '\"'"); - CHECK_THROWS_WITH(parser_helper("\"\x1f\""), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: '\"'"); + CHECK_THROWS_WITH(parser_helper("\"\x00\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: missing closing quote; last read: '\"'"); + CHECK_THROWS_WITH(parser_helper("\"\x01\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0001 (SOH) must be escaped to \\u0001; last read: '\"'"); + CHECK_THROWS_WITH(parser_helper("\"\x02\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0002 (STX) must be escaped to \\u0002; last read: '\"'"); + CHECK_THROWS_WITH(parser_helper("\"\x03\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0003 (ETX) must be escaped to \\u0003; last read: '\"'"); + CHECK_THROWS_WITH(parser_helper("\"\x04\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0004 (EOT) must be escaped to \\u0004; last read: '\"'"); + CHECK_THROWS_WITH(parser_helper("\"\x05\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0005 (ENQ) must be escaped to \\u0005; last read: '\"'"); + CHECK_THROWS_WITH(parser_helper("\"\x06\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0006 (ACK) must be escaped to \\u0006; last read: '\"'"); + CHECK_THROWS_WITH(parser_helper("\"\x07\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0007 (BEL) must be escaped to \\u0007; last read: '\"'"); + CHECK_THROWS_WITH(parser_helper("\"\x08\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b; last read: '\"'"); + CHECK_THROWS_WITH(parser_helper("\"\x09\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t; last read: '\"'"); + CHECK_THROWS_WITH(parser_helper("\"\x0a\""), "[json.exception.parse_error.101] parse error at line 2, column 0: syntax error while parsing value - invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n; last read: '\"'"); + CHECK_THROWS_WITH(parser_helper("\"\x0b\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+000B (VT) must be escaped to \\u000B; last read: '\"'"); + CHECK_THROWS_WITH(parser_helper("\"\x0c\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f; last read: '\"'"); + CHECK_THROWS_WITH(parser_helper("\"\x0d\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r; last read: '\"'"); + CHECK_THROWS_WITH(parser_helper("\"\x0e\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+000E (SO) must be escaped to \\u000E; last read: '\"'"); + CHECK_THROWS_WITH(parser_helper("\"\x0f\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+000F (SI) must be escaped to \\u000F; last read: '\"'"); + CHECK_THROWS_WITH(parser_helper("\"\x10\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0010 (DLE) must be escaped to \\u0010; last read: '\"'"); + CHECK_THROWS_WITH(parser_helper("\"\x11\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0011 (DC1) must be escaped to \\u0011; last read: '\"'"); + CHECK_THROWS_WITH(parser_helper("\"\x12\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0012 (DC2) must be escaped to \\u0012; last read: '\"'"); + CHECK_THROWS_WITH(parser_helper("\"\x13\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0013 (DC3) must be escaped to \\u0013; last read: '\"'"); + CHECK_THROWS_WITH(parser_helper("\"\x14\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0014 (DC4) must be escaped to \\u0014; last read: '\"'"); + CHECK_THROWS_WITH(parser_helper("\"\x15\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0015 (NAK) must be escaped to \\u0015; last read: '\"'"); + CHECK_THROWS_WITH(parser_helper("\"\x16\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0016 (SYN) must be escaped to \\u0016; last read: '\"'"); + CHECK_THROWS_WITH(parser_helper("\"\x17\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0017 (ETB) must be escaped to \\u0017; last read: '\"'"); + CHECK_THROWS_WITH(parser_helper("\"\x18\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0018 (CAN) must be escaped to \\u0018; last read: '\"'"); + CHECK_THROWS_WITH(parser_helper("\"\x19\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0019 (EM) must be escaped to \\u0019; last read: '\"'"); + CHECK_THROWS_WITH(parser_helper("\"\x1a\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+001A (SUB) must be escaped to \\u001A; last read: '\"'"); + CHECK_THROWS_WITH(parser_helper("\"\x1b\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+001B (ESC) must be escaped to \\u001B; last read: '\"'"); + CHECK_THROWS_WITH(parser_helper("\"\x1c\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+001C (FS) must be escaped to \\u001C; last read: '\"'"); + CHECK_THROWS_WITH(parser_helper("\"\x1d\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+001D (GS) must be escaped to \\u001D; last read: '\"'"); + CHECK_THROWS_WITH(parser_helper("\"\x1e\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+001E (RS) must be escaped to \\u001E; last read: '\"'"); + CHECK_THROWS_WITH(parser_helper("\"\x1f\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+001F (US) must be escaped to \\u001F; last read: '\"'"); SECTION("additional test for null byte") { @@ -403,7 +403,7 @@ TEST_CASE("parser class") std::string s = "\"1\""; s[1] = '\0'; CHECK_THROWS_AS(json::parse(s.begin(), s.end()), json::parse_error&); - CHECK_THROWS_WITH(json::parse(s.begin(), s.end()), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control character must be escaped; last read: '\"'"); + CHECK_THROWS_WITH(json::parse(s.begin(), s.end()), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0000 (NUL) must be escaped to \\u0000; last read: '\"'"); } } @@ -603,39 +603,39 @@ TEST_CASE("parser class") CHECK_THROWS_AS(parser_helper("+0"), json::parse_error&); CHECK_THROWS_WITH(parser_helper("01"), - "[json.exception.parse_error.101] parse error at 2: syntax error - unexpected number literal; expected end of input"); + "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - unexpected number literal; expected end of input"); CHECK_THROWS_WITH(parser_helper("-01"), - "[json.exception.parse_error.101] parse error at 3: syntax error - unexpected number literal; expected end of input"); + "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - unexpected number literal; expected end of input"); CHECK_THROWS_WITH(parser_helper("--1"), - "[json.exception.parse_error.101] parse error at 2: syntax error - invalid number; expected digit after '-'; last read: '--'"); + "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid number; expected digit after '-'; last read: '--'"); CHECK_THROWS_WITH(parser_helper("1."), - "[json.exception.parse_error.101] parse error at 3: syntax error - invalid number; expected digit after '.'; last read: '1.'"); + "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid number; expected digit after '.'; last read: '1.'"); CHECK_THROWS_WITH(parser_helper("1E"), - "[json.exception.parse_error.101] parse error at 3: syntax error - invalid number; expected '+', '-', or digit after exponent; last read: '1E'"); + "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid number; expected '+', '-', or digit after exponent; last read: '1E'"); CHECK_THROWS_WITH(parser_helper("1E-"), - "[json.exception.parse_error.101] parse error at 4: syntax error - invalid number; expected digit after exponent sign; last read: '1E-'"); + "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid number; expected digit after exponent sign; last read: '1E-'"); CHECK_THROWS_WITH(parser_helper("1.E1"), - "[json.exception.parse_error.101] parse error at 3: syntax error - invalid number; expected digit after '.'; last read: '1.E'"); + "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid number; expected digit after '.'; last read: '1.E'"); CHECK_THROWS_WITH(parser_helper("-1E"), - "[json.exception.parse_error.101] parse error at 4: syntax error - invalid number; expected '+', '-', or digit after exponent; last read: '-1E'"); + "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid number; expected '+', '-', or digit after exponent; last read: '-1E'"); CHECK_THROWS_WITH(parser_helper("-0E#"), - "[json.exception.parse_error.101] parse error at 4: syntax error - invalid number; expected '+', '-', or digit after exponent; last read: '-0E#'"); + "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid number; expected '+', '-', or digit after exponent; last read: '-0E#'"); CHECK_THROWS_WITH(parser_helper("-0E-#"), - "[json.exception.parse_error.101] parse error at 5: syntax error - invalid number; expected digit after exponent sign; last read: '-0E-#'"); + "[json.exception.parse_error.101] parse error at line 1, column 5: syntax error while parsing value - invalid number; expected digit after exponent sign; last read: '-0E-#'"); CHECK_THROWS_WITH(parser_helper("-0#"), - "[json.exception.parse_error.101] parse error at 3: syntax error - invalid literal; last read: '-0#'; expected end of input"); + "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid literal; last read: '-0#'; expected end of input"); CHECK_THROWS_WITH(parser_helper("-0.0:"), - "[json.exception.parse_error.101] parse error at 5: syntax error - unexpected ':'; expected end of input"); + "[json.exception.parse_error.101] parse error at line 1, column 5: syntax error while parsing value - unexpected ':'; expected end of input"); CHECK_THROWS_WITH(parser_helper("-0.0Z"), - "[json.exception.parse_error.101] parse error at 5: syntax error - invalid literal; last read: '-0.0Z'; expected end of input"); + "[json.exception.parse_error.101] parse error at line 1, column 5: syntax error while parsing value - invalid literal; last read: '-0.0Z'; expected end of input"); CHECK_THROWS_WITH(parser_helper("-0E123:"), - "[json.exception.parse_error.101] parse error at 7: syntax error - unexpected ':'; expected end of input"); + "[json.exception.parse_error.101] parse error at line 1, column 7: syntax error while parsing value - unexpected ':'; expected end of input"); CHECK_THROWS_WITH(parser_helper("-0e0-:"), - "[json.exception.parse_error.101] parse error at 6: syntax error - invalid number; expected digit after '-'; last read: '-:'; expected end of input"); + "[json.exception.parse_error.101] parse error at line 1, column 6: syntax error while parsing value - invalid number; expected digit after '-'; last read: '-:'; expected end of input"); CHECK_THROWS_WITH(parser_helper("-0e-:"), - "[json.exception.parse_error.101] parse error at 5: syntax error - invalid number; expected digit after exponent sign; last read: '-0e-:'"); + "[json.exception.parse_error.101] parse error at line 1, column 5: syntax error while parsing value - invalid number; expected digit after exponent sign; last read: '-0e-:'"); CHECK_THROWS_WITH(parser_helper("-0f"), - "[json.exception.parse_error.101] parse error at 4: syntax error - invalid literal; last read: '-0f'; expected end of input"); + "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid literal; last read: '-0f'; expected end of input"); } } } @@ -920,33 +920,33 @@ TEST_CASE("parser class") CHECK_THROWS_AS(parser_helper("1E/"), json::parse_error&); CHECK_THROWS_AS(parser_helper("1E:"), json::parse_error&); CHECK_THROWS_WITH(parser_helper("0."), - "[json.exception.parse_error.101] parse error at 3: syntax error - invalid number; expected digit after '.'; last read: '0.'"); + "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid number; expected digit after '.'; last read: '0.'"); CHECK_THROWS_WITH(parser_helper("-"), - "[json.exception.parse_error.101] parse error at 2: syntax error - invalid number; expected digit after '-'; last read: '-'"); + "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid number; expected digit after '-'; last read: '-'"); CHECK_THROWS_WITH(parser_helper("--"), - "[json.exception.parse_error.101] parse error at 2: syntax error - invalid number; expected digit after '-'; last read: '--'"); + "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid number; expected digit after '-'; last read: '--'"); CHECK_THROWS_WITH(parser_helper("-0."), - "[json.exception.parse_error.101] parse error at 4: syntax error - invalid number; expected digit after '.'; last read: '-0.'"); + "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid number; expected digit after '.'; last read: '-0.'"); CHECK_THROWS_WITH(parser_helper("-."), - "[json.exception.parse_error.101] parse error at 2: syntax error - invalid number; expected digit after '-'; last read: '-.'"); + "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid number; expected digit after '-'; last read: '-.'"); CHECK_THROWS_WITH(parser_helper("-:"), - "[json.exception.parse_error.101] parse error at 2: syntax error - invalid number; expected digit after '-'; last read: '-:'"); + "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid number; expected digit after '-'; last read: '-:'"); CHECK_THROWS_WITH(parser_helper("0.:"), - "[json.exception.parse_error.101] parse error at 3: syntax error - invalid number; expected digit after '.'; last read: '0.:'"); + "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid number; expected digit after '.'; last read: '0.:'"); CHECK_THROWS_WITH(parser_helper("e."), - "[json.exception.parse_error.101] parse error at 1: syntax error - invalid literal; last read: 'e'"); + "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - invalid literal; last read: 'e'"); CHECK_THROWS_WITH(parser_helper("1e."), - "[json.exception.parse_error.101] parse error at 3: syntax error - invalid number; expected '+', '-', or digit after exponent; last read: '1e.'"); + "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid number; expected '+', '-', or digit after exponent; last read: '1e.'"); CHECK_THROWS_WITH(parser_helper("1e/"), - "[json.exception.parse_error.101] parse error at 3: syntax error - invalid number; expected '+', '-', or digit after exponent; last read: '1e/'"); + "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid number; expected '+', '-', or digit after exponent; last read: '1e/'"); CHECK_THROWS_WITH(parser_helper("1e:"), - "[json.exception.parse_error.101] parse error at 3: syntax error - invalid number; expected '+', '-', or digit after exponent; last read: '1e:'"); + "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid number; expected '+', '-', or digit after exponent; last read: '1e:'"); CHECK_THROWS_WITH(parser_helper("1E."), - "[json.exception.parse_error.101] parse error at 3: syntax error - invalid number; expected '+', '-', or digit after exponent; last read: '1E.'"); + "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid number; expected '+', '-', or digit after exponent; last read: '1E.'"); CHECK_THROWS_WITH(parser_helper("1E/"), - "[json.exception.parse_error.101] parse error at 3: syntax error - invalid number; expected '+', '-', or digit after exponent; last read: '1E/'"); + "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid number; expected '+', '-', or digit after exponent; last read: '1E/'"); CHECK_THROWS_WITH(parser_helper("1E:"), - "[json.exception.parse_error.101] parse error at 3: syntax error - invalid number; expected '+', '-', or digit after exponent; last read: '1E:'"); + "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid number; expected '+', '-', or digit after exponent; last read: '1E:'"); // unexpected end of null CHECK_THROWS_AS(parser_helper("n"), json::parse_error&); @@ -955,15 +955,15 @@ TEST_CASE("parser class") CHECK_THROWS_AS(parser_helper("nulk"), json::parse_error&); CHECK_THROWS_AS(parser_helper("nulm"), json::parse_error&); CHECK_THROWS_WITH(parser_helper("n"), - "[json.exception.parse_error.101] parse error at 2: syntax error - invalid literal; last read: 'n'"); + "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid literal; last read: 'n'"); CHECK_THROWS_WITH(parser_helper("nu"), - "[json.exception.parse_error.101] parse error at 3: syntax error - invalid literal; last read: 'nu'"); + "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid literal; last read: 'nu'"); CHECK_THROWS_WITH(parser_helper("nul"), - "[json.exception.parse_error.101] parse error at 4: syntax error - invalid literal; last read: 'nul'"); + "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid literal; last read: 'nul'"); CHECK_THROWS_WITH(parser_helper("nulk"), - "[json.exception.parse_error.101] parse error at 4: syntax error - invalid literal; last read: 'nulk'"); + "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid literal; last read: 'nulk'"); CHECK_THROWS_WITH(parser_helper("nulm"), - "[json.exception.parse_error.101] parse error at 4: syntax error - invalid literal; last read: 'nulm'"); + "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid literal; last read: 'nulm'"); // unexpected end of true CHECK_THROWS_AS(parser_helper("t"), json::parse_error&); @@ -972,15 +972,15 @@ TEST_CASE("parser class") CHECK_THROWS_AS(parser_helper("trud"), json::parse_error&); CHECK_THROWS_AS(parser_helper("truf"), json::parse_error&); CHECK_THROWS_WITH(parser_helper("t"), - "[json.exception.parse_error.101] parse error at 2: syntax error - invalid literal; last read: 't'"); + "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid literal; last read: 't'"); CHECK_THROWS_WITH(parser_helper("tr"), - "[json.exception.parse_error.101] parse error at 3: syntax error - invalid literal; last read: 'tr'"); + "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid literal; last read: 'tr'"); CHECK_THROWS_WITH(parser_helper("tru"), - "[json.exception.parse_error.101] parse error at 4: syntax error - invalid literal; last read: 'tru'"); + "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid literal; last read: 'tru'"); CHECK_THROWS_WITH(parser_helper("trud"), - "[json.exception.parse_error.101] parse error at 4: syntax error - invalid literal; last read: 'trud'"); + "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid literal; last read: 'trud'"); CHECK_THROWS_WITH(parser_helper("truf"), - "[json.exception.parse_error.101] parse error at 4: syntax error - invalid literal; last read: 'truf'"); + "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid literal; last read: 'truf'"); // unexpected end of false CHECK_THROWS_AS(parser_helper("f"), json::parse_error&); @@ -990,17 +990,17 @@ TEST_CASE("parser class") CHECK_THROWS_AS(parser_helper("falsd"), json::parse_error&); CHECK_THROWS_AS(parser_helper("falsf"), json::parse_error&); CHECK_THROWS_WITH(parser_helper("f"), - "[json.exception.parse_error.101] parse error at 2: syntax error - invalid literal; last read: 'f'"); + "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid literal; last read: 'f'"); CHECK_THROWS_WITH(parser_helper("fa"), - "[json.exception.parse_error.101] parse error at 3: syntax error - invalid literal; last read: 'fa'"); + "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid literal; last read: 'fa'"); CHECK_THROWS_WITH(parser_helper("fal"), - "[json.exception.parse_error.101] parse error at 4: syntax error - invalid literal; last read: 'fal'"); + "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid literal; last read: 'fal'"); CHECK_THROWS_WITH(parser_helper("fals"), - "[json.exception.parse_error.101] parse error at 5: syntax error - invalid literal; last read: 'fals'"); + "[json.exception.parse_error.101] parse error at line 1, column 5: syntax error while parsing value - invalid literal; last read: 'fals'"); CHECK_THROWS_WITH(parser_helper("falsd"), - "[json.exception.parse_error.101] parse error at 5: syntax error - invalid literal; last read: 'falsd'"); + "[json.exception.parse_error.101] parse error at line 1, column 5: syntax error while parsing value - invalid literal; last read: 'falsd'"); CHECK_THROWS_WITH(parser_helper("falsf"), - "[json.exception.parse_error.101] parse error at 5: syntax error - invalid literal; last read: 'falsf'"); + "[json.exception.parse_error.101] parse error at line 1, column 5: syntax error while parsing value - invalid literal; last read: 'falsf'"); // missing/unexpected end of array CHECK_THROWS_AS(parser_helper("["), json::parse_error&); @@ -1009,15 +1009,15 @@ TEST_CASE("parser class") CHECK_THROWS_AS(parser_helper("[1,]"), json::parse_error&); CHECK_THROWS_AS(parser_helper("]"), json::parse_error&); CHECK_THROWS_WITH(parser_helper("["), - "[json.exception.parse_error.101] parse error at 2: syntax error - unexpected end of input; expected '[', '{', or a literal"); + "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal"); CHECK_THROWS_WITH(parser_helper("[1"), - "[json.exception.parse_error.101] parse error at 3: syntax error - unexpected end of input; expected ']'"); + "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing array - unexpected end of input; expected ']'"); CHECK_THROWS_WITH(parser_helper("[1,"), - "[json.exception.parse_error.101] parse error at 4: syntax error - unexpected end of input; expected '[', '{', or a literal"); + "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal"); CHECK_THROWS_WITH(parser_helper("[1,]"), - "[json.exception.parse_error.101] parse error at 4: syntax error - unexpected ']'; expected '[', '{', or a literal"); + "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - unexpected ']'; expected '[', '{', or a literal"); CHECK_THROWS_WITH(parser_helper("]"), - "[json.exception.parse_error.101] parse error at 1: syntax error - unexpected ']'; expected '[', '{', or a literal"); + "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - unexpected ']'; expected '[', '{', or a literal"); // missing/unexpected end of object CHECK_THROWS_AS(parser_helper("{"), json::parse_error&); @@ -1027,17 +1027,17 @@ TEST_CASE("parser class") CHECK_THROWS_AS(parser_helper("{\"foo\":1,}"), json::parse_error&); CHECK_THROWS_AS(parser_helper("}"), json::parse_error&); CHECK_THROWS_WITH(parser_helper("{"), - "[json.exception.parse_error.101] parse error at 2: syntax error - unexpected end of input; expected string literal"); + "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing object key - unexpected end of input; expected string literal"); CHECK_THROWS_WITH(parser_helper("{\"foo\""), - "[json.exception.parse_error.101] parse error at 7: syntax error - unexpected end of input; expected ':'"); + "[json.exception.parse_error.101] parse error at line 1, column 7: syntax error while parsing object separator - unexpected end of input; expected ':'"); CHECK_THROWS_WITH(parser_helper("{\"foo\":"), - "[json.exception.parse_error.101] parse error at 8: syntax error - unexpected end of input; expected '[', '{', or a literal"); + "[json.exception.parse_error.101] parse error at line 1, column 8: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal"); CHECK_THROWS_WITH(parser_helper("{\"foo\":}"), - "[json.exception.parse_error.101] parse error at 8: syntax error - unexpected '}'; expected '[', '{', or a literal"); + "[json.exception.parse_error.101] parse error at line 1, column 8: syntax error while parsing value - unexpected '}'; expected '[', '{', or a literal"); CHECK_THROWS_WITH(parser_helper("{\"foo\":1,}"), - "[json.exception.parse_error.101] parse error at 10: syntax error - unexpected '}'; expected string literal"); + "[json.exception.parse_error.101] parse error at line 1, column 10: syntax error while parsing object key - unexpected '}'; expected string literal"); CHECK_THROWS_WITH(parser_helper("}"), - "[json.exception.parse_error.101] parse error at 1: syntax error - unexpected '}'; expected '[', '{', or a literal"); + "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - unexpected '}'; expected '[', '{', or a literal"); // missing/unexpected end of string CHECK_THROWS_AS(parser_helper("\""), json::parse_error&); @@ -1051,25 +1051,25 @@ TEST_CASE("parser class") CHECK_THROWS_AS(parser_helper("\"\\u01"), json::parse_error&); CHECK_THROWS_AS(parser_helper("\"\\u012"), json::parse_error&); CHECK_THROWS_WITH(parser_helper("\""), - "[json.exception.parse_error.101] parse error at 2: syntax error - invalid string: missing closing quote; last read: '\"'"); + "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: missing closing quote; last read: '\"'"); CHECK_THROWS_WITH(parser_helper("\"\\\""), - "[json.exception.parse_error.101] parse error at 4: syntax error - invalid string: missing closing quote; last read: '\"\\\"'"); + "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid string: missing closing quote; last read: '\"\\\"'"); CHECK_THROWS_WITH(parser_helper("\"\\u\""), - "[json.exception.parse_error.101] parse error at 4: syntax error - invalid string: '\\u' must be followed by 4 hex digits; last read: '\"\\u\"'"); + "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid string: '\\u' must be followed by 4 hex digits; last read: '\"\\u\"'"); CHECK_THROWS_WITH(parser_helper("\"\\u0\""), - "[json.exception.parse_error.101] parse error at 5: syntax error - invalid string: '\\u' must be followed by 4 hex digits; last read: '\"\\u0\"'"); + "[json.exception.parse_error.101] parse error at line 1, column 5: syntax error while parsing value - invalid string: '\\u' must be followed by 4 hex digits; last read: '\"\\u0\"'"); CHECK_THROWS_WITH(parser_helper("\"\\u01\""), - "[json.exception.parse_error.101] parse error at 6: syntax error - invalid string: '\\u' must be followed by 4 hex digits; last read: '\"\\u01\"'"); + "[json.exception.parse_error.101] parse error at line 1, column 6: syntax error while parsing value - invalid string: '\\u' must be followed by 4 hex digits; last read: '\"\\u01\"'"); CHECK_THROWS_WITH(parser_helper("\"\\u012\""), - "[json.exception.parse_error.101] parse error at 7: syntax error - invalid string: '\\u' must be followed by 4 hex digits; last read: '\"\\u012\"'"); + "[json.exception.parse_error.101] parse error at line 1, column 7: syntax error while parsing value - invalid string: '\\u' must be followed by 4 hex digits; last read: '\"\\u012\"'"); CHECK_THROWS_WITH(parser_helper("\"\\u"), - "[json.exception.parse_error.101] parse error at 4: syntax error - invalid string: '\\u' must be followed by 4 hex digits; last read: '\"\\u'"); + "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid string: '\\u' must be followed by 4 hex digits; last read: '\"\\u'"); CHECK_THROWS_WITH(parser_helper("\"\\u0"), - "[json.exception.parse_error.101] parse error at 5: syntax error - invalid string: '\\u' must be followed by 4 hex digits; last read: '\"\\u0'"); + "[json.exception.parse_error.101] parse error at line 1, column 5: syntax error while parsing value - invalid string: '\\u' must be followed by 4 hex digits; last read: '\"\\u0'"); CHECK_THROWS_WITH(parser_helper("\"\\u01"), - "[json.exception.parse_error.101] parse error at 6: syntax error - invalid string: '\\u' must be followed by 4 hex digits; last read: '\"\\u01'"); + "[json.exception.parse_error.101] parse error at line 1, column 6: syntax error while parsing value - invalid string: '\\u' must be followed by 4 hex digits; last read: '\"\\u01'"); CHECK_THROWS_WITH(parser_helper("\"\\u012"), - "[json.exception.parse_error.101] parse error at 7: syntax error - invalid string: '\\u' must be followed by 4 hex digits; last read: '\"\\u012'"); + "[json.exception.parse_error.101] parse error at line 1, column 7: syntax error while parsing value - invalid string: '\\u' must be followed by 4 hex digits; last read: '\"\\u012'"); // invalid escapes for (int c = 1; c < 128; ++c) @@ -1106,7 +1106,7 @@ TEST_CASE("parser class") if (c > 0x1f) { CHECK_THROWS_WITH(parser_helper(s.c_str()), - "[json.exception.parse_error.101] parse error at 3: syntax error - invalid string: forbidden character after backslash; last read: '\"\\" + std::string(1, static_cast(c)) + "'"); + "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid string: forbidden character after backslash; last read: '\"\\" + std::string(1, static_cast(c)) + "'"); } break; } @@ -1182,7 +1182,7 @@ TEST_CASE("parser class") if (c > 0x1f) { CHECK_THROWS_WITH(parser_helper(s1.c_str()), - "[json.exception.parse_error.101] parse error at 7: syntax error - invalid string: '\\u' must be followed by 4 hex digits; last read: '" + s1.substr(0, 7) + "'"); + "[json.exception.parse_error.101] parse error at line 1, column 7: syntax error while parsing value - invalid string: '\\u' must be followed by 4 hex digits; last read: '" + s1.substr(0, 7) + "'"); } CAPTURE(s2); @@ -1191,7 +1191,7 @@ TEST_CASE("parser class") if (c > 0x1f) { CHECK_THROWS_WITH(parser_helper(s2.c_str()), - "[json.exception.parse_error.101] parse error at 6: syntax error - invalid string: '\\u' must be followed by 4 hex digits; last read: '" + s2.substr(0, 6) + "'"); + "[json.exception.parse_error.101] parse error at line 1, column 6: syntax error while parsing value - invalid string: '\\u' must be followed by 4 hex digits; last read: '" + s2.substr(0, 6) + "'"); } CAPTURE(s3); @@ -1200,7 +1200,7 @@ TEST_CASE("parser class") if (c > 0x1f) { CHECK_THROWS_WITH(parser_helper(s3.c_str()), - "[json.exception.parse_error.101] parse error at 5: syntax error - invalid string: '\\u' must be followed by 4 hex digits; last read: '" + s3.substr(0, 5) + "'"); + "[json.exception.parse_error.101] parse error at line 1, column 5: syntax error while parsing value - invalid string: '\\u' must be followed by 4 hex digits; last read: '" + s3.substr(0, 5) + "'"); } CAPTURE(s4); @@ -1209,7 +1209,7 @@ TEST_CASE("parser class") if (c > 0x1f) { CHECK_THROWS_WITH(parser_helper(s4.c_str()), - "[json.exception.parse_error.101] parse error at 4: syntax error - invalid string: '\\u' must be followed by 4 hex digits; last read: '" + s4.substr(0, 4) + "'"); + "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid string: '\\u' must be followed by 4 hex digits; last read: '" + s4.substr(0, 4) + "'"); } } } @@ -1218,17 +1218,17 @@ TEST_CASE("parser class") // missing part of a surrogate pair CHECK_THROWS_AS(json::parse("\"\\uD80C\""), json::parse_error&); CHECK_THROWS_WITH(json::parse("\"\\uD80C\""), - "[json.exception.parse_error.101] parse error at 8: syntax error - invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF; last read: '\"\\uD80C\"'"); + "[json.exception.parse_error.101] parse error at line 1, column 8: syntax error while parsing value - invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF; last read: '\"\\uD80C\"'"); // invalid surrogate pair CHECK_THROWS_AS(json::parse("\"\\uD80C\\uD80C\""), json::parse_error&); CHECK_THROWS_AS(json::parse("\"\\uD80C\\u0000\""), json::parse_error&); CHECK_THROWS_AS(json::parse("\"\\uD80C\\uFFFF\""), json::parse_error&); CHECK_THROWS_WITH(json::parse("\"\\uD80C\\uD80C\""), - "[json.exception.parse_error.101] parse error at 13: syntax error - invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF; last read: '\"\\uD80C\\uD80C'"); + "[json.exception.parse_error.101] parse error at line 1, column 13: syntax error while parsing value - invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF; last read: '\"\\uD80C\\uD80C'"); CHECK_THROWS_WITH(json::parse("\"\\uD80C\\u0000\""), - "[json.exception.parse_error.101] parse error at 13: syntax error - invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF; last read: '\"\\uD80C\\u0000'"); + "[json.exception.parse_error.101] parse error at line 1, column 13: syntax error while parsing value - invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF; last read: '\"\\uD80C\\u0000'"); CHECK_THROWS_WITH(json::parse("\"\\uD80C\\uFFFF\""), - "[json.exception.parse_error.101] parse error at 13: syntax error - invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF; last read: '\"\\uD80C\\uFFFF'"); + "[json.exception.parse_error.101] parse error at line 1, column 13: syntax error while parsing value - invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF; last read: '\"\\uD80C\\uFFFF'"); } SECTION("parse errors (accept)") @@ -1292,6 +1292,9 @@ TEST_CASE("parser class") CHECK(accept_helper("\"\\u01") == false); CHECK(accept_helper("\"\\u012") == false); + // unget of newline + CHECK(parser_helper("\n123\n") == 123); + // invalid escapes for (int c = 1; c < 128; ++c) { @@ -1419,11 +1422,11 @@ TEST_CASE("parser class") // test case to make sure no comma preceeds the first key CHECK_THROWS_AS(parser_helper("{,\"key\": false}"), json::parse_error&); CHECK_THROWS_WITH(parser_helper("{,\"key\": false}"), - "[json.exception.parse_error.101] parse error at 2: syntax error - unexpected ','; expected string literal"); + "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing object key - unexpected ','; expected string literal"); // test case to make sure an object is properly closed CHECK_THROWS_AS(parser_helper("[{\"key\": false true]"), json::parse_error&); CHECK_THROWS_WITH(parser_helper("[{\"key\": false true]"), - "[json.exception.parse_error.101] parse error at 19: syntax error - unexpected true literal; expected '}'"); + "[json.exception.parse_error.101] parse error at line 1, column 19: syntax error while parsing object - unexpected true literal; expected '}'"); // test case to make sure the callback is properly evaluated after reading a key { @@ -1674,7 +1677,7 @@ TEST_CASE("parser class") CHECK_THROWS_AS(json::parse("{\"foo\": true:", cb), json::parse_error&); CHECK_THROWS_WITH(json::parse("{\"foo\": true:", cb), - "[json.exception.parse_error.101] parse error at 13: syntax error - unexpected ':'; expected '}'"); + "[json.exception.parse_error.101] parse error at line 1, column 13: syntax error while parsing object - unexpected ':'; expected '}'"); CHECK_THROWS_AS(json::parse("1.18973e+4932", cb), json::out_of_range&); CHECK_THROWS_WITH(json::parse("1.18973e+4932", cb), diff --git a/test/src/unit-deserialization.cpp b/test/src/unit-deserialization.cpp index f6c75d11..8610cebd 100644 --- a/test/src/unit-deserialization.cpp +++ b/test/src/unit-deserialization.cpp @@ -267,7 +267,7 @@ TEST_CASE("deserialization") ss5 << "[\"foo\",1,2,3,false,{\"one\":1}"; CHECK_THROWS_AS(json::parse(ss1), json::parse_error&); CHECK_THROWS_WITH(json::parse(ss2), - "[json.exception.parse_error.101] parse error at 29: syntax error - unexpected end of input; expected ']'"); + "[json.exception.parse_error.101] parse error at line 1, column 29: syntax error while parsing array - unexpected end of input; expected ']'"); CHECK(not json::accept(ss3)); json j_error; @@ -291,7 +291,7 @@ TEST_CASE("deserialization") json::string_t s = "[\"foo\",1,2,3,false,{\"one\":1}"; CHECK_THROWS_AS(json::parse(s), json::parse_error&); CHECK_THROWS_WITH(json::parse(s), - "[json.exception.parse_error.101] parse error at 29: syntax error - unexpected end of input; expected ']'"); + "[json.exception.parse_error.101] parse error at line 1, column 29: syntax error while parsing array - unexpected end of input; expected ']'"); CHECK(not json::accept(s)); json j_error; @@ -318,7 +318,7 @@ TEST_CASE("deserialization") json j; CHECK_THROWS_AS(j << ss1, json::parse_error&); CHECK_THROWS_WITH(j << ss2, - "[json.exception.parse_error.101] parse error at 29: syntax error - unexpected end of input; expected ']'"); + "[json.exception.parse_error.101] parse error at line 1, column 29: syntax error while parsing array - unexpected end of input; expected ']'"); } SECTION("operator>>") @@ -329,14 +329,14 @@ TEST_CASE("deserialization") json j; CHECK_THROWS_AS(ss1 >> j, json::parse_error&); CHECK_THROWS_WITH(ss2 >> j, - "[json.exception.parse_error.101] parse error at 29: syntax error - unexpected end of input; expected ']'"); + "[json.exception.parse_error.101] parse error at line 1, column 29: syntax error while parsing array - unexpected end of input; expected ']'"); } SECTION("user-defined string literal") { 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, - "[json.exception.parse_error.101] parse error at 29: syntax error - unexpected end of input; expected ']'"); + "[json.exception.parse_error.101] parse error at line 1, column 29: syntax error while parsing array - unexpected end of input; expected ']'"); } } @@ -612,7 +612,7 @@ TEST_CASE("deserialization") uint8_t v[] = {'\"', 0x7F, 0xDF, 0x7F}; CHECK_THROWS_AS(json::parse(std::begin(v), std::end(v)), json::parse_error&); CHECK_THROWS_WITH(json::parse(std::begin(v), std::end(v)), - "[json.exception.parse_error.101] parse error at 4: syntax error - invalid string: ill-formed UTF-8 byte; last read: '\"\x7f\xdf\x7f'"); + "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid string: ill-formed UTF-8 byte; last read: '\"\x7f\xdf\x7f'"); CHECK(not json::accept(std::begin(v), std::end(v))); json j_error; @@ -799,11 +799,11 @@ TEST_CASE("deserialization") { CHECK_THROWS_AS(json::parse(bom), json::parse_error&); CHECK_THROWS_WITH(json::parse(bom), - "[json.exception.parse_error.101] parse error at 4: syntax error - unexpected end of input; expected '[', '{', or a literal"); + "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal"); CHECK_THROWS_AS(json::parse(std::istringstream(bom)), json::parse_error&); CHECK_THROWS_WITH(json::parse(std::istringstream(bom)), - "[json.exception.parse_error.101] parse error at 4: syntax error - unexpected end of input; expected '[', '{', or a literal"); + "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal"); SaxEventLogger l; CHECK(not json::sax_parse(bom, &l)); @@ -838,11 +838,11 @@ TEST_CASE("deserialization") { CHECK_THROWS_AS(json::parse(bom.substr(0, 2)), json::parse_error&); CHECK_THROWS_WITH(json::parse(bom.substr(0, 2)), - "[json.exception.parse_error.101] parse error at 3: syntax error - invalid BOM; must be 0xEF 0xBB 0xBF if given; last read: '\xEF\xBB'"); + "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid BOM; must be 0xEF 0xBB 0xBF if given; last read: '\xEF\xBB'"); CHECK_THROWS_AS(json::parse(std::istringstream(bom.substr(0, 2))), json::parse_error&); CHECK_THROWS_WITH(json::parse(std::istringstream(bom.substr(0, 2))), - "[json.exception.parse_error.101] parse error at 3: syntax error - invalid BOM; must be 0xEF 0xBB 0xBF if given; last read: '\xEF\xBB'"); + "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid BOM; must be 0xEF 0xBB 0xBF if given; last read: '\xEF\xBB'"); SaxEventLogger l1, l2; CHECK(not json::sax_parse(std::istringstream(bom.substr(0, 2)), &l1)); @@ -863,11 +863,11 @@ TEST_CASE("deserialization") { CHECK_THROWS_AS(json::parse(bom.substr(0, 1)), json::parse_error&); CHECK_THROWS_WITH(json::parse(bom.substr(0, 1)), - "[json.exception.parse_error.101] parse error at 2: syntax error - invalid BOM; must be 0xEF 0xBB 0xBF if given; last read: '\xEF'"); + "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid BOM; must be 0xEF 0xBB 0xBF if given; last read: '\xEF'"); CHECK_THROWS_AS(json::parse(std::istringstream(bom.substr(0, 1))), json::parse_error&); CHECK_THROWS_WITH(json::parse(std::istringstream(bom.substr(0, 1))), - "[json.exception.parse_error.101] parse error at 2: syntax error - invalid BOM; must be 0xEF 0xBB 0xBF if given; last read: '\xEF'"); + "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid BOM; must be 0xEF 0xBB 0xBF if given; last read: '\xEF'"); SaxEventLogger l1, l2; CHECK(not json::sax_parse(std::istringstream(bom.substr(0, 1)), &l1)); diff --git a/test/src/unit-json_pointer.cpp b/test/src/unit-json_pointer.cpp index d02bd939..7f5605d9 100644 --- a/test/src/unit-json_pointer.cpp +++ b/test/src/unit-json_pointer.cpp @@ -39,7 +39,7 @@ TEST_CASE("JSON pointers") { CHECK_THROWS_AS(json::json_pointer("foo"), json::parse_error&); CHECK_THROWS_WITH(json::json_pointer("foo"), - "[json.exception.parse_error.107] parse error at 1: JSON pointer must be empty or begin with '/' - was: 'foo'"); + "[json.exception.parse_error.107] parse error at byte 1: JSON pointer must be empty or begin with '/' - was: 'foo'"); CHECK_THROWS_AS(json::json_pointer("/~~"), json::parse_error&); CHECK_THROWS_WITH(json::json_pointer("/~~"), diff --git a/test/src/unit-msgpack.cpp b/test/src/unit-msgpack.cpp index 0848ef08..f75cedce 100644 --- a/test/src/unit-msgpack.cpp +++ b/test/src/unit-msgpack.cpp @@ -1124,7 +1124,7 @@ TEST_CASE("MessagePack") { CHECK_THROWS_AS(json::from_msgpack(std::vector()), json::parse_error&); CHECK_THROWS_WITH(json::from_msgpack(std::vector()), - "[json.exception.parse_error.110] parse error at 1: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 1: unexpected end of input"); CHECK(json::from_msgpack(std::vector(), true, false).is_discarded()); } @@ -1151,43 +1151,43 @@ TEST_CASE("MessagePack") CHECK_THROWS_AS(json::from_msgpack(std::vector({0x81, 0xa1, 0x61})), json::parse_error&); CHECK_THROWS_WITH(json::from_msgpack(std::vector({0x87})), - "[json.exception.parse_error.110] parse error at 2: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 2: unexpected end of input"); CHECK_THROWS_WITH(json::from_msgpack(std::vector({0xcc})), - "[json.exception.parse_error.110] parse error at 2: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 2: unexpected end of input"); CHECK_THROWS_WITH(json::from_msgpack(std::vector({0xcd})), - "[json.exception.parse_error.110] parse error at 2: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 2: unexpected end of input"); CHECK_THROWS_WITH(json::from_msgpack(std::vector({0xcd, 0x00})), - "[json.exception.parse_error.110] parse error at 3: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 3: unexpected end of input"); CHECK_THROWS_WITH(json::from_msgpack(std::vector({0xce})), - "[json.exception.parse_error.110] parse error at 2: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 2: unexpected end of input"); CHECK_THROWS_WITH(json::from_msgpack(std::vector({0xce, 0x00})), - "[json.exception.parse_error.110] parse error at 3: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 3: unexpected end of input"); CHECK_THROWS_WITH(json::from_msgpack(std::vector({0xce, 0x00, 0x00})), - "[json.exception.parse_error.110] parse error at 4: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 4: unexpected end of input"); CHECK_THROWS_WITH(json::from_msgpack(std::vector({0xce, 0x00, 0x00, 0x00})), - "[json.exception.parse_error.110] parse error at 5: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 5: unexpected end of input"); CHECK_THROWS_WITH(json::from_msgpack(std::vector({0xcf})), - "[json.exception.parse_error.110] parse error at 2: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 2: unexpected end of input"); CHECK_THROWS_WITH(json::from_msgpack(std::vector({0xcf, 0x00})), - "[json.exception.parse_error.110] parse error at 3: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 3: unexpected end of input"); CHECK_THROWS_WITH(json::from_msgpack(std::vector({0xcf, 0x00, 0x00})), - "[json.exception.parse_error.110] parse error at 4: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 4: unexpected end of input"); CHECK_THROWS_WITH(json::from_msgpack(std::vector({0xcf, 0x00, 0x00, 0x00})), - "[json.exception.parse_error.110] parse error at 5: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 5: unexpected end of input"); CHECK_THROWS_WITH(json::from_msgpack(std::vector({0xcf, 0x00, 0x00, 0x00, 0x00})), - "[json.exception.parse_error.110] parse error at 6: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 6: unexpected end of input"); CHECK_THROWS_WITH(json::from_msgpack(std::vector({0xcf, 0x00, 0x00, 0x00, 0x00, 0x00})), - "[json.exception.parse_error.110] parse error at 7: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 7: unexpected end of input"); CHECK_THROWS_WITH(json::from_msgpack(std::vector({0xcf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})), - "[json.exception.parse_error.110] parse error at 8: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 8: unexpected end of input"); CHECK_THROWS_WITH(json::from_msgpack(std::vector({0xcf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})), - "[json.exception.parse_error.110] parse error at 9: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 9: unexpected end of input"); CHECK_THROWS_WITH(json::from_msgpack(std::vector({0xa5, 0x68, 0x65})), - "[json.exception.parse_error.110] parse error at 4: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 4: unexpected end of input"); CHECK_THROWS_WITH(json::from_msgpack(std::vector({0x92, 0x01})), - "[json.exception.parse_error.110] parse error at 3: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 3: unexpected end of input"); CHECK_THROWS_WITH(json::from_msgpack(std::vector({0x81, 0xa1, 0x61})), - "[json.exception.parse_error.110] parse error at 4: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 4: unexpected end of input"); CHECK(json::from_msgpack(std::vector({0x87}), true, false).is_discarded()); CHECK(json::from_msgpack(std::vector({0xcc}), true, false).is_discarded()); @@ -1216,12 +1216,12 @@ TEST_CASE("MessagePack") { CHECK_THROWS_AS(json::from_msgpack(std::vector({0xc1})), json::parse_error&); CHECK_THROWS_WITH(json::from_msgpack(std::vector({0xc1})), - "[json.exception.parse_error.112] parse error at 1: error reading MessagePack; last byte: 0xC1"); + "[json.exception.parse_error.112] parse error at byte 1: error reading MessagePack; last byte: 0xC1"); CHECK(json::from_msgpack(std::vector({0xc6}), true, false).is_discarded()); CHECK_THROWS_AS(json::from_msgpack(std::vector({0xc6})), json::parse_error&); CHECK_THROWS_WITH(json::from_msgpack(std::vector({0xc6})), - "[json.exception.parse_error.112] parse error at 1: error reading MessagePack; last byte: 0xC6"); + "[json.exception.parse_error.112] parse error at byte 1: error reading MessagePack; last byte: 0xC6"); CHECK(json::from_msgpack(std::vector({0xc6}), true, false).is_discarded()); } @@ -1249,7 +1249,7 @@ TEST_CASE("MessagePack") { CHECK_THROWS_AS(json::from_msgpack(std::vector({0x81, 0xff, 0x01})), json::parse_error&); CHECK_THROWS_WITH(json::from_msgpack(std::vector({0x81, 0xff, 0x01})), - "[json.exception.parse_error.113] parse error at 2: expected a MessagePack string; last byte: 0xFF"); + "[json.exception.parse_error.113] parse error at byte 2: expected a MessagePack string; last byte: 0xFF"); CHECK(json::from_msgpack(std::vector({0x81, 0xff, 0x01}), true, false).is_discarded()); } @@ -1266,7 +1266,7 @@ TEST_CASE("MessagePack") { CHECK_THROWS_AS(json::from_msgpack(vec), json::parse_error&); CHECK_THROWS_WITH(json::from_msgpack(vec), - "[json.exception.parse_error.110] parse error at 2: expected end of input"); + "[json.exception.parse_error.110] parse error at byte 2: expected end of input"); CHECK(json::from_msgpack(vec, true, false).is_discarded()); } } diff --git a/test/src/unit-regression.cpp b/test/src/unit-regression.cpp index 6b9fd957..fe4913cb 100644 --- a/test/src/unit-regression.cpp +++ b/test/src/unit-regression.cpp @@ -725,7 +725,7 @@ TEST_CASE("regression tests") { std::ifstream f("file_not_found.json"); CHECK_THROWS_AS(json::parse(f), json::parse_error&); - CHECK_THROWS_WITH(json::parse(f), "[json.exception.parse_error.101] parse error at 1: syntax error - unexpected end of input; expected '[', '{', or a literal"); + CHECK_THROWS_WITH(json::parse(f), "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal"); } SECTION("issue #367 - calling stream at EOF") @@ -741,7 +741,7 @@ TEST_CASE("regression tests") // a parse error because of the EOF. CHECK_THROWS_AS(ss >> j, json::parse_error&); CHECK_THROWS_WITH(ss >> j, - "[json.exception.parse_error.101] parse error at 1: syntax error - unexpected end of input; expected '[', '{', or a literal"); + "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal"); } SECTION("issue #367 - behavior of operator>> should more closely resemble that of built-in overloads") @@ -752,7 +752,7 @@ TEST_CASE("regression tests") json j; CHECK_THROWS_AS(ss >> j, json::parse_error&); CHECK_THROWS_WITH(ss >> j, - "[json.exception.parse_error.101] parse error at 1: syntax error - unexpected end of input; expected '[', '{', or a literal"); + "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal"); } SECTION("(whitespace)") @@ -762,7 +762,7 @@ TEST_CASE("regression tests") json j; CHECK_THROWS_AS(ss >> j, json::parse_error&); CHECK_THROWS_WITH(ss >> j, - "[json.exception.parse_error.101] parse error at 1: syntax error - unexpected end of input; expected '[', '{', or a literal"); + "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal"); } SECTION("one value") @@ -775,7 +775,7 @@ TEST_CASE("regression tests") CHECK_THROWS_AS(ss >> j, json::parse_error&); CHECK_THROWS_WITH(ss >> j, - "[json.exception.parse_error.101] parse error at 1: syntax error - unexpected end of input; expected '[', '{', or a literal"); + "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal"); } SECTION("one value + whitespace") @@ -788,7 +788,7 @@ TEST_CASE("regression tests") CHECK_THROWS_AS(ss >> j, json::parse_error&); CHECK_THROWS_WITH(ss >> j, - "[json.exception.parse_error.101] parse error at 1: syntax error - unexpected end of input; expected '[', '{', or a literal"); + "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal"); } SECTION("whitespace + one value") @@ -801,7 +801,7 @@ TEST_CASE("regression tests") CHECK_THROWS_AS(ss >> j, json::parse_error&); CHECK_THROWS_WITH(ss >> j, - "[json.exception.parse_error.101] parse error at 1: syntax error - unexpected end of input; expected '[', '{', or a literal"); + "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal"); } SECTION("three values") @@ -818,7 +818,7 @@ TEST_CASE("regression tests") CHECK_THROWS_AS(ss >> j, json::parse_error&); CHECK_THROWS_WITH(ss >> j, - "[json.exception.parse_error.101] parse error at 1: syntax error - unexpected end of input; expected '[', '{', or a literal"); + "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal"); } SECTION("literals without whitespace") @@ -837,7 +837,7 @@ TEST_CASE("regression tests") CHECK_THROWS_AS(ss >> j, json::parse_error&); CHECK_THROWS_WITH(ss >> j, - "[json.exception.parse_error.101] parse error at 1: syntax error - unexpected end of input; expected '[', '{', or a literal"); + "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal"); } SECTION("example from #529") @@ -852,7 +852,7 @@ TEST_CASE("regression tests") CHECK_THROWS_AS(ss >> j, json::parse_error&); CHECK_THROWS_WITH(ss >> j, - "[json.exception.parse_error.101] parse error at 1: syntax error - unexpected end of input; expected '[', '{', or a literal"); + "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal"); } SECTION("second example from #529") @@ -922,7 +922,7 @@ TEST_CASE("regression tests") std::vector vec {0x65, 0xf5, 0x0a, 0x48, 0x21}; CHECK_THROWS_AS(json::from_cbor(vec), json::parse_error&); CHECK_THROWS_WITH(json::from_cbor(vec), - "[json.exception.parse_error.110] parse error at 6: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 6: unexpected end of input"); } SECTION("issue #407 - Heap-buffer-overflow (OSS-Fuzz issue 343)") @@ -931,31 +931,31 @@ TEST_CASE("regression tests") std::vector vec1 {0xcb, 0x8f, 0x0a}; CHECK_THROWS_AS(json::from_msgpack(vec1), json::parse_error&); CHECK_THROWS_WITH(json::from_msgpack(vec1), - "[json.exception.parse_error.110] parse error at 4: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 4: unexpected end of input"); // related test case: incomplete float32 std::vector vec2 {0xca, 0x8f, 0x0a}; CHECK_THROWS_AS(json::from_msgpack(vec2), json::parse_error&); CHECK_THROWS_WITH(json::from_msgpack(vec2), - "[json.exception.parse_error.110] parse error at 4: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 4: unexpected end of input"); // related test case: incomplete Half-Precision Float (CBOR) std::vector vec3 {0xf9, 0x8f}; CHECK_THROWS_AS(json::from_cbor(vec3), json::parse_error&); CHECK_THROWS_WITH(json::from_cbor(vec3), - "[json.exception.parse_error.110] parse error at 3: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 3: unexpected end of input"); // related test case: incomplete Single-Precision Float (CBOR) std::vector vec4 {0xfa, 0x8f, 0x0a}; CHECK_THROWS_AS(json::from_cbor(vec4), json::parse_error&); CHECK_THROWS_WITH(json::from_cbor(vec4), - "[json.exception.parse_error.110] parse error at 4: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 4: unexpected end of input"); // related test case: incomplete Double-Precision Float (CBOR) std::vector vec5 {0xfb, 0x8f, 0x0a}; CHECK_THROWS_AS(json::from_cbor(vec5), json::parse_error&); CHECK_THROWS_WITH(json::from_cbor(vec5), - "[json.exception.parse_error.110] parse error at 4: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 4: unexpected end of input"); } SECTION("issue #408 - Heap-buffer-overflow (OSS-Fuzz issue 344)") @@ -964,7 +964,7 @@ TEST_CASE("regression tests") std::vector vec1 {0x87}; CHECK_THROWS_AS(json::from_msgpack(vec1), json::parse_error&); CHECK_THROWS_WITH(json::from_msgpack(vec1), - "[json.exception.parse_error.110] parse error at 2: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 2: unexpected end of input"); // more test cases for MessagePack for (auto b : @@ -998,10 +998,10 @@ TEST_CASE("regression tests") std::vector vec2; CHECK_THROWS_AS(json::from_cbor(vec2), json::parse_error&); CHECK_THROWS_WITH(json::from_cbor(vec2), - "[json.exception.parse_error.110] parse error at 1: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 1: unexpected end of input"); CHECK_THROWS_AS(json::from_msgpack(vec2), json::parse_error&); CHECK_THROWS_WITH(json::from_msgpack(vec2), - "[json.exception.parse_error.110] parse error at 1: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 1: unexpected end of input"); } SECTION("issue #411 - Heap-buffer-overflow (OSS-Fuzz issue 366)") @@ -1010,19 +1010,19 @@ TEST_CASE("regression tests") std::vector vec1 {0x7f}; CHECK_THROWS_AS(json::from_cbor(vec1), json::parse_error&); CHECK_THROWS_WITH(json::from_cbor(vec1), - "[json.exception.parse_error.110] parse error at 2: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 2: unexpected end of input"); // related test case: empty array (indefinite length) std::vector vec2 {0x9f}; CHECK_THROWS_AS(json::from_cbor(vec2), json::parse_error&); CHECK_THROWS_WITH(json::from_cbor(vec2), - "[json.exception.parse_error.110] parse error at 2: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 2: unexpected end of input"); // related test case: empty map (indefinite length) std::vector vec3 {0xbf}; CHECK_THROWS_AS(json::from_cbor(vec3), json::parse_error&); CHECK_THROWS_WITH(json::from_cbor(vec3), - "[json.exception.parse_error.110] parse error at 2: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 2: unexpected end of input"); } SECTION("issue #412 - Heap-buffer-overflow (OSS-Fuzz issue 367)") @@ -1050,25 +1050,25 @@ TEST_CASE("regression tests") }; CHECK_THROWS_AS(json::from_cbor(vec), json::parse_error&); CHECK_THROWS_WITH(json::from_cbor(vec), - "[json.exception.parse_error.113] parse error at 2: expected a CBOR string; last byte: 0x98"); + "[json.exception.parse_error.113] parse error at byte 2: expected a CBOR string; last byte: 0x98"); // related test case: nonempty UTF-8 string (indefinite length) std::vector vec1 {0x7f, 0x61, 0x61}; CHECK_THROWS_AS(json::from_cbor(vec1), json::parse_error&); CHECK_THROWS_WITH(json::from_cbor(vec1), - "[json.exception.parse_error.110] parse error at 4: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 4: unexpected end of input"); // related test case: nonempty array (indefinite length) std::vector vec2 {0x9f, 0x01}; CHECK_THROWS_AS(json::from_cbor(vec2), json::parse_error&); CHECK_THROWS_WITH(json::from_cbor(vec2), - "[json.exception.parse_error.110] parse error at 3: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 3: unexpected end of input"); // related test case: nonempty map (indefinite length) std::vector vec3 {0xbf, 0x61, 0x61, 0x01}; CHECK_THROWS_AS(json::from_cbor(vec3), json::parse_error&); CHECK_THROWS_WITH(json::from_cbor(vec3), - "[json.exception.parse_error.110] parse error at 5: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 5: unexpected end of input"); } SECTION("issue #414 - compare with literal 0)") @@ -1103,7 +1103,7 @@ TEST_CASE("regression tests") }; CHECK_THROWS_AS(json::from_cbor(vec1), json::parse_error&); CHECK_THROWS_WITH(json::from_cbor(vec1), - "[json.exception.parse_error.113] parse error at 13: expected a CBOR string; last byte: 0xB4"); + "[json.exception.parse_error.113] parse error at byte 13: expected a CBOR string; last byte: 0xB4"); // related test case: double-precision std::vector vec2 @@ -1117,7 +1117,7 @@ TEST_CASE("regression tests") }; CHECK_THROWS_AS(json::from_cbor(vec2), json::parse_error&); CHECK_THROWS_WITH(json::from_cbor(vec2), - "[json.exception.parse_error.113] parse error at 13: expected a CBOR string; last byte: 0xB4"); + "[json.exception.parse_error.113] parse error at byte 13: expected a CBOR string; last byte: 0xB4"); } SECTION("issue #452 - Heap-buffer-overflow (OSS-Fuzz issue 585)") diff --git a/test/src/unit-ubjson.cpp b/test/src/unit-ubjson.cpp index 3b060c97..d2410ff6 100644 --- a/test/src/unit-ubjson.cpp +++ b/test/src/unit-ubjson.cpp @@ -1299,7 +1299,7 @@ TEST_CASE("UBJSON") { CHECK_THROWS_AS(json::from_ubjson(vec), json::parse_error&); CHECK_THROWS_WITH(json::from_ubjson(vec), - "[json.exception.parse_error.110] parse error at 2: expected end of input"); + "[json.exception.parse_error.110] parse error at byte 2: expected end of input"); } } @@ -1529,7 +1529,7 @@ TEST_CASE("UBJSON") { CHECK_THROWS_AS(json::from_ubjson(std::vector()), json::parse_error&); CHECK_THROWS_WITH(json::from_ubjson(std::vector()), - "[json.exception.parse_error.110] parse error at 1: unexpected end of input"); + "[json.exception.parse_error.110] parse error at byte 1: unexpected end of input"); } SECTION("char") @@ -1538,14 +1538,14 @@ TEST_CASE("UBJSON") { std::vector v = {'C'}; CHECK_THROWS_AS(json::from_ubjson(v), json::parse_error&); - CHECK_THROWS_WITH(json::from_ubjson(v), "[json.exception.parse_error.110] parse error at 2: unexpected end of input"); + CHECK_THROWS_WITH(json::from_ubjson(v), "[json.exception.parse_error.110] parse error at byte 2: unexpected end of input"); } SECTION("byte out of range") { std::vector v = {'C', 130}; CHECK_THROWS_AS(json::from_ubjson(v), json::parse_error&); - CHECK_THROWS_WITH(json::from_ubjson(v), "[json.exception.parse_error.113] parse error at 2: byte after 'C' must be in range 0x00..0x7F; last byte: 0x82"); + CHECK_THROWS_WITH(json::from_ubjson(v), "[json.exception.parse_error.113] parse error at byte 2: byte after 'C' must be in range 0x00..0x7F; last byte: 0x82"); } } @@ -1555,14 +1555,14 @@ TEST_CASE("UBJSON") { std::vector v = {'S'}; CHECK_THROWS_AS(json::from_ubjson(v), json::parse_error&); - CHECK_THROWS_WITH(json::from_ubjson(v), "[json.exception.parse_error.110] parse error at 2: unexpected end of input"); + CHECK_THROWS_WITH(json::from_ubjson(v), "[json.exception.parse_error.110] parse error at byte 2: unexpected end of input"); } SECTION("invalid byte") { std::vector v = {'S', '1', 'a'}; CHECK_THROWS_AS(json::from_ubjson(v), json::parse_error&); - CHECK_THROWS_WITH(json::from_ubjson(v), "[json.exception.parse_error.113] parse error at 2: expected a UBJSON string; last byte: 0x31"); + CHECK_THROWS_WITH(json::from_ubjson(v), "[json.exception.parse_error.113] parse error at byte 2: expected a UBJSON string; last byte: 0x31"); } } @@ -1572,7 +1572,7 @@ TEST_CASE("UBJSON") { std::vector v = {'[', '$', 'i', 2}; CHECK_THROWS_AS(json::from_ubjson(v), json::parse_error&); - CHECK_THROWS_WITH(json::from_ubjson(v), "[json.exception.parse_error.112] parse error at 4: expected '#' after UBJSON type information; last byte: 0x02"); + CHECK_THROWS_WITH(json::from_ubjson(v), "[json.exception.parse_error.112] parse error at byte 4: expected '#' after UBJSON type information; last byte: 0x02"); } } @@ -1580,17 +1580,17 @@ TEST_CASE("UBJSON") { std::vector vS = {'S'}; CHECK_THROWS_AS(json::from_ubjson(vS), json::parse_error&); - CHECK_THROWS_WITH(json::from_ubjson(vS), "[json.exception.parse_error.110] parse error at 2: unexpected end of input"); + CHECK_THROWS_WITH(json::from_ubjson(vS), "[json.exception.parse_error.110] parse error at byte 2: unexpected end of input"); CHECK(json::from_ubjson(vS, true, false).is_discarded()); std::vector v = {'S', 'i', '2', 'a'}; CHECK_THROWS_AS(json::from_ubjson(v), json::parse_error&); - CHECK_THROWS_WITH(json::from_ubjson(v), "[json.exception.parse_error.110] parse error at 5: unexpected end of input"); + CHECK_THROWS_WITH(json::from_ubjson(v), "[json.exception.parse_error.110] parse error at byte 5: unexpected end of input"); CHECK(json::from_ubjson(v, true, false).is_discarded()); std::vector vC = {'C'}; CHECK_THROWS_AS(json::from_ubjson(vC), json::parse_error&); - CHECK_THROWS_WITH(json::from_ubjson(vC), "[json.exception.parse_error.110] parse error at 2: unexpected end of input"); + CHECK_THROWS_WITH(json::from_ubjson(vC), "[json.exception.parse_error.110] parse error at byte 2: unexpected end of input"); CHECK(json::from_ubjson(vC, true, false).is_discarded()); } @@ -1598,32 +1598,32 @@ TEST_CASE("UBJSON") { std::vector vU = {'[', '#', 'U'}; CHECK_THROWS_AS(json::from_ubjson(vU), json::parse_error&); - CHECK_THROWS_WITH(json::from_ubjson(vU), "[json.exception.parse_error.110] parse error at 4: unexpected end of input"); + CHECK_THROWS_WITH(json::from_ubjson(vU), "[json.exception.parse_error.110] parse error at byte 4: unexpected end of input"); CHECK(json::from_ubjson(vU, true, false).is_discarded()); std::vector vi = {'[', '#', 'i'}; CHECK_THROWS_AS(json::from_ubjson(vi), json::parse_error&); - CHECK_THROWS_WITH(json::from_ubjson(vi), "[json.exception.parse_error.110] parse error at 4: unexpected end of input"); + CHECK_THROWS_WITH(json::from_ubjson(vi), "[json.exception.parse_error.110] parse error at byte 4: unexpected end of input"); CHECK(json::from_ubjson(vi, true, false).is_discarded()); std::vector vI = {'[', '#', 'I'}; CHECK_THROWS_AS(json::from_ubjson(vI), json::parse_error&); - CHECK_THROWS_WITH(json::from_ubjson(vI), "[json.exception.parse_error.110] parse error at 4: unexpected end of input"); + CHECK_THROWS_WITH(json::from_ubjson(vI), "[json.exception.parse_error.110] parse error at byte 4: unexpected end of input"); CHECK(json::from_ubjson(vI, true, false).is_discarded()); std::vector vl = {'[', '#', 'l'}; CHECK_THROWS_AS(json::from_ubjson(vl), json::parse_error&); - CHECK_THROWS_WITH(json::from_ubjson(vl), "[json.exception.parse_error.110] parse error at 4: unexpected end of input"); + CHECK_THROWS_WITH(json::from_ubjson(vl), "[json.exception.parse_error.110] parse error at byte 4: unexpected end of input"); CHECK(json::from_ubjson(vl, true, false).is_discarded()); std::vector vL = {'[', '#', 'L'}; CHECK_THROWS_AS(json::from_ubjson(vL), json::parse_error&); - CHECK_THROWS_WITH(json::from_ubjson(vL), "[json.exception.parse_error.110] parse error at 4: unexpected end of input"); + CHECK_THROWS_WITH(json::from_ubjson(vL), "[json.exception.parse_error.110] parse error at byte 4: unexpected end of input"); CHECK(json::from_ubjson(vL, true, false).is_discarded()); std::vector v0 = {'[', '#', 'T', ']'}; CHECK_THROWS_AS(json::from_ubjson(v0), json::parse_error&); - CHECK_THROWS_WITH(json::from_ubjson(v0), "[json.exception.parse_error.113] parse error at 3: byte after '#' must denote a number type; last byte: 0x54"); + CHECK_THROWS_WITH(json::from_ubjson(v0), "[json.exception.parse_error.113] parse error at byte 3: byte after '#' must denote a number type; last byte: 0x54"); CHECK(json::from_ubjson(v0, true, false).is_discarded()); } @@ -1631,17 +1631,17 @@ TEST_CASE("UBJSON") { std::vector v0 = {'[', '$'}; CHECK_THROWS_AS(json::from_ubjson(v0), json::parse_error&); - CHECK_THROWS_WITH(json::from_ubjson(v0), "[json.exception.parse_error.110] parse error at 3: unexpected end of input"); + CHECK_THROWS_WITH(json::from_ubjson(v0), "[json.exception.parse_error.110] parse error at byte 3: unexpected end of input"); CHECK(json::from_ubjson(v0, true, false).is_discarded()); std::vector vi = {'[', '$', '#'}; CHECK_THROWS_AS(json::from_ubjson(vi), json::parse_error&); - CHECK_THROWS_WITH(json::from_ubjson(vi), "[json.exception.parse_error.110] parse error at 4: unexpected end of input"); + CHECK_THROWS_WITH(json::from_ubjson(vi), "[json.exception.parse_error.110] parse error at byte 4: unexpected end of input"); CHECK(json::from_ubjson(vi, true, false).is_discarded()); std::vector vT = {'[', '$', 'T'}; CHECK_THROWS_AS(json::from_ubjson(vT), json::parse_error&); - CHECK_THROWS_WITH(json::from_ubjson(vT), "[json.exception.parse_error.110] parse error at 4: unexpected end of input"); + CHECK_THROWS_WITH(json::from_ubjson(vT), "[json.exception.parse_error.110] parse error at byte 4: unexpected end of input"); CHECK(json::from_ubjson(vT, true, false).is_discarded()); } @@ -1649,17 +1649,17 @@ TEST_CASE("UBJSON") { std::vector vST = {'[', '$', 'i', '#', 'i', 2, 1}; CHECK_THROWS_AS(json::from_ubjson(vST), json::parse_error&); - CHECK_THROWS_WITH(json::from_ubjson(vST), "[json.exception.parse_error.110] parse error at 8: unexpected end of input"); + CHECK_THROWS_WITH(json::from_ubjson(vST), "[json.exception.parse_error.110] parse error at byte 8: unexpected end of input"); CHECK(json::from_ubjson(vST, true, false).is_discarded()); std::vector vS = {'[', '#', 'i', 2, 'i', 1}; CHECK_THROWS_AS(json::from_ubjson(vS), json::parse_error&); - CHECK_THROWS_WITH(json::from_ubjson(vS), "[json.exception.parse_error.110] parse error at 7: unexpected end of input"); + CHECK_THROWS_WITH(json::from_ubjson(vS), "[json.exception.parse_error.110] parse error at byte 7: unexpected end of input"); CHECK(json::from_ubjson(vS, true, false).is_discarded()); std::vector v = {'[', 'i', 2, 'i', 1}; CHECK_THROWS_AS(json::from_ubjson(v), json::parse_error&); - CHECK_THROWS_WITH(json::from_ubjson(v), "[json.exception.parse_error.110] parse error at 6: unexpected end of input"); + CHECK_THROWS_WITH(json::from_ubjson(v), "[json.exception.parse_error.110] parse error at byte 6: unexpected end of input"); CHECK(json::from_ubjson(v, true, false).is_discarded()); } @@ -1667,42 +1667,42 @@ TEST_CASE("UBJSON") { std::vector vST = {'{', '$', 'i', '#', 'i', 2, 'i', 1, 'a', 1}; CHECK_THROWS_AS(json::from_ubjson(vST), json::parse_error&); - CHECK_THROWS_WITH(json::from_ubjson(vST), "[json.exception.parse_error.110] parse error at 11: unexpected end of input"); + CHECK_THROWS_WITH(json::from_ubjson(vST), "[json.exception.parse_error.110] parse error at byte 11: unexpected end of input"); CHECK(json::from_ubjson(vST, true, false).is_discarded()); std::vector vT = {'{', '$', 'i', 'i', 1, 'a', 1}; CHECK_THROWS_AS(json::from_ubjson(vT), json::parse_error&); - CHECK_THROWS_WITH(json::from_ubjson(vT), "[json.exception.parse_error.112] parse error at 4: expected '#' after UBJSON type information; last byte: 0x69"); + CHECK_THROWS_WITH(json::from_ubjson(vT), "[json.exception.parse_error.112] parse error at byte 4: expected '#' after UBJSON type information; last byte: 0x69"); CHECK(json::from_ubjson(vT, true, false).is_discarded()); std::vector vS = {'{', '#', 'i', 2, 'i', 1, 'a', 'i', 1}; CHECK_THROWS_AS(json::from_ubjson(vS), json::parse_error&); - CHECK_THROWS_WITH(json::from_ubjson(vS), "[json.exception.parse_error.110] parse error at 10: unexpected end of input"); + CHECK_THROWS_WITH(json::from_ubjson(vS), "[json.exception.parse_error.110] parse error at byte 10: unexpected end of input"); CHECK(json::from_ubjson(vS, true, false).is_discarded()); std::vector v = {'{', 'i', 1, 'a', 'i', 1}; CHECK_THROWS_AS(json::from_ubjson(v), json::parse_error&); - CHECK_THROWS_WITH(json::from_ubjson(v), "[json.exception.parse_error.110] parse error at 7: unexpected end of input"); + CHECK_THROWS_WITH(json::from_ubjson(v), "[json.exception.parse_error.110] parse error at byte 7: unexpected end of input"); CHECK(json::from_ubjson(v, true, false).is_discarded()); std::vector v2 = {'{', 'i', 1, 'a', 'i', 1, 'i'}; CHECK_THROWS_AS(json::from_ubjson(v2), json::parse_error&); - CHECK_THROWS_WITH(json::from_ubjson(v2), "[json.exception.parse_error.110] parse error at 8: unexpected end of input"); + CHECK_THROWS_WITH(json::from_ubjson(v2), "[json.exception.parse_error.110] parse error at byte 8: unexpected end of input"); CHECK(json::from_ubjson(v2, true, false).is_discarded()); std::vector v3 = {'{', 'i', 1, 'a'}; CHECK_THROWS_AS(json::from_ubjson(v3), json::parse_error&); - CHECK_THROWS_WITH(json::from_ubjson(v3), "[json.exception.parse_error.110] parse error at 5: unexpected end of input"); + CHECK_THROWS_WITH(json::from_ubjson(v3), "[json.exception.parse_error.110] parse error at byte 5: unexpected end of input"); CHECK(json::from_ubjson(v3, true, false).is_discarded()); std::vector vST1 = {'{', '$', 'd', '#', 'i', 2, 'i', 1, 'a'}; CHECK_THROWS_AS(json::from_ubjson(vST1), json::parse_error&); - CHECK_THROWS_WITH(json::from_ubjson(vST1), "[json.exception.parse_error.110] parse error at 10: unexpected end of input"); + CHECK_THROWS_WITH(json::from_ubjson(vST1), "[json.exception.parse_error.110] parse error at byte 10: unexpected end of input"); CHECK(json::from_ubjson(vST1, true, false).is_discarded()); std::vector vST2 = {'{', '#', 'i', 2, 'i', 1, 'a'}; CHECK_THROWS_AS(json::from_ubjson(vST2), json::parse_error&); - CHECK_THROWS_WITH(json::from_ubjson(vST2), "[json.exception.parse_error.110] parse error at 8: unexpected end of input"); + CHECK_THROWS_WITH(json::from_ubjson(vST2), "[json.exception.parse_error.110] parse error at byte 8: unexpected end of input"); CHECK(json::from_ubjson(vST2, true, false).is_discarded()); } } diff --git a/test/src/unit-unicode.cpp b/test/src/unit-unicode.cpp index ae580e3e..4def1a3e 100644 --- a/test/src/unit-unicode.cpp +++ b/test/src/unit-unicode.cpp @@ -931,31 +931,31 @@ TEST_CASE("Unicode", "[hide]") { CHECK_THROWS_AS(json::parse("\"\\uDC00\\uDC00\""), json::parse_error&); CHECK_THROWS_WITH(json::parse("\"\\uDC00\\uDC00\""), - "[json.exception.parse_error.101] parse error at 7: syntax error - invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF; last read: '\"\\uDC00'"); + "[json.exception.parse_error.101] parse error at line 1, column 7: syntax error while parsing value - invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF; last read: '\"\\uDC00'"); CHECK_THROWS_AS(json::parse("\"\\uD7FF\\uDC00\""), json::parse_error&); CHECK_THROWS_WITH(json::parse("\"\\uD7FF\\uDC00\""), - "[json.exception.parse_error.101] parse error at 13: syntax error - invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF; last read: '\"\\uD7FF\\uDC00'"); + "[json.exception.parse_error.101] parse error at line 1, column 13: syntax error while parsing value - invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF; last read: '\"\\uD7FF\\uDC00'"); CHECK_THROWS_AS(json::parse("\"\\uD800]\""), json::parse_error&); CHECK_THROWS_WITH(json::parse("\"\\uD800]\""), - "[json.exception.parse_error.101] parse error at 8: syntax error - invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF; last read: '\"\\uD800]'"); + "[json.exception.parse_error.101] parse error at line 1, column 8: syntax error while parsing value - invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF; last read: '\"\\uD800]'"); CHECK_THROWS_AS(json::parse("\"\\uD800\\v\""), json::parse_error&); CHECK_THROWS_WITH(json::parse("\"\\uD800\\v\""), - "[json.exception.parse_error.101] parse error at 9: syntax error - invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF; last read: '\"\\uD800\\v'"); + "[json.exception.parse_error.101] parse error at line 1, column 9: syntax error while parsing value - invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF; last read: '\"\\uD800\\v'"); CHECK_THROWS_AS(json::parse("\"\\uD800\\u123\""), json::parse_error&); CHECK_THROWS_WITH(json::parse("\"\\uD800\\u123\""), - "[json.exception.parse_error.101] parse error at 13: syntax error - invalid string: '\\u' must be followed by 4 hex digits; last read: '\"\\uD800\\u123\"'"); + "[json.exception.parse_error.101] parse error at line 1, column 13: syntax error while parsing value - invalid string: '\\u' must be followed by 4 hex digits; last read: '\"\\uD800\\u123\"'"); CHECK_THROWS_AS(json::parse("\"\\uD800\\uDBFF\""), json::parse_error&); CHECK_THROWS_WITH(json::parse("\"\\uD800\\uDBFF\""), - "[json.exception.parse_error.101] parse error at 13: syntax error - invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF; last read: '\"\\uD800\\uDBFF'"); + "[json.exception.parse_error.101] parse error at line 1, column 13: syntax error while parsing value - invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF; last read: '\"\\uD800\\uDBFF'"); CHECK_THROWS_AS(json::parse("\"\\uD800\\uE000\""), json::parse_error&); CHECK_THROWS_WITH(json::parse("\"\\uD800\\uE000\""), - "[json.exception.parse_error.101] parse error at 13: syntax error - invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF; last read: '\"\\uD800\\uE000'"); + "[json.exception.parse_error.101] parse error at line 1, column 13: syntax error while parsing value - invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF; last read: '\"\\uD800\\uE000'"); } }