🔥 replaced acceptor with SAX parser
This commit is contained in:
parent
303a0c5843
commit
8b379948d0
3 changed files with 154 additions and 228 deletions
|
@ -275,5 +275,79 @@ class json_sax_dom_parser : public json_sax<BasicJsonType>
|
||||||
const bool allow_exceptions = true;
|
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;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -137,7 +137,9 @@ class parser
|
||||||
*/
|
*/
|
||||||
bool accept(const bool strict = true)
|
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;
|
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)
|
bool sax_parse_internal(json_sax_t* sax)
|
||||||
{
|
{
|
||||||
switch (last_token)
|
switch (last_token)
|
||||||
|
|
|
@ -3409,6 +3409,80 @@ class json_sax_dom_parser : public json_sax<BasicJsonType>
|
||||||
const bool allow_exceptions = true;
|
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)
|
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;
|
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)
|
bool sax_parse_internal(json_sax_t* sax)
|
||||||
{
|
{
|
||||||
switch (last_token)
|
switch (last_token)
|
||||||
|
|
Loading…
Reference in a new issue