diff --git a/src/json.hpp b/src/json.hpp index fbc996adec6ebdf3f5008c64673a6f4ce70cfb25..20c5b2bc09fcd94b9f239898707b5077e07a9de3 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -7284,7 +7284,7 @@ class basic_json static basic_json parse(const CharT s, const parser_callback_t cb = nullptr) { - return parser(reinterpret_cast(s), cb).parse(true); + return parser(input_adapter::create(s), cb).parse(true); } /*! @@ -7319,7 +7319,7 @@ class basic_json static basic_json parse(std::istream& i, const parser_callback_t cb = nullptr) { - return parser(i, cb).parse(true); + return parser(input_adapter::create(i), cb).parse(true); } /*! @@ -7328,7 +7328,7 @@ class basic_json static basic_json parse(std::istream&& i, const parser_callback_t cb = nullptr) { - return parser(i, cb).parse(true); + return parser(input_adapter::create(i), cb).parse(true); } /*! @@ -7383,27 +7383,7 @@ class basic_json static basic_json parse(IteratorType first, IteratorType last, const parser_callback_t cb = nullptr) { - // assertion to check that the iterator range is indeed contiguous, - // see http://stackoverflow.com/a/35008842/266378 for more discussion - assert(std::accumulate(first, last, std::pair(true, 0), - [&first](std::pair res, decltype(*first) val) - { - res.first &= (val == *(std::next(std::addressof(*first), res.second++))); - return res; - }).first); - - // assertion to check that each element is 1 byte long - static_assert(sizeof(typename std::iterator_traits::value_type) == 1, - "each element in the iterator range must have the size of 1 byte"); - - // if iterator range is empty, create a parser with an empty string - // to generate "unexpected EOF" error message - if (std::distance(first, last) <= 0) - { - return parser("").parse(true); - } - - return parser(first, last, cb).parse(true); + return parser(input_adapter::create(first, last), cb).parse(true); } /*! @@ -7473,7 +7453,7 @@ class basic_json JSON_DEPRECATED friend std::istream& operator<<(basic_json& j, std::istream& i) { - j = parser(i).parse(true); + j = parser(input_adapter::create(i)).parse(true); return i; } @@ -7505,7 +7485,7 @@ class basic_json */ friend std::istream& operator>>(std::istream& i, basic_json& j) { - j = parser(i).parse(true); + j = parser(input_adapter::create(i)).parse(true); return i; } @@ -8566,6 +8546,84 @@ class basic_json virtual int get_character() = 0; virtual std::string read(size_t offset, size_t length) = 0; virtual ~input_adapter() {} + + // native support + + /// input adapter for input stream + static std::shared_ptr create(std::istream& i, const size_t buffer_size = 16384) + { + return std::shared_ptr(new cached_input_stream_adapter(i, buffer_size)); + } + + /// input adapter for input stream + static std::shared_ptr create(std::istream&& i, const size_t buffer_size = 16384) + { + return std::shared_ptr(new cached_input_stream_adapter(i, buffer_size)); + } + + /// input adapter for buffer + static std::shared_ptr create(const char* b, size_t l) + { + return std::shared_ptr(new input_buffer_adapter(b, l)); + } + + // derived support + + /// input adapter for string literal + template::value and + std::is_integral::type>::value and + sizeof(typename std::remove_pointer::type) == 1, int>::type = 0> + static std::shared_ptr create(CharT b) + { + return create(reinterpret_cast(b), + std::strlen(reinterpret_cast(b))); + } + + /// input adapter for iterator range with contiguous storage + template::iterator_category, std::random_access_iterator_tag>::value + , int>::type + = 0> + static std::shared_ptr create(IteratorType first, IteratorType last) + { + // assertion to check that the iterator range is indeed contiguous, + // see http://stackoverflow.com/a/35008842/266378 for more discussion + assert(std::accumulate(first, last, std::pair(true, 0), + [&first](std::pair res, decltype(*first) val) + { + res.first &= (val == *(std::next(std::addressof(*first), res.second++))); + return res; + }).first); + + // assertion to check that each element is 1 byte long + static_assert(sizeof(typename std::iterator_traits::value_type) == 1, + "each element in the iterator range must have the size of 1 byte"); + + return create(reinterpret_cast(&(*first)), + static_cast(std::distance(first, last))); + } + + /// input adapter for array + template + static std::shared_ptr create(T (&array)[N]) + { + // delegate the call to the iterator-range overload + return create(std::begin(array), std::end(array)); + } + + /// input adapter for contiguous container + template::value and + std::is_base_of< + std::random_access_iterator_tag, + typename std::iterator_traits()))>::iterator_category>::value + , int>::type = 0> + static std::shared_ptr create(const ContiguousContainer& c) + { + // delegate the call to the iterator-range overload + return create(std::begin(c), std::end(c)); + } }; /// input adapter for cached stream input @@ -8725,25 +8783,10 @@ class basic_json class binary_reader { public: - explicit binary_reader(std::istream& i) - : ia(new cached_input_stream_adapter(i, 16384)), - is_little_endian(little_endianess()) + explicit binary_reader(std::shared_ptr a) + : ia(a), is_little_endian(little_endianess()) {} - binary_reader(const char* buff, const size_t len) - : ia(new input_buffer_adapter(buff, len)), - is_little_endian(little_endianess()) - {} - - ~binary_reader() - { - delete ia; - } - - // switch off unwanted functions (due to pointer members) - binary_reader(const binary_reader&) = delete; - binary_reader operator=(const binary_reader&) = delete; - /*! @param[in] get_char whether a new character should be retrieved from the input (true, default) or whether the last @@ -9764,7 +9807,7 @@ class basic_json private: /// input adapter - input_adapter* ia = nullptr; + std::shared_ptr ia = nullptr; /// the current character int current = std::char_traits::eof(); @@ -10560,7 +10603,7 @@ class basic_json static basic_json from_cbor(const std::vector& v, const size_t start_index = 0) { - binary_reader br(reinterpret_cast(v.data() + start_index), v.size() - start_index); + binary_reader br(input_adapter::create(v.begin() + static_cast(start_index), v.end())); return br.parse_cbor(); } @@ -10635,7 +10678,7 @@ class basic_json static basic_json from_msgpack(const std::vector& v, const size_t start_index = 0) { - binary_reader br(reinterpret_cast(v.data() + start_index), v.size() - start_index); + binary_reader br(input_adapter::create(v.begin() + static_cast(start_index), v.end())); return br.parse_msgpack(); } @@ -10718,26 +10761,10 @@ class basic_json } } - explicit lexer(std::istream& i) - : ia(new cached_input_stream_adapter(i, 16384)), - decimal_point_char(get_decimal_point()) - {} - - lexer(const char* buff, const size_t len) - : ia(new input_buffer_adapter(buff, len)), - decimal_point_char(get_decimal_point()) + explicit lexer(std::shared_ptr a) + : ia(a), decimal_point_char(get_decimal_point()) {} - ~lexer() - { - delete ia; - } - - // switch off unwanted functions (due to pointer members) - lexer() = delete; - lexer(const lexer&) = delete; - lexer operator=(const lexer&) = delete; - private: ///////////////////// // locales @@ -12091,7 +12118,7 @@ scan_number_done: private: /// input adapter - input_adapter* ia = nullptr; + std::shared_ptr ia = nullptr; /// the current character int current = std::char_traits::eof(); @@ -12129,28 +12156,10 @@ scan_number_done: class parser { public: - /// a parser reading from a string literal - parser(const char* buff, const parser_callback_t cb = nullptr) - : callback(cb), m_lexer(buff, std::strlen(buff)) - {} - - /*! - @brief a parser reading from an input stream - @throw parse_error.111 if input stream is in a bad state - */ - parser(std::istream& is, const parser_callback_t cb = nullptr) - : callback(cb), m_lexer(is) - {} - - /// a parser reading from an iterator range with contiguous storage - template::iterator_category, std::random_access_iterator_tag>::value - , int>::type - = 0> - parser(IteratorType first, IteratorType last, const parser_callback_t cb = nullptr) - : callback(cb), - m_lexer(reinterpret_cast(&(*first)), - static_cast(std::distance(first, last))) + /// a parser reading from an input adapter + explicit parser(std::shared_ptr ia, + const parser_callback_t cb = nullptr) + : callback(cb), m_lexer(ia) {} /*! diff --git a/test/src/unit-class_lexer.cpp b/test/src/unit-class_lexer.cpp index 2acea176ea2bb658ee8fe67c6e0af9f1138a7f08..071337b5d781fa9dd66cb5ed68ec26ba4ab7ddd2 100644 --- a/test/src/unit-class_lexer.cpp +++ b/test/src/unit-class_lexer.cpp @@ -32,56 +32,63 @@ SOFTWARE. #include "json.hpp" using nlohmann::json; +// shortcut to scan a string literal +json::lexer::token_type scan_string(const char* s); +json::lexer::token_type scan_string(const char* s) +{ + return json::lexer(json::input_adapter::create(s)).scan(); +} + TEST_CASE("lexer class") { SECTION("scan") { SECTION("structural characters") { - CHECK((json::lexer("[", 1).scan() == json::lexer::token_type::begin_array)); - CHECK((json::lexer("]", 1).scan() == json::lexer::token_type::end_array)); - CHECK((json::lexer("{", 1).scan() == json::lexer::token_type::begin_object)); - CHECK((json::lexer("}", 1).scan() == json::lexer::token_type::end_object)); - CHECK((json::lexer(",", 1).scan() == json::lexer::token_type::value_separator)); - CHECK((json::lexer(":", 1).scan() == json::lexer::token_type::name_separator)); + CHECK((scan_string("[") == json::lexer::token_type::begin_array)); + CHECK((scan_string("]") == json::lexer::token_type::end_array)); + CHECK((scan_string("{") == json::lexer::token_type::begin_object)); + CHECK((scan_string("}") == json::lexer::token_type::end_object)); + CHECK((scan_string(",") == json::lexer::token_type::value_separator)); + CHECK((scan_string(":") == json::lexer::token_type::name_separator)); } SECTION("literal names") { - CHECK((json::lexer("null", 4).scan() == json::lexer::token_type::literal_null)); - CHECK((json::lexer("true", 4).scan() == json::lexer::token_type::literal_true)); - CHECK((json::lexer("false", 5).scan() == json::lexer::token_type::literal_false)); + CHECK((scan_string("null") == json::lexer::token_type::literal_null)); + CHECK((scan_string("true") == json::lexer::token_type::literal_true)); + CHECK((scan_string("false") == json::lexer::token_type::literal_false)); } SECTION("numbers") { - CHECK((json::lexer("0", 1).scan() == json::lexer::token_type::value_unsigned)); - CHECK((json::lexer("1", 1).scan() == json::lexer::token_type::value_unsigned)); - CHECK((json::lexer("2", 1).scan() == json::lexer::token_type::value_unsigned)); - CHECK((json::lexer("3", 1).scan() == json::lexer::token_type::value_unsigned)); - CHECK((json::lexer("4", 1).scan() == json::lexer::token_type::value_unsigned)); - CHECK((json::lexer("5", 1).scan() == json::lexer::token_type::value_unsigned)); - CHECK((json::lexer("6", 1).scan() == json::lexer::token_type::value_unsigned)); - CHECK((json::lexer("7", 1).scan() == json::lexer::token_type::value_unsigned)); - CHECK((json::lexer("8", 1).scan() == json::lexer::token_type::value_unsigned)); - CHECK((json::lexer("9", 1).scan() == json::lexer::token_type::value_unsigned)); - - CHECK((json::lexer("-0", 2).scan() == json::lexer::token_type::value_integer)); - CHECK((json::lexer("-1", 2).scan() == json::lexer::token_type::value_integer)); - - CHECK((json::lexer("1.1", 3).scan() == json::lexer::token_type::value_float)); - CHECK((json::lexer("-1.1", 4).scan() == json::lexer::token_type::value_float)); - CHECK((json::lexer("1E10", 4).scan() == json::lexer::token_type::value_float)); + CHECK((scan_string("0") == json::lexer::token_type::value_unsigned)); + CHECK((scan_string("1") == json::lexer::token_type::value_unsigned)); + CHECK((scan_string("2") == json::lexer::token_type::value_unsigned)); + CHECK((scan_string("3") == json::lexer::token_type::value_unsigned)); + CHECK((scan_string("4") == json::lexer::token_type::value_unsigned)); + CHECK((scan_string("5") == json::lexer::token_type::value_unsigned)); + CHECK((scan_string("6") == json::lexer::token_type::value_unsigned)); + CHECK((scan_string("7") == json::lexer::token_type::value_unsigned)); + CHECK((scan_string("8") == json::lexer::token_type::value_unsigned)); + CHECK((scan_string("9") == json::lexer::token_type::value_unsigned)); + + CHECK((scan_string("-0") == json::lexer::token_type::value_integer)); + CHECK((scan_string("-1") == json::lexer::token_type::value_integer)); + + CHECK((scan_string("1.1") == json::lexer::token_type::value_float)); + CHECK((scan_string("-1.1") == json::lexer::token_type::value_float)); + CHECK((scan_string("1E10") == json::lexer::token_type::value_float)); } SECTION("whitespace") { // result is end_of_input, because not token is following - CHECK((json::lexer(" ", 1).scan() == json::lexer::token_type::end_of_input)); - CHECK((json::lexer("\t", 1).scan() == json::lexer::token_type::end_of_input)); - CHECK((json::lexer("\n", 1).scan() == json::lexer::token_type::end_of_input)); - CHECK((json::lexer("\r", 1).scan() == json::lexer::token_type::end_of_input)); - CHECK((json::lexer(" \t\n\r\n\t ", 7).scan() == json::lexer::token_type::end_of_input)); + CHECK((scan_string(" ") == json::lexer::token_type::end_of_input)); + CHECK((scan_string("\t") == json::lexer::token_type::end_of_input)); + CHECK((scan_string("\n") == json::lexer::token_type::end_of_input)); + CHECK((scan_string("\r") == json::lexer::token_type::end_of_input)); + CHECK((scan_string(" \t\n\r\n\t ") == json::lexer::token_type::end_of_input)); } } @@ -112,7 +119,7 @@ TEST_CASE("lexer class") // create string from the ASCII code const auto s = std::string(1, static_cast(c)); // store scan() result - const auto res = json::lexer(s.c_str(), 1).scan(); + const auto res = scan_string(s.c_str()); switch (c) { @@ -164,7 +171,7 @@ TEST_CASE("lexer class") std::string s("\""); s += std::string(2048, 'x'); s += "\""; - CHECK((json::lexer(s.c_str(), 2050).scan() == json::lexer::token_type::value_string)); + CHECK((scan_string(s.c_str()) == json::lexer::token_type::value_string)); } /* NOTE: to_unicode function has been removed diff --git a/test/src/unit-class_parser.cpp b/test/src/unit-class_parser.cpp index 864b7be1c112763ad82740d1bcb7b6c6af5c5d12..e0fffac43e4aeef282bffafaa65909b718452620 100644 --- a/test/src/unit-class_parser.cpp +++ b/test/src/unit-class_parser.cpp @@ -34,36 +34,43 @@ using nlohmann::json; #include +// shortcut to parse a string literal +json::parser parse_string(const char* s); +json::parser parse_string(const char* s) +{ + return json::parser(json::input_adapter::create(s)); +} + TEST_CASE("parser class") { SECTION("parse") { SECTION("null") { - CHECK(json::parser("null").parse() == json(nullptr)); + CHECK(parse_string("null").parse() == json(nullptr)); } SECTION("true") { - CHECK(json::parser("true").parse() == json(true)); + CHECK(parse_string("true").parse() == json(true)); } SECTION("false") { - CHECK(json::parser("false").parse() == json(false)); + CHECK(parse_string("false").parse() == json(false)); } SECTION("array") { SECTION("empty array") { - CHECK(json::parser("[]").parse() == json(json::value_t::array)); - CHECK(json::parser("[ ]").parse() == json(json::value_t::array)); + CHECK(parse_string("[]").parse() == json(json::value_t::array)); + CHECK(parse_string("[ ]").parse() == json(json::value_t::array)); } SECTION("nonempty array") { - CHECK(json::parser("[true, false, null]").parse() == json({true, false, nullptr})); + CHECK(parse_string("[true, false, null]").parse() == json({true, false, nullptr})); } } @@ -71,113 +78,113 @@ TEST_CASE("parser class") { SECTION("empty object") { - CHECK(json::parser("{}").parse() == json(json::value_t::object)); - CHECK(json::parser("{ }").parse() == json(json::value_t::object)); + CHECK(parse_string("{}").parse() == json(json::value_t::object)); + CHECK(parse_string("{ }").parse() == json(json::value_t::object)); } SECTION("nonempty object") { - CHECK(json::parser("{\"\": true, \"one\": 1, \"two\": null}").parse() == json({{"", true}, {"one", 1}, {"two", nullptr}})); + CHECK(parse_string("{\"\": true, \"one\": 1, \"two\": null}").parse() == json({{"", true}, {"one", 1}, {"two", nullptr}})); } } SECTION("string") { // empty string - CHECK(json::parser("\"\"").parse() == json(json::value_t::string)); + CHECK(parse_string("\"\"").parse() == json(json::value_t::string)); SECTION("errors") { // error: tab in string - CHECK_THROWS_AS(json::parser("\"\t\"").parse(), json::parse_error); - CHECK_THROWS_WITH(json::parser("\"\t\"").parse(), + CHECK_THROWS_AS(parse_string("\"\t\"").parse(), json::parse_error); + CHECK_THROWS_WITH(parse_string("\"\t\"").parse(), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control characters (U+0000 through U+001f) must be escaped; last read '\"'"); // error: newline in string - CHECK_THROWS_AS(json::parser("\"\n\"").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("\"\r\"").parse(), json::parse_error); - CHECK_THROWS_WITH(json::parser("\"\n\"").parse(), + CHECK_THROWS_AS(parse_string("\"\n\"").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("\"\r\"").parse(), json::parse_error); + CHECK_THROWS_WITH(parse_string("\"\n\"").parse(), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control characters (U+0000 through U+001f) must be escaped; last read '\"'"); - CHECK_THROWS_WITH(json::parser("\"\r\"").parse(), + CHECK_THROWS_WITH(parse_string("\"\r\"").parse(), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control characters (U+0000 through U+001f) must be escaped; last read '\"'"); // error: backspace in string - CHECK_THROWS_AS(json::parser("\"\b\"").parse(), json::parse_error); - CHECK_THROWS_WITH(json::parser("\"\b\"").parse(), + CHECK_THROWS_AS(parse_string("\"\b\"").parse(), json::parse_error); + CHECK_THROWS_WITH(parse_string("\"\b\"").parse(), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid string: control characters (U+0000 through U+001f) must be escaped; last read '\"'"); // improve code coverage - CHECK_THROWS_AS(json::parser("\uFF01").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("[-4:1,]").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("\uFF01").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("[-4:1,]").parse(), json::parse_error); // unescaped control characters - CHECK_THROWS_AS(json::parser("\"\x00\"").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("\"\x01\"").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("\"\x02\"").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("\"\x03\"").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("\"\x04\"").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("\"\x05\"").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("\"\x06\"").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("\"\x07\"").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("\"\x08\"").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("\"\x09\"").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("\"\x0a\"").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("\"\x0b\"").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("\"\x0c\"").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("\"\x0d\"").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("\"\x0e\"").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("\"\x0f\"").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("\"\x10\"").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("\"\x11\"").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("\"\x12\"").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("\"\x13\"").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("\"\x14\"").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("\"\x15\"").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("\"\x16\"").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("\"\x17\"").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("\"\x18\"").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("\"\x19\"").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("\"\x1a\"").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("\"\x1b\"").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("\"\x1c\"").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("\"\x1d\"").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("\"\x1e\"").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("\"\x1f\"").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("\"\x00\"").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("\"\x01\"").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("\"\x02\"").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("\"\x03\"").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("\"\x04\"").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("\"\x05\"").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("\"\x06\"").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("\"\x07\"").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("\"\x08\"").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("\"\x09\"").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("\"\x0a\"").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("\"\x0b\"").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("\"\x0c\"").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("\"\x0d\"").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("\"\x0e\"").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("\"\x0f\"").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("\"\x10\"").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("\"\x11\"").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("\"\x12\"").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("\"\x13\"").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("\"\x14\"").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("\"\x15\"").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("\"\x16\"").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("\"\x17\"").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("\"\x18\"").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("\"\x19\"").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("\"\x1a\"").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("\"\x1b\"").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("\"\x1c\"").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("\"\x1d\"").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("\"\x1e\"").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("\"\x1f\"").parse(), json::parse_error); } SECTION("escaped") { // quotation mark "\"" auto r1 = R"("\"")"_json; - CHECK(json::parser("\"\\\"\"").parse() == r1); + CHECK(parse_string("\"\\\"\"").parse() == r1); // reverse solidus "\\" auto r2 = R"("\\")"_json; - CHECK(json::parser("\"\\\\\"").parse() == r2); + CHECK(parse_string("\"\\\\\"").parse() == r2); // solidus - CHECK(json::parser("\"\\/\"").parse() == R"("/")"_json); + CHECK(parse_string("\"\\/\"").parse() == R"("/")"_json); // backspace - CHECK(json::parser("\"\\b\"").parse() == json("\b")); + CHECK(parse_string("\"\\b\"").parse() == json("\b")); // formfeed - CHECK(json::parser("\"\\f\"").parse() == json("\f")); + CHECK(parse_string("\"\\f\"").parse() == json("\f")); // newline - CHECK(json::parser("\"\\n\"").parse() == json("\n")); + CHECK(parse_string("\"\\n\"").parse() == json("\n")); // carriage return - CHECK(json::parser("\"\\r\"").parse() == json("\r")); + CHECK(parse_string("\"\\r\"").parse() == json("\r")); // horizontal tab - CHECK(json::parser("\"\\t\"").parse() == json("\t")); - - CHECK(json::parser("\"\\u0001\"").parse().get() == "\x01"); - CHECK(json::parser("\"\\u000a\"").parse().get() == "\n"); - CHECK(json::parser("\"\\u00b0\"").parse().get() == "°"); - CHECK(json::parser("\"\\u0c00\"").parse().get() == "ఀ"); - CHECK(json::parser("\"\\ud000\"").parse().get() == "퀀"); - CHECK(json::parser("\"\\u000E\"").parse().get() == "\x0E"); - CHECK(json::parser("\"\\u00F0\"").parse().get() == "ð"); - CHECK(json::parser("\"\\u0100\"").parse().get() == "Ā"); - CHECK(json::parser("\"\\u2000\"").parse().get() == " "); - CHECK(json::parser("\"\\uFFFF\"").parse().get() == "￿"); - CHECK(json::parser("\"\\u20AC\"").parse().get() == "€"); - CHECK(json::parser("\"€\"").parse().get() == "€"); - CHECK(json::parser("\"🎈\"").parse().get() == "🎈"); - - CHECK(json::parse("\"\\ud80c\\udc60\"").get() == u8"\U00013060"); - CHECK(json::parse("\"\\ud83c\\udf1e\"").get() == "🌞"); + CHECK(parse_string("\"\\t\"").parse() == json("\t")); + + CHECK(parse_string("\"\\u0001\"").parse().get() == "\x01"); + CHECK(parse_string("\"\\u000a\"").parse().get() == "\n"); + CHECK(parse_string("\"\\u00b0\"").parse().get() == "°"); + CHECK(parse_string("\"\\u0c00\"").parse().get() == "ఀ"); + CHECK(parse_string("\"\\ud000\"").parse().get() == "퀀"); + CHECK(parse_string("\"\\u000E\"").parse().get() == "\x0E"); + CHECK(parse_string("\"\\u00F0\"").parse().get() == "ð"); + CHECK(parse_string("\"\\u0100\"").parse().get() == "Ā"); + CHECK(parse_string("\"\\u2000\"").parse().get() == " "); + CHECK(parse_string("\"\\uFFFF\"").parse().get() == "￿"); + CHECK(parse_string("\"\\u20AC\"").parse().get() == "€"); + CHECK(parse_string("\"€\"").parse().get() == "€"); + CHECK(parse_string("\"🎈\"").parse().get() == "🎈"); + + CHECK(parse_string("\"\\ud80c\\udc60\"").parse().get() == u8"\U00013060"); + CHECK(parse_string("\"\\ud83c\\udf1e\"").parse().get() == "🌞"); } } @@ -187,40 +194,40 @@ TEST_CASE("parser class") { SECTION("without exponent") { - CHECK(json::parser("-128").parse() == json(-128)); - CHECK(json::parser("-0").parse() == json(-0)); - CHECK(json::parser("0").parse() == json(0)); - CHECK(json::parser("128").parse() == json(128)); + CHECK(parse_string("-128").parse() == json(-128)); + CHECK(parse_string("-0").parse() == json(-0)); + CHECK(parse_string("0").parse() == json(0)); + CHECK(parse_string("128").parse() == json(128)); } SECTION("with exponent") { - CHECK(json::parser("0e1").parse() == json(0e1)); - CHECK(json::parser("0E1").parse() == json(0e1)); - - CHECK(json::parser("10000E-4").parse() == json(10000e-4)); - CHECK(json::parser("10000E-3").parse() == json(10000e-3)); - CHECK(json::parser("10000E-2").parse() == json(10000e-2)); - CHECK(json::parser("10000E-1").parse() == json(10000e-1)); - CHECK(json::parser("10000E0").parse() == json(10000e0)); - CHECK(json::parser("10000E1").parse() == json(10000e1)); - CHECK(json::parser("10000E2").parse() == json(10000e2)); - CHECK(json::parser("10000E3").parse() == json(10000e3)); - CHECK(json::parser("10000E4").parse() == json(10000e4)); - - CHECK(json::parser("10000e-4").parse() == json(10000e-4)); - CHECK(json::parser("10000e-3").parse() == json(10000e-3)); - CHECK(json::parser("10000e-2").parse() == json(10000e-2)); - CHECK(json::parser("10000e-1").parse() == json(10000e-1)); - CHECK(json::parser("10000e0").parse() == json(10000e0)); - CHECK(json::parser("10000e1").parse() == json(10000e1)); - CHECK(json::parser("10000e2").parse() == json(10000e2)); - CHECK(json::parser("10000e3").parse() == json(10000e3)); - CHECK(json::parser("10000e4").parse() == json(10000e4)); - - CHECK(json::parser("-0e1").parse() == json(-0e1)); - CHECK(json::parser("-0E1").parse() == json(-0e1)); - CHECK(json::parser("-0E123").parse() == json(-0e123)); + CHECK(parse_string("0e1").parse() == json(0e1)); + CHECK(parse_string("0E1").parse() == json(0e1)); + + CHECK(parse_string("10000E-4").parse() == json(10000e-4)); + CHECK(parse_string("10000E-3").parse() == json(10000e-3)); + CHECK(parse_string("10000E-2").parse() == json(10000e-2)); + CHECK(parse_string("10000E-1").parse() == json(10000e-1)); + CHECK(parse_string("10000E0").parse() == json(10000e0)); + CHECK(parse_string("10000E1").parse() == json(10000e1)); + CHECK(parse_string("10000E2").parse() == json(10000e2)); + CHECK(parse_string("10000E3").parse() == json(10000e3)); + CHECK(parse_string("10000E4").parse() == json(10000e4)); + + CHECK(parse_string("10000e-4").parse() == json(10000e-4)); + CHECK(parse_string("10000e-3").parse() == json(10000e-3)); + CHECK(parse_string("10000e-2").parse() == json(10000e-2)); + CHECK(parse_string("10000e-1").parse() == json(10000e-1)); + CHECK(parse_string("10000e0").parse() == json(10000e0)); + CHECK(parse_string("10000e1").parse() == json(10000e1)); + CHECK(parse_string("10000e2").parse() == json(10000e2)); + CHECK(parse_string("10000e3").parse() == json(10000e3)); + CHECK(parse_string("10000e4").parse() == json(10000e4)); + + CHECK(parse_string("-0e1").parse() == json(-0e1)); + CHECK(parse_string("-0E1").parse() == json(-0e1)); + CHECK(parse_string("-0E123").parse() == json(-0e123)); } SECTION("edge cases") @@ -232,9 +239,9 @@ TEST_CASE("parser class") // agree exactly on their numeric values. // -(2**53)+1 - CHECK(json::parser("-9007199254740991").parse().get() == -9007199254740991); + CHECK(parse_string("-9007199254740991").parse().get() == -9007199254740991); // (2**53)-1 - CHECK(json::parser("9007199254740991").parse().get() == 9007199254740991); + CHECK(parse_string("9007199254740991").parse().get() == 9007199254740991); } SECTION("over the edge cases") // issue #178 - Integer conversion to unsigned (incorrect handling of 64 bit integers) @@ -247,11 +254,11 @@ TEST_CASE("parser class") // i.e. -(2**63) -> (2**64)-1. // -(2**63) ** Note: compilers see negative literals as negated positive numbers (hence the -1)) - CHECK(json::parser("-9223372036854775808").parse().get() == -9223372036854775807 - 1); + CHECK(parse_string("-9223372036854775808").parse().get() == -9223372036854775807 - 1); // (2**63)-1 - CHECK(json::parser("9223372036854775807").parse().get() == 9223372036854775807); + CHECK(parse_string("9223372036854775807").parse().get() == 9223372036854775807); // (2**64)-1 - CHECK(json::parser("18446744073709551615").parse().get() == 18446744073709551615u); + CHECK(parse_string("18446744073709551615").parse().get() == 18446744073709551615u); } } @@ -259,85 +266,85 @@ TEST_CASE("parser class") { SECTION("without exponent") { - CHECK(json::parser("-128.5").parse() == json(-128.5)); - CHECK(json::parser("0.999").parse() == json(0.999)); - CHECK(json::parser("128.5").parse() == json(128.5)); - CHECK(json::parser("-0.0").parse() == json(-0.0)); + CHECK(parse_string("-128.5").parse() == json(-128.5)); + CHECK(parse_string("0.999").parse() == json(0.999)); + CHECK(parse_string("128.5").parse() == json(128.5)); + CHECK(parse_string("-0.0").parse() == json(-0.0)); } SECTION("with exponent") { - CHECK(json::parser("-128.5E3").parse() == json(-128.5E3)); - CHECK(json::parser("-128.5E-3").parse() == json(-128.5E-3)); - CHECK(json::parser("-0.0e1").parse() == json(-0.0e1)); - CHECK(json::parser("-0.0E1").parse() == json(-0.0e1)); + CHECK(parse_string("-128.5E3").parse() == json(-128.5E3)); + CHECK(parse_string("-128.5E-3").parse() == json(-128.5E-3)); + CHECK(parse_string("-0.0e1").parse() == json(-0.0e1)); + CHECK(parse_string("-0.0E1").parse() == json(-0.0e1)); } } SECTION("overflow") { // overflows during parsing yield an exception - CHECK_THROWS_AS(json::parser("1.18973e+4932").parse() == json(), json::out_of_range); - CHECK_THROWS_WITH(json::parser("1.18973e+4932").parse() == json(), + CHECK_THROWS_AS(parse_string("1.18973e+4932").parse() == json(), json::out_of_range); + CHECK_THROWS_WITH(parse_string("1.18973e+4932").parse() == json(), "[json.exception.out_of_range.406] number overflow parsing '1.18973e+4932'"); } SECTION("invalid numbers") { - CHECK_THROWS_AS(json::parser("01").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("--1").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("1.").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("1E").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("1E-").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("1.E1").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("-1E").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("-0E#").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("-0E-#").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("-0#").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("-0.0:").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("-0.0Z").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("-0E123:").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("-0e0-:").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("-0e-:").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("-0f").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("01").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("--1").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("1.").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("1E").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("1E-").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("1.E1").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("-1E").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("-0E#").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("-0E-#").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("-0#").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("-0.0:").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("-0.0Z").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("-0E123:").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("-0e0-:").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("-0e-:").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("-0f").parse(), json::parse_error); // numbers must not begin with "+" - CHECK_THROWS_AS(json::parser("+1").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("+0").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("+1").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("+0").parse(), json::parse_error); - CHECK_THROWS_WITH(json::parser("01").parse(), + CHECK_THROWS_WITH(parse_string("01").parse(), "[json.exception.parse_error.101] parse error at 2: syntax error - unexpected number literal; expected end of input"); - CHECK_THROWS_WITH(json::parser("-01").parse(), + CHECK_THROWS_WITH(parse_string("-01").parse(), "[json.exception.parse_error.101] parse error at 3: syntax error - unexpected number literal; expected end of input"); - CHECK_THROWS_WITH(json::parser("--1").parse(), + CHECK_THROWS_WITH(parse_string("--1").parse(), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid number; expected digit after '-'; last read '--'"); - CHECK_THROWS_WITH(json::parser("1.").parse(), + CHECK_THROWS_WITH(parse_string("1.").parse(), "[json.exception.parse_error.101] parse error at 3: syntax error - invalid number; expected digit after '.'; last read '1.'"); - CHECK_THROWS_WITH(json::parser("1E").parse(), + CHECK_THROWS_WITH(parse_string("1E").parse(), "[json.exception.parse_error.101] parse error at 3: syntax error - invalid number; expected '+', '-', or digit after exponent; last read '1E'"); - CHECK_THROWS_WITH(json::parser("1E-").parse(), + CHECK_THROWS_WITH(parse_string("1E-").parse(), "[json.exception.parse_error.101] parse error at 4: syntax error - invalid number; expected digit after exponent sign; last read '1E-'"); - CHECK_THROWS_WITH(json::parser("1.E1").parse(), + CHECK_THROWS_WITH(parse_string("1.E1").parse(), "[json.exception.parse_error.101] parse error at 3: syntax error - invalid number; expected digit after '.'; last read '1.E'"); - CHECK_THROWS_WITH(json::parser("-1E").parse(), + CHECK_THROWS_WITH(parse_string("-1E").parse(), "[json.exception.parse_error.101] parse error at 4: syntax error - invalid number; expected '+', '-', or digit after exponent; last read '-1E'"); - CHECK_THROWS_WITH(json::parser("-0E#").parse(), + CHECK_THROWS_WITH(parse_string("-0E#").parse(), "[json.exception.parse_error.101] parse error at 4: syntax error - invalid number; expected '+', '-', or digit after exponent; last read '-0E#'"); - CHECK_THROWS_WITH(json::parser("-0E-#").parse(), + CHECK_THROWS_WITH(parse_string("-0E-#").parse(), "[json.exception.parse_error.101] parse error at 5: syntax error - invalid number; expected digit after exponent sign; last read '-0E-#'"); - CHECK_THROWS_WITH(json::parser("-0#").parse(), + CHECK_THROWS_WITH(parse_string("-0#").parse(), "[json.exception.parse_error.101] parse error at 3: syntax error - invalid literal; last read: '-0#'; expected end of input"); - CHECK_THROWS_WITH(json::parser("-0.0:").parse(), + CHECK_THROWS_WITH(parse_string("-0.0:").parse(), "[json.exception.parse_error.101] parse error at 5: syntax error - unexpected ':'; expected end of input"); - CHECK_THROWS_WITH(json::parser("-0.0Z").parse(), + CHECK_THROWS_WITH(parse_string("-0.0Z").parse(), "[json.exception.parse_error.101] parse error at 5: syntax error - invalid literal; last read: '-0.0Z'; expected end of input"); - CHECK_THROWS_WITH(json::parser("-0E123:").parse(), + CHECK_THROWS_WITH(parse_string("-0E123:").parse(), "[json.exception.parse_error.101] parse error at 7: syntax error - unexpected ':'; expected end of input"); - CHECK_THROWS_WITH(json::parser("-0e0-:").parse(), + CHECK_THROWS_WITH(parse_string("-0e0-:").parse(), "[json.exception.parse_error.101] parse error at 6: syntax error - invalid number; expected digit after '-'; last read: '-:'; expected end of input"); - CHECK_THROWS_WITH(json::parser("-0e-:").parse(), + CHECK_THROWS_WITH(parse_string("-0e-:").parse(), "[json.exception.parse_error.101] parse error at 5: syntax error - invalid number; expected digit after exponent sign; last read '-0e-:'"); - CHECK_THROWS_WITH(json::parser("-0f").parse(), + CHECK_THROWS_WITH(parse_string("-0f").parse(), "[json.exception.parse_error.101] parse error at 4: syntax error - invalid literal; expected 'false'; last read: '-0f'; expected end of input"); } } @@ -346,152 +353,152 @@ TEST_CASE("parser class") SECTION("parse errors") { // unexpected end of number - CHECK_THROWS_AS(json::parser("0.").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("-").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("--").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("-0.").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("-.").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("-:").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("0.:").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("e.").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("1e.").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("1e/").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("1e:").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("1E.").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("1E/").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("1E:").parse(), json::parse_error); - CHECK_THROWS_WITH(json::parser("0.").parse(), + CHECK_THROWS_AS(parse_string("0.").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("-").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("--").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("-0.").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("-.").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("-:").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("0.:").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("e.").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("1e.").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("1e/").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("1e:").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("1E.").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("1E/").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("1E:").parse(), json::parse_error); + CHECK_THROWS_WITH(parse_string("0.").parse(), "[json.exception.parse_error.101] parse error at 3: syntax error - invalid number; expected digit after '.'; last read '0.'"); - CHECK_THROWS_WITH(json::parser("-").parse(), + CHECK_THROWS_WITH(parse_string("-").parse(), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid number; expected digit after '-'; last read '-'"); - CHECK_THROWS_WITH(json::parser("--").parse(), + CHECK_THROWS_WITH(parse_string("--").parse(), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid number; expected digit after '-'; last read '--'"); - CHECK_THROWS_WITH(json::parser("-0.").parse(), + CHECK_THROWS_WITH(parse_string("-0.").parse(), "[json.exception.parse_error.101] parse error at 4: syntax error - invalid number; expected digit after '.'; last read '-0.'"); - CHECK_THROWS_WITH(json::parser("-.").parse(), + CHECK_THROWS_WITH(parse_string("-.").parse(), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid number; expected digit after '-'; last read '-.'"); - CHECK_THROWS_WITH(json::parser("-:").parse(), + CHECK_THROWS_WITH(parse_string("-:").parse(), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid number; expected digit after '-'; last read '-:'"); - CHECK_THROWS_WITH(json::parser("0.:").parse(), + CHECK_THROWS_WITH(parse_string("0.:").parse(), "[json.exception.parse_error.101] parse error at 3: syntax error - invalid number; expected digit after '.'; last read '0.:'"); - CHECK_THROWS_WITH(json::parser("e.").parse(), + CHECK_THROWS_WITH(parse_string("e.").parse(), "[json.exception.parse_error.101] parse error at 1: syntax error - invalid literal; last read 'e'"); - CHECK_THROWS_WITH(json::parser("1e.").parse(), + CHECK_THROWS_WITH(parse_string("1e.").parse(), "[json.exception.parse_error.101] parse error at 3: syntax error - invalid number; expected '+', '-', or digit after exponent; last read '1e.'"); - CHECK_THROWS_WITH(json::parser("1e/").parse(), + CHECK_THROWS_WITH(parse_string("1e/").parse(), "[json.exception.parse_error.101] parse error at 3: syntax error - invalid number; expected '+', '-', or digit after exponent; last read '1e/'"); - CHECK_THROWS_WITH(json::parser("1e:").parse(), + CHECK_THROWS_WITH(parse_string("1e:").parse(), "[json.exception.parse_error.101] parse error at 3: syntax error - invalid number; expected '+', '-', or digit after exponent; last read '1e:'"); - CHECK_THROWS_WITH(json::parser("1E.").parse(), + CHECK_THROWS_WITH(parse_string("1E.").parse(), "[json.exception.parse_error.101] parse error at 3: syntax error - invalid number; expected '+', '-', or digit after exponent; last read '1E.'"); - CHECK_THROWS_WITH(json::parser("1E/").parse(), + CHECK_THROWS_WITH(parse_string("1E/").parse(), "[json.exception.parse_error.101] parse error at 3: syntax error - invalid number; expected '+', '-', or digit after exponent; last read '1E/'"); - CHECK_THROWS_WITH(json::parser("1E:").parse(), + CHECK_THROWS_WITH(parse_string("1E:").parse(), "[json.exception.parse_error.101] parse error at 3: syntax error - invalid number; expected '+', '-', or digit after exponent; last read '1E:'"); // unexpected end of null - CHECK_THROWS_AS(json::parser("n").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("nu").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("nul").parse(), json::parse_error); - CHECK_THROWS_WITH(json::parser("n").parse(), + CHECK_THROWS_AS(parse_string("n").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("nu").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("nul").parse(), json::parse_error); + CHECK_THROWS_WITH(parse_string("n").parse(), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid literal; expected 'null'; last read 'n'"); - CHECK_THROWS_WITH(json::parser("nu").parse(), + CHECK_THROWS_WITH(parse_string("nu").parse(), "[json.exception.parse_error.101] parse error at 3: syntax error - invalid literal; expected 'null'; last read 'nu'"); - CHECK_THROWS_WITH(json::parser("nul").parse(), + CHECK_THROWS_WITH(parse_string("nul").parse(), "[json.exception.parse_error.101] parse error at 4: syntax error - invalid literal; expected 'null'; last read 'nul'"); // unexpected end of true - CHECK_THROWS_AS(json::parser("t").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("tr").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("tru").parse(), json::parse_error); - CHECK_THROWS_WITH(json::parser("t").parse(), + CHECK_THROWS_AS(parse_string("t").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("tr").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("tru").parse(), json::parse_error); + CHECK_THROWS_WITH(parse_string("t").parse(), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid literal; expected 'true'; last read 't'"); - CHECK_THROWS_WITH(json::parser("tr").parse(), + CHECK_THROWS_WITH(parse_string("tr").parse(), "[json.exception.parse_error.101] parse error at 3: syntax error - invalid literal; expected 'true'; last read 'tr'"); - CHECK_THROWS_WITH(json::parser("tru").parse(), + CHECK_THROWS_WITH(parse_string("tru").parse(), "[json.exception.parse_error.101] parse error at 4: syntax error - invalid literal; expected 'true'; last read 'tru'"); // unexpected end of false - CHECK_THROWS_AS(json::parser("f").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("fa").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("fal").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("fals").parse(), json::parse_error); - CHECK_THROWS_WITH(json::parser("f").parse(), + CHECK_THROWS_AS(parse_string("f").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("fa").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("fal").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("fals").parse(), json::parse_error); + CHECK_THROWS_WITH(parse_string("f").parse(), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid literal; expected 'false'; last read 'f'"); - CHECK_THROWS_WITH(json::parser("fa").parse(), + CHECK_THROWS_WITH(parse_string("fa").parse(), "[json.exception.parse_error.101] parse error at 3: syntax error - invalid literal; expected 'false'; last read 'fa'"); - CHECK_THROWS_WITH(json::parser("fal").parse(), + CHECK_THROWS_WITH(parse_string("fal").parse(), "[json.exception.parse_error.101] parse error at 4: syntax error - invalid literal; expected 'false'; last read 'fal'"); - CHECK_THROWS_WITH(json::parser("fals").parse(), + CHECK_THROWS_WITH(parse_string("fals").parse(), "[json.exception.parse_error.101] parse error at 5: syntax error - invalid literal; expected 'false'; last read 'fals'"); // missing/unexpected end of array - CHECK_THROWS_AS(json::parser("[").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("[1").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("[1,").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("[1,]").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("]").parse(), json::parse_error); - CHECK_THROWS_WITH(json::parser("[").parse(), + CHECK_THROWS_AS(parse_string("[").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("[1").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("[1,").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("[1,]").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("]").parse(), json::parse_error); + CHECK_THROWS_WITH(parse_string("[").parse(), "[json.exception.parse_error.101] parse error at 2: syntax error - unexpected end of input"); - CHECK_THROWS_WITH(json::parser("[1").parse(), + CHECK_THROWS_WITH(parse_string("[1").parse(), "[json.exception.parse_error.101] parse error at 3: syntax error - unexpected end of input; expected ']'"); - CHECK_THROWS_WITH(json::parser("[1,").parse(), + CHECK_THROWS_WITH(parse_string("[1,").parse(), "[json.exception.parse_error.101] parse error at 4: syntax error - unexpected end of input"); - CHECK_THROWS_WITH(json::parser("[1,]").parse(), + CHECK_THROWS_WITH(parse_string("[1,]").parse(), "[json.exception.parse_error.101] parse error at 4: syntax error - unexpected ']'"); - CHECK_THROWS_WITH(json::parser("]").parse(), + CHECK_THROWS_WITH(parse_string("]").parse(), "[json.exception.parse_error.101] parse error at 1: syntax error - unexpected ']'"); // missing/unexpected end of object - CHECK_THROWS_AS(json::parser("{").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("{\"foo\"").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("{\"foo\":").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("{\"foo\":}").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("{\"foo\":1,}").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("}").parse(), json::parse_error); - CHECK_THROWS_WITH(json::parser("{").parse(), + CHECK_THROWS_AS(parse_string("{").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("{\"foo\"").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("{\"foo\":").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("{\"foo\":}").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("{\"foo\":1,}").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("}").parse(), json::parse_error); + CHECK_THROWS_WITH(parse_string("{").parse(), "[json.exception.parse_error.101] parse error at 2: syntax error - unexpected end of input; expected string literal"); - CHECK_THROWS_WITH(json::parser("{\"foo\"").parse(), + CHECK_THROWS_WITH(parse_string("{\"foo\"").parse(), "[json.exception.parse_error.101] parse error at 7: syntax error - unexpected end of input; expected ':'"); - CHECK_THROWS_WITH(json::parser("{\"foo\":").parse(), + CHECK_THROWS_WITH(parse_string("{\"foo\":").parse(), "[json.exception.parse_error.101] parse error at 8: syntax error - unexpected end of input"); - CHECK_THROWS_WITH(json::parser("{\"foo\":}").parse(), + CHECK_THROWS_WITH(parse_string("{\"foo\":}").parse(), "[json.exception.parse_error.101] parse error at 8: syntax error - unexpected '}'"); - CHECK_THROWS_WITH(json::parser("{\"foo\":1,}").parse(), + CHECK_THROWS_WITH(parse_string("{\"foo\":1,}").parse(), "[json.exception.parse_error.101] parse error at 10: syntax error - unexpected '}'; expected string literal"); - CHECK_THROWS_WITH(json::parser("}").parse(), + CHECK_THROWS_WITH(parse_string("}").parse(), "[json.exception.parse_error.101] parse error at 1: syntax error - unexpected '}'"); // missing/unexpected end of string - CHECK_THROWS_AS(json::parser("\"").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("\"\\\"").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("\"\\u\"").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("\"\\u0\"").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("\"\\u01\"").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("\"\\u012\"").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("\"\\u").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("\"\\u0").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("\"\\u01").parse(), json::parse_error); - CHECK_THROWS_AS(json::parser("\"\\u012").parse(), json::parse_error); - CHECK_THROWS_WITH(json::parser("\"").parse(), + CHECK_THROWS_AS(parse_string("\"").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("\"\\\"").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("\"\\u\"").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("\"\\u0\"").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("\"\\u01\"").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("\"\\u012\"").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("\"\\u").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("\"\\u0").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("\"\\u01").parse(), json::parse_error); + CHECK_THROWS_AS(parse_string("\"\\u012").parse(), json::parse_error); + CHECK_THROWS_WITH(parse_string("\"").parse(), "[json.exception.parse_error.101] parse error at 2: syntax error - invalid string: missing closing quote; last read '\"'"); - CHECK_THROWS_WITH(json::parser("\"\\\"").parse(), + CHECK_THROWS_WITH(parse_string("\"\\\"").parse(), "[json.exception.parse_error.101] parse error at 4: syntax error - invalid string: missing closing quote; last read '\"\\\"'"); - CHECK_THROWS_WITH(json::parser("\"\\u\"").parse(), + CHECK_THROWS_WITH(parse_string("\"\\u\"").parse(), "[json.exception.parse_error.101] parse error at 4: syntax error - invalid string: '\\u' must be followed by 4 hex digits; last read '\"\\u\"'"); - CHECK_THROWS_WITH(json::parser("\"\\u0\"").parse(), + CHECK_THROWS_WITH(parse_string("\"\\u0\"").parse(), "[json.exception.parse_error.101] parse error at 5: syntax error - invalid string: '\\u' must be followed by 4 hex digits; last read '\"\\u0\"'"); - CHECK_THROWS_WITH(json::parser("\"\\u01\"").parse(), + CHECK_THROWS_WITH(parse_string("\"\\u01\"").parse(), "[json.exception.parse_error.101] parse error at 6: syntax error - invalid string: '\\u' must be followed by 4 hex digits; last read '\"\\u01\"'"); - CHECK_THROWS_WITH(json::parser("\"\\u012\"").parse(), + CHECK_THROWS_WITH(parse_string("\"\\u012\"").parse(), "[json.exception.parse_error.101] parse error at 7: syntax error - invalid string: '\\u' must be followed by 4 hex digits; last read '\"\\u012\"'"); - CHECK_THROWS_WITH(json::parser("\"\\u").parse(), + CHECK_THROWS_WITH(parse_string("\"\\u").parse(), "[json.exception.parse_error.101] parse error at 4: syntax error - invalid string: '\\u' must be followed by 4 hex digits; last read '\"\\u'"); - CHECK_THROWS_WITH(json::parser("\"\\u0").parse(), + CHECK_THROWS_WITH(parse_string("\"\\u0").parse(), "[json.exception.parse_error.101] parse error at 5: syntax error - invalid string: '\\u' must be followed by 4 hex digits; last read '\"\\u0'"); - CHECK_THROWS_WITH(json::parser("\"\\u01").parse(), + CHECK_THROWS_WITH(parse_string("\"\\u01").parse(), "[json.exception.parse_error.101] parse error at 6: syntax error - invalid string: '\\u' must be followed by 4 hex digits; last read '\"\\u01'"); - CHECK_THROWS_WITH(json::parser("\"\\u012").parse(), + CHECK_THROWS_WITH(parse_string("\"\\u012").parse(), "[json.exception.parse_error.101] parse error at 7: syntax error - invalid string: '\\u' must be followed by 4 hex digits; last read '\"\\u012'"); // invalid escapes @@ -511,7 +518,7 @@ TEST_CASE("parser class") case ('r'): case ('t'): { - CHECK_NOTHROW(json::parser(s.c_str()).parse()); + CHECK_NOTHROW(parse_string(s.c_str()).parse()); break; } @@ -524,11 +531,11 @@ TEST_CASE("parser class") // any other combination of backslash and character is invalid default: { - CHECK_THROWS_AS(json::parser(s.c_str()).parse(), json::parse_error); + CHECK_THROWS_AS(parse_string(s.c_str()).parse(), json::parse_error); // only check error message if c is not a control character if (c > 0x1f) { - CHECK_THROWS_WITH(json::parser(s.c_str()).parse(), + CHECK_THROWS_WITH(parse_string(s.c_str()).parse(), "[json.exception.parse_error.101] parse error at 3: syntax error - invalid string: forbidden character after backspace; last read '\"\\" + std::string(1, static_cast(c)) + "'"); } break; @@ -589,49 +596,49 @@ TEST_CASE("parser class") if (valid(c)) { CAPTURE(s1); - CHECK_NOTHROW(json::parser(s1.c_str()).parse()); + CHECK_NOTHROW(parse_string(s1.c_str()).parse()); CAPTURE(s2); - CHECK_NOTHROW(json::parser(s2.c_str()).parse()); + CHECK_NOTHROW(parse_string(s2.c_str()).parse()); CAPTURE(s3); - CHECK_NOTHROW(json::parser(s3.c_str()).parse()); + CHECK_NOTHROW(parse_string(s3.c_str()).parse()); CAPTURE(s4); - CHECK_NOTHROW(json::parser(s4.c_str()).parse()); + CHECK_NOTHROW(parse_string(s4.c_str()).parse()); } else { CAPTURE(s1); - CHECK_THROWS_AS(json::parser(s1.c_str()).parse(), json::parse_error); + CHECK_THROWS_AS(parse_string(s1.c_str()).parse(), json::parse_error); // only check error message if c is not a control character if (c > 0x1f) { - CHECK_THROWS_WITH(json::parser(s1.c_str()).parse(), + CHECK_THROWS_WITH(parse_string(s1.c_str()).parse(), "[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) + "'"); } CAPTURE(s2); - CHECK_THROWS_AS(json::parser(s2.c_str()).parse(), json::parse_error); + CHECK_THROWS_AS(parse_string(s2.c_str()).parse(), json::parse_error); // only check error message if c is not a control character if (c > 0x1f) { - CHECK_THROWS_WITH(json::parser(s2.c_str()).parse(), + CHECK_THROWS_WITH(parse_string(s2.c_str()).parse(), "[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) + "'"); } CAPTURE(s3); - CHECK_THROWS_AS(json::parser(s3.c_str()).parse(), json::parse_error); + CHECK_THROWS_AS(parse_string(s3.c_str()).parse(), json::parse_error); // only check error message if c is not a control character if (c > 0x1f) { - CHECK_THROWS_WITH(json::parser(s3.c_str()).parse(), + CHECK_THROWS_WITH(parse_string(s3.c_str()).parse(), "[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) + "'"); } CAPTURE(s4); - CHECK_THROWS_AS(json::parser(s4.c_str()).parse(), json::parse_error); + CHECK_THROWS_AS(parse_string(s4.c_str()).parse(), json::parse_error); // only check error message if c is not a control character if (c > 0x1f) { - CHECK_THROWS_WITH(json::parser(s4.c_str()).parse(), + CHECK_THROWS_WITH(parse_string(s4.c_str()).parse(), "[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) + "'"); } } @@ -657,12 +664,12 @@ TEST_CASE("parser class") SECTION("tests found by mutate++") { // test case to make sure no comma preceeds the first key - CHECK_THROWS_AS(json::parser("{,\"key\": false}").parse(), json::parse_error); - CHECK_THROWS_WITH(json::parser("{,\"key\": false}").parse(), + CHECK_THROWS_AS(parse_string("{,\"key\": false}").parse(), json::parse_error); + CHECK_THROWS_WITH(parse_string("{,\"key\": false}").parse(), "[json.exception.parse_error.101] parse error at 2: syntax error - unexpected ','; expected string literal"); // test case to make sure an object is properly closed - CHECK_THROWS_AS(json::parser("[{\"key\": false true]").parse(), json::parse_error); - CHECK_THROWS_WITH(json::parser("[{\"key\": false true]").parse(), + CHECK_THROWS_AS(parse_string("[{\"key\": false true]").parse(), json::parse_error); + CHECK_THROWS_WITH(parse_string("[{\"key\": false true]").parse(), "[json.exception.parse_error.101] parse error at 19: syntax error - unexpected true literal; expected '}'"); // test case to make sure the callback is properly evaluated after reading a key @@ -850,42 +857,42 @@ TEST_CASE("parser class") SECTION("from std::vector") { std::vector v = {'t', 'r', 'u', 'e'}; - CHECK(json::parser(std::begin(v), std::end(v)).parse() == json(true)); + CHECK(json::parser(json::input_adapter::create(std::begin(v), std::end(v))).parse() == json(true)); } SECTION("from std::array") { std::array v { {'t', 'r', 'u', 'e'} }; - CHECK(json::parser(std::begin(v), std::end(v)).parse() == json(true)); + CHECK(json::parser(json::input_adapter::create(std::begin(v), std::end(v))).parse() == json(true)); } SECTION("from array") { uint8_t v[] = {'t', 'r', 'u', 'e'}; - CHECK(json::parser(std::begin(v), std::end(v)).parse() == json(true)); + CHECK(json::parser(json::input_adapter::create(std::begin(v), std::end(v))).parse() == json(true)); } SECTION("from char literal") { - CHECK(json::parser("true").parse() == json(true)); + CHECK(parse_string("true").parse() == json(true)); } SECTION("from std::string") { std::string v = {'t', 'r', 'u', 'e'}; - CHECK(json::parser(std::begin(v), std::end(v)).parse() == json(true)); + CHECK(json::parser(json::input_adapter::create(std::begin(v), std::end(v))).parse() == json(true)); } SECTION("from std::initializer_list") { std::initializer_list v = {'t', 'r', 'u', 'e'}; - CHECK(json::parser(std::begin(v), std::end(v)).parse() == json(true)); + CHECK(json::parser(json::input_adapter::create(std::begin(v), std::end(v))).parse() == json(true)); } SECTION("from std::valarray") { std::valarray v = {'t', 'r', 'u', 'e'}; - CHECK(json::parser(std::begin(v), std::end(v)).parse() == json(true)); + CHECK(json::parser(json::input_adapter::create(std::begin(v), std::end(v))).parse() == json(true)); } } }