🔥 replaced acceptor with SAX parser

This commit is contained in:
Niels Lohmann 2018-03-07 22:40:48 +01:00
parent 303a0c5843
commit 8b379948d0
No known key found for this signature in database
GPG key ID: 7F3CEA63AE251B69
3 changed files with 154 additions and 228 deletions

View file

@ -275,5 +275,79 @@ class json_sax_dom_parser : public json_sax<BasicJsonType>
const bool allow_exceptions = true;
};
template<typename BasicJsonType>
class json_sax_acceptor : public json_sax<BasicJsonType>
{
public:
using number_integer_t = typename BasicJsonType::number_integer_t;
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
using number_float_t = typename BasicJsonType::number_float_t;
bool null() override
{
return true;
}
bool boolean(bool) override
{
return true;
}
bool number_integer(number_integer_t) override
{
return true;
}
bool number_unsigned(number_unsigned_t) override
{
return true;
}
bool number_float(number_float_t, const std::string&) override
{
return true;
}
bool string(std::string&&) override
{
return true;
}
bool start_object(std::size_t) override
{
return true;
}
bool key(std::string&&) override
{
return true;
}
bool end_object() override
{
return true;
}
bool start_array(std::size_t) override
{
return true;
}
bool end_array() override
{
return true;
}
bool binary(const std::vector<uint8_t>&) override
{
return true;
}
bool parse_error(std::size_t, const std::string&, const std::string&) override
{
return false;
}
};
}

View file

@ -137,7 +137,9 @@ class parser
*/
bool accept(const bool strict = true)
{
if (not accept_internal())
json_sax_acceptor<BasicJsonType> sax_acceptor;
if (not sax_parse_internal(&sax_acceptor))
{
return false;
}
@ -436,119 +438,6 @@ class parser
}
}
/*!
@brief the actual acceptor
@invariant 1. The last token is not yet processed. Therefore, the caller
of this function must make sure a token has been read.
2. When this function returns, the last token is processed.
That is, the last read character was already considered.
This invariant makes sure that no token needs to be "unput".
*/
bool accept_internal()
{
switch (last_token)
{
case token_type::begin_object:
{
// read next token
get_token();
// closing } -> we are done
if (last_token == token_type::end_object)
{
return true;
}
// parse values
while (true)
{
// parse key
if (last_token != token_type::value_string)
{
return false;
}
// parse separator (:)
get_token();
if (last_token != token_type::name_separator)
{
return false;
}
// parse value
get_token();
if (not accept_internal())
{
return false;
}
// comma -> next value
get_token();
if (last_token == token_type::value_separator)
{
get_token();
continue;
}
// closing }
return (last_token == token_type::end_object);
}
}
case token_type::begin_array:
{
// read next token
get_token();
// closing ] -> we are done
if (last_token == token_type::end_array)
{
return true;
}
// parse values
while (true)
{
// parse value
if (not accept_internal())
{
return false;
}
// comma -> next value
get_token();
if (last_token == token_type::value_separator)
{
get_token();
continue;
}
// closing ]
return (last_token == token_type::end_array);
}
}
case token_type::value_float:
{
// reject infinity or NAN
return std::isfinite(m_lexer.get_number_float());
}
case token_type::literal_false:
case token_type::literal_null:
case token_type::literal_true:
case token_type::value_integer:
case token_type::value_string:
case token_type::value_unsigned:
return true;
default: // the last token was unexpected
return false;
}
}
bool sax_parse_internal(json_sax_t* sax)
{
switch (last_token)

View file

@ -3409,6 +3409,80 @@ class json_sax_dom_parser : public json_sax<BasicJsonType>
const bool allow_exceptions = true;
};
template<typename BasicJsonType>
class json_sax_acceptor : public json_sax<BasicJsonType>
{
public:
using number_integer_t = typename BasicJsonType::number_integer_t;
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
using number_float_t = typename BasicJsonType::number_float_t;
bool null() override
{
return true;
}
bool boolean(bool) override
{
return true;
}
bool number_integer(number_integer_t) override
{
return true;
}
bool number_unsigned(number_unsigned_t) override
{
return true;
}
bool number_float(number_float_t, const std::string&) override
{
return true;
}
bool string(std::string&&) override
{
return true;
}
bool start_object(std::size_t) override
{
return true;
}
bool key(std::string&&) override
{
return true;
}
bool end_object() override
{
return true;
}
bool start_array(std::size_t) override
{
return true;
}
bool end_array() override
{
return true;
}
bool binary(const std::vector<uint8_t>&) override
{
return true;
}
bool parse_error(std::size_t, const std::string&, const std::string&) override
{
return false;
}
};
}
@ -3540,7 +3614,9 @@ class parser
*/
bool accept(const bool strict = true)
{
if (not accept_internal())
json_sax_acceptor<BasicJsonType> sax_acceptor;
if (not sax_parse_internal(&sax_acceptor))
{
return false;
}
@ -3839,119 +3915,6 @@ class parser
}
}
/*!
@brief the actual acceptor
@invariant 1. The last token is not yet processed. Therefore, the caller
of this function must make sure a token has been read.
2. When this function returns, the last token is processed.
That is, the last read character was already considered.
This invariant makes sure that no token needs to be "unput".
*/
bool accept_internal()
{
switch (last_token)
{
case token_type::begin_object:
{
// read next token
get_token();
// closing } -> we are done
if (last_token == token_type::end_object)
{
return true;
}
// parse values
while (true)
{
// parse key
if (last_token != token_type::value_string)
{
return false;
}
// parse separator (:)
get_token();
if (last_token != token_type::name_separator)
{
return false;
}
// parse value
get_token();
if (not accept_internal())
{
return false;
}
// comma -> next value
get_token();
if (last_token == token_type::value_separator)
{
get_token();
continue;
}
// closing }
return (last_token == token_type::end_object);
}
}
case token_type::begin_array:
{
// read next token
get_token();
// closing ] -> we are done
if (last_token == token_type::end_array)
{
return true;
}
// parse values
while (true)
{
// parse value
if (not accept_internal())
{
return false;
}
// comma -> next value
get_token();
if (last_token == token_type::value_separator)
{
get_token();
continue;
}
// closing ]
return (last_token == token_type::end_array);
}
}
case token_type::value_float:
{
// reject infinity or NAN
return std::isfinite(m_lexer.get_number_float());
}
case token_type::literal_false:
case token_type::literal_null:
case token_type::literal_true:
case token_type::value_integer:
case token_type::value_string:
case token_type::value_unsigned:
return true;
default: // the last token was unexpected
return false;
}
}
bool sax_parse_internal(json_sax_t* sax)
{
switch (last_token)