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:
Niels Lohmann 2017-07-22 15:18:38 +02:00
parent f513c46749
commit c7a69ae03e
No known key found for this signature in database
GPG key ID: 7F3CEA63AE251B69
2 changed files with 527 additions and 494 deletions

View file

@ -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