🔨 simplified interface for parser, lexer, and binary_reader

These classes are now constructed with an interface adapter. This moves
complexity from various places into the interface adapter class, or to
some factories which now implement the different flavors of input.

Furthermore, input adapters are kept in std::shared_ptr to avoid the
need of manual deletion.
This commit is contained in:
Niels Lohmann 2017-04-09 19:28:15 +02:00
parent 6f99d5b2e9
commit 186a9fd44d
No known key found for this signature in database
GPG key ID: 7F3CEA63AE251B69
3 changed files with 409 additions and 386 deletions

View file

@ -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((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((json::lexer("-0", 2).scan() == json::lexer::token_type::value_integer));
CHECK((json::lexer("-1", 2).scan() == json::lexer::token_type::value_integer));
CHECK((scan_string("-0") == json::lexer::token_type::value_integer));
CHECK((scan_string("-1") == 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("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<char>(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