⚡ started working on parser with provded result reference #418
Internally, the parser now writes its result into a JSON value provided as a reference. To be usable, the public interfaces need to be extended.
This commit is contained in:
parent
f513c46749
commit
c7a69ae03e
2 changed files with 527 additions and 494 deletions
98
src/json.hpp
98
src/json.hpp
|
@ -3108,18 +3108,18 @@ class parser
|
||||||
@brief public parser interface
|
@brief public parser interface
|
||||||
|
|
||||||
@param[in] strict whether to expect the last token to be EOF
|
@param[in] strict whether to expect the last token to be EOF
|
||||||
@return parsed JSON value
|
@param[in,out] result parsed JSON value
|
||||||
|
|
||||||
@throw parse_error.101 in case of an unexpected token
|
@throw parse_error.101 in case of an unexpected token
|
||||||
@throw parse_error.102 if to_unicode fails or surrogate error
|
@throw parse_error.102 if to_unicode fails or surrogate error
|
||||||
@throw parse_error.103 if to_unicode fails
|
@throw parse_error.103 if to_unicode fails
|
||||||
*/
|
*/
|
||||||
BasicJsonType parse(const bool strict = true)
|
void parse(const bool strict, BasicJsonType& result)
|
||||||
{
|
{
|
||||||
// read first token
|
// read first token
|
||||||
get_token();
|
get_token();
|
||||||
|
|
||||||
BasicJsonType result = parse_internal(true);
|
parse_internal(true, result);
|
||||||
result.assert_invariant();
|
result.assert_invariant();
|
||||||
|
|
||||||
if (strict)
|
if (strict)
|
||||||
|
@ -3128,9 +3128,12 @@ class parser
|
||||||
expect(token_type::end_of_input);
|
expect(token_type::end_of_input);
|
||||||
}
|
}
|
||||||
|
|
||||||
// return parser result and replace it with null in case the
|
// set top-level value to null if it was discarded by the callback
|
||||||
// top-level value was discarded by the callback function
|
// function
|
||||||
return result.is_discarded() ? BasicJsonType() : std::move(result);
|
if (result.is_discarded())
|
||||||
|
{
|
||||||
|
result = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -3164,17 +3167,19 @@ class parser
|
||||||
@throw parse_error.102 if to_unicode fails or surrogate error
|
@throw parse_error.102 if to_unicode fails or surrogate error
|
||||||
@throw parse_error.103 if to_unicode fails
|
@throw parse_error.103 if to_unicode fails
|
||||||
*/
|
*/
|
||||||
BasicJsonType parse_internal(bool keep)
|
void parse_internal(bool keep, BasicJsonType& result)
|
||||||
{
|
{
|
||||||
auto result = BasicJsonType(value_t::discarded);
|
// start with a discarded value
|
||||||
|
if (not result.is_discarded())
|
||||||
|
{
|
||||||
|
result.m_type = value_t::discarded;
|
||||||
|
}
|
||||||
|
|
||||||
switch (last_token)
|
switch (last_token)
|
||||||
{
|
{
|
||||||
case token_type::begin_object:
|
case token_type::begin_object:
|
||||||
{
|
{
|
||||||
if (keep and (not callback or
|
if (keep and (not callback or ((keep = callback(depth++, parse_event_t::object_start, result)))))
|
||||||
((keep = callback(depth++, parse_event_t::object_start,
|
|
||||||
result)) != 0)))
|
|
||||||
{
|
{
|
||||||
// explicitly set result to object to cope with {}
|
// explicitly set result to object to cope with {}
|
||||||
result.m_type = value_t::object;
|
result.m_type = value_t::object;
|
||||||
|
@ -3187,15 +3192,15 @@ class parser
|
||||||
// closing } -> we are done
|
// closing } -> we are done
|
||||||
if (last_token == token_type::end_object)
|
if (last_token == token_type::end_object)
|
||||||
{
|
{
|
||||||
if (keep and callback and
|
if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
|
||||||
not callback(--depth, parse_event_t::object_end, result))
|
|
||||||
{
|
{
|
||||||
result = BasicJsonType(value_t::discarded);
|
result.m_type = value_t::discarded;
|
||||||
}
|
}
|
||||||
return result;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse values
|
// parse values
|
||||||
|
BasicJsonType value;
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
// store key
|
// store key
|
||||||
|
@ -3222,7 +3227,8 @@ class parser
|
||||||
|
|
||||||
// parse and add value
|
// parse and add value
|
||||||
get_token();
|
get_token();
|
||||||
auto value = parse_internal(keep);
|
value = value_t::discarded;
|
||||||
|
parse_internal(keep, value);
|
||||||
if (keep and keep_tag and not value.is_discarded())
|
if (keep and keep_tag and not value.is_discarded())
|
||||||
{
|
{
|
||||||
result[key] = std::move(value);
|
result[key] = std::move(value);
|
||||||
|
@ -3241,20 +3247,16 @@ class parser
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (keep and callback and
|
if (keep and callback and not callback(--depth, parse_event_t::object_end, result))
|
||||||
not callback(--depth, parse_event_t::object_end, result))
|
|
||||||
{
|
{
|
||||||
result = BasicJsonType(value_t::discarded);
|
result.m_type = value_t::discarded;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case token_type::begin_array:
|
case token_type::begin_array:
|
||||||
{
|
{
|
||||||
if (keep and (not callback or
|
if (keep and (not callback or ((keep = callback(depth++, parse_event_t::array_start, result)))))
|
||||||
((keep = callback(depth++, parse_event_t::array_start,
|
|
||||||
result)) != 0)))
|
|
||||||
{
|
{
|
||||||
// explicitly set result to object to cope with []
|
// explicitly set result to object to cope with []
|
||||||
result.m_type = value_t::array;
|
result.m_type = value_t::array;
|
||||||
|
@ -3267,19 +3269,19 @@ class parser
|
||||||
// closing ] -> we are done
|
// closing ] -> we are done
|
||||||
if (last_token == token_type::end_array)
|
if (last_token == token_type::end_array)
|
||||||
{
|
{
|
||||||
if (callback and
|
if (callback and not callback(--depth, parse_event_t::array_end, result))
|
||||||
not callback(--depth, parse_event_t::array_end, result))
|
|
||||||
{
|
{
|
||||||
result = BasicJsonType(value_t::discarded);
|
result.m_type = value_t::discarded;
|
||||||
}
|
}
|
||||||
return result;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse values
|
// parse values
|
||||||
|
BasicJsonType value;
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
// parse value
|
// parse value
|
||||||
auto value = parse_internal(keep);
|
parse_internal(keep, value);
|
||||||
if (keep and not value.is_discarded())
|
if (keep and not value.is_discarded())
|
||||||
{
|
{
|
||||||
result.push_back(std::move(value));
|
result.push_back(std::move(value));
|
||||||
|
@ -3298,13 +3300,11 @@ class parser
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (keep and callback and
|
if (keep and callback and not callback(--depth, parse_event_t::array_end, result))
|
||||||
not callback(--depth, parse_event_t::array_end, result))
|
|
||||||
{
|
{
|
||||||
result = BasicJsonType(value_t::discarded);
|
result.m_type = value_t::discarded;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case token_type::literal_null:
|
case token_type::literal_null:
|
||||||
|
@ -3315,7 +3315,8 @@ class parser
|
||||||
|
|
||||||
case token_type::value_string:
|
case token_type::value_string:
|
||||||
{
|
{
|
||||||
result = BasicJsonType(m_lexer.get_string());
|
result.m_type = value_t::string;
|
||||||
|
result.m_value = m_lexer.get_string();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3359,7 +3360,6 @@ class parser
|
||||||
m_lexer.get_token_string() +
|
m_lexer.get_token_string() +
|
||||||
"'"));
|
"'"));
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3378,12 +3378,10 @@ class parser
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (keep and callback and
|
if (keep and callback and not callback(depth, parse_event_t::value, result))
|
||||||
not callback(depth, parse_event_t::value, result))
|
|
||||||
{
|
{
|
||||||
result = BasicJsonType(value_t::discarded);
|
result.m_type = value_t::discarded;
|
||||||
}
|
}
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -12892,7 +12890,9 @@ class basic_json
|
||||||
static basic_json parse(const CharT s,
|
static basic_json parse(const CharT s,
|
||||||
const parser_callback_t cb = nullptr)
|
const parser_callback_t cb = nullptr)
|
||||||
{
|
{
|
||||||
return parser(detail::input_adapter_factory::create(s), cb).parse(true);
|
basic_json result;
|
||||||
|
parser(detail::input_adapter_factory::create(s), cb).parse(true, result);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename CharT, typename std::enable_if<
|
template<typename CharT, typename std::enable_if<
|
||||||
|
@ -12935,7 +12935,9 @@ class basic_json
|
||||||
static basic_json parse(std::istream& i,
|
static basic_json parse(std::istream& i,
|
||||||
const parser_callback_t cb = nullptr)
|
const parser_callback_t cb = nullptr)
|
||||||
{
|
{
|
||||||
return parser(detail::input_adapter_factory::create(i), cb).parse(true);
|
basic_json result;
|
||||||
|
parser(detail::input_adapter_factory::create(i), cb).parse(true, result);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool accept(std::istream& i)
|
static bool accept(std::istream& i)
|
||||||
|
@ -12949,7 +12951,9 @@ class basic_json
|
||||||
static basic_json parse(std::istream&& i,
|
static basic_json parse(std::istream&& i,
|
||||||
const parser_callback_t cb = nullptr)
|
const parser_callback_t cb = nullptr)
|
||||||
{
|
{
|
||||||
return parser(detail::input_adapter_factory::create(i), cb).parse(true);
|
basic_json result;
|
||||||
|
parser(detail::input_adapter_factory::create(i), cb).parse(true, result);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool accept(std::istream&& i)
|
static bool accept(std::istream&& i)
|
||||||
|
@ -13009,7 +13013,9 @@ class basic_json
|
||||||
static basic_json parse(IteratorType first, IteratorType last,
|
static basic_json parse(IteratorType first, IteratorType last,
|
||||||
const parser_callback_t cb = nullptr)
|
const parser_callback_t cb = nullptr)
|
||||||
{
|
{
|
||||||
return parser(detail::input_adapter_factory::create(first, last), cb).parse(true);
|
basic_json result;
|
||||||
|
parser(detail::input_adapter_factory::create(first, last), cb).parse(true, result);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class IteratorType, typename std::enable_if<
|
template<class IteratorType, typename std::enable_if<
|
||||||
|
@ -13100,7 +13106,7 @@ class basic_json
|
||||||
JSON_DEPRECATED
|
JSON_DEPRECATED
|
||||||
friend std::istream& operator<<(basic_json& j, std::istream& i)
|
friend std::istream& operator<<(basic_json& j, std::istream& i)
|
||||||
{
|
{
|
||||||
j = parser(detail::input_adapter_factory::create(i)).parse(false);
|
parser(detail::input_adapter_factory::create(i)).parse(false, j);
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13131,7 +13137,7 @@ class basic_json
|
||||||
*/
|
*/
|
||||||
friend std::istream& operator>>(std::istream& i, basic_json& j)
|
friend std::istream& operator>>(std::istream& i, basic_json& j)
|
||||||
{
|
{
|
||||||
j = parser(detail::input_adapter_factory::create(i)).parse(false);
|
parser(detail::input_adapter_factory::create(i)).parse(false, j);
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue