Skip to content
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
88 commits
Select commit Hold shift + click to select a range
7f545a8
Normalize the words "position" and "end"
jkeiser Mar 20, 2021
a334303
Don't step off the end of the index buffer
jkeiser Mar 21, 2021
02762fa
Split ondemand_object_tests into smaller files
jkeiser Mar 21, 2021
09601eb
Add __SIMDJSON_CHECK_EOF feature flag
jkeiser Mar 22, 2021
1fbd604
This adds "guarded" (i.e., memory-safe) number parsing routines.
lemire Mar 23, 2021
081f954
Adding potentially useless definition.
lemire Mar 23, 2021
42c8541
Adding the functions that I meant to add earlier.
lemire Mar 23, 2021
4d0f102
Merge pull request #1516 from simdjson/dlemire/guarded_number_parsing
jkeiser Mar 31, 2021
d7b08c8
Merge branch 'master' into jkeiser/no-padding
lemire Apr 23, 2021
76f7e4a
Merge branch 'master' into jkeiser/no-padding
lemire May 8, 2021
595c628
Merge branch 'master' into jkeiser/no-padding
lemire May 27, 2021
dadfb51
Minor correction.
lemire May 27, 2021
930b0be
Missing #ifdef SIMDJSON_DEVELOPMENT_CHECKS
lemire May 27, 2021
c0fb5f7
Another merge issue.
lemire May 28, 2021
0c14707
Merge branch 'master' into jkeiser/no-padding
lemire May 28, 2021
0d8f6f5
Merging again. Fixing issue.
lemire May 28, 2021
10a7b9b
Merge branch 'master' into jkeiser/no-padding
lemire Jun 4, 2021
633784a
Merge issue
jkeiser Jun 6, 2021
eda0f19
Don't allocate when parsing root number
jkeiser Jun 6, 2021
da4de2e
Don't read padding at all for root booleans and numbers
jkeiser Jun 6, 2021
b02aedb
Don't use padding parsing booleans
jkeiser Jun 6, 2021
ba0406f
Minor changes to compilation test.
lemire Jun 7, 2021
f45c59f
I suspect that sanitizers might increase stack usage, to combat that …
lemire Jun 8, 2021
bab51e5
Remove unlikely from null / bool parsing
jkeiser Jun 19, 2021
6ba9ad3
Remove need for padding from SIMD string parsing
jkeiser Jun 19, 2021
45fbd8c
Make len available to any dom_parser_implementation user
jkeiser Jun 21, 2021
ac647e6
Don't change the order of fields to avoid perf changes
jkeiser Jun 21, 2021
42a31ad
Fix ARM compile errors
jkeiser Jun 23, 2021
6a1f8fc
Don't step off the end of the index buffer
jkeiser Mar 21, 2021
78d1cd9
Split ondemand_object_tests into smaller files
jkeiser Mar 21, 2021
9040989
Add __SIMDJSON_CHECK_EOF feature flag
jkeiser Mar 22, 2021
5a6894c
This adds "guarded" (i.e., memory-safe) number parsing routines.
lemire Mar 23, 2021
40f522a
Adding potentially useless definition.
lemire Mar 23, 2021
b3b108b
Adding the functions that I meant to add earlier.
lemire Mar 23, 2021
e5d0e92
Minor correction.
lemire May 27, 2021
4b118bd
Verifying issue.
lemire Jul 18, 2021
267e70d
Adding another case.
lemire Jul 18, 2021
3300d84
Adding type test.
lemire Jul 19, 2021
3c5c2d2
This backports (isolate) a fix by jkeiser of issue 1632.
lemire Jul 19, 2021
f364e35
Minor fixes.
lemire Jul 19, 2021
e8e731a
Merge branch 'master' into dlemire/backport_jkeiser_fix_for_issue1632
lemire Jul 19, 2021
a349969
Adding a duplicate of the existing test.
lemire Jul 19, 2021
8b2bff9
Messy temporary work.
lemire Jul 19, 2021
df24da3
Cleaning.
lemire Jul 19, 2021
4501aeb
Disabling a couple of asserts.
lemire Jul 19, 2021
2e688a2
Removing two other asserts.
lemire Jul 19, 2021
9cace04
Adding more tests.
lemire Jul 19, 2021
d0e2a7f
Minor fixes
lemire Jul 19, 2021
c3f7eff
Adding some commentary
lemire Jul 19, 2021
7dcd43e
Merge branch 'jkeiser/no-padding' into dlemire/nopadding
lemire Jul 21, 2021
bbeec66
Merge branch 'jkeiser/no-padding-scalar' into dlemire/nopadding
lemire Jul 21, 2021
081c3ca
Merged.
lemire Jul 22, 2021
91b8fa4
Fixing a CI issue.
lemire Jul 22, 2021
ca9391c
Let us run more CI tests.
lemire Jul 22, 2021
e4bba2d
Do not needlessly do perf checks.
lemire Jul 22, 2021
24068a0
Merge branch 'master' into dlemire/backport_jkeiser_fix_for_issue1632
lemire Jul 22, 2021
57ca29e
Merge branch 'dlemire/backport_jkeiser_fix_for_issue1632' into dlemir…
lemire Jul 22, 2021
f2d419d
Basic guarding.
lemire Jul 22, 2021
1fe50cb
Trimming.
lemire Jul 22, 2021
0e8b686
Merge branch 'dlemire/backport_jkeiser_fix_for_issue1632' into dlemir…
lemire Jul 22, 2021
d7770e9
Disabling 'json[N-1]' test.
lemire Jul 22, 2021
bb0ed22
Removing some of the padding in the tests.
lemire Jul 22, 2021
70a0d62
Merge branch 'dlemire/backport_jkeiser_fix_for_issue1632' into dlemir…
lemire Jul 22, 2021
b1a3943
We should now be able to iterate over a string_view.
lemire Jul 22, 2021
910686f
Merge branch 'dlemire/nopadding' of github.com:simdjson/simdjson into…
lemire Jul 22, 2021
dc86daa
Removing the padding.
lemire Jul 22, 2021
21845f1
Documenting iterate_many + removing remnants of padding in On Demand.
lemire Jul 23, 2021
1a433fc
Enabling a broad range of tests.
lemire Jul 23, 2021
b12014f
Let us try some setups in debug mode (for faster builds).
lemire Jul 23, 2021
8ce1e52
Merge branch 'master' into dlemire/nopadding
lemire Jul 23, 2021
f6fc786
Disabling some change made to the DOM kernel which was evidently made…
lemire Jul 23, 2021
7175731
Removing the special-case
lemire Jul 23, 2021
757db1b
Removing padding from DOM API.
lemire Jul 23, 2021
d72cba2
Minor tweaks.
lemire Jul 23, 2021
a7ff410
Various fixes for the number parsing in the DOM front-end. Basically,…
lemire Jul 23, 2021
13055a4
Using an alternative instrinsic.
lemire Jul 23, 2021
dc66d61
Fixing comment.
lemire Jul 23, 2021
68df233
Removing a couple of tests from circle ci.
lemire Jul 23, 2021
bbc9bd0
Some tweaking.
lemire Jul 24, 2021
d8b6a8c
Merge branch 'dlemire/nopadding' of github.com:simdjson/simdjson into…
lemire Jul 24, 2021
2ceca3e
More tweaking to fix problems exposed by the fuzzers.
lemire Jul 24, 2021
60b6a16
Let us stress the memory overflow in more tests.
lemire Jul 24, 2021
657489e
More fixes.
lemire Jul 24, 2021
7c8bc65
Turning on developer mode explicitly throughout.
lemire Jul 24, 2021
ce11f41
Merge branch 'dlemire/nopadding' of github.com:simdjson/simdjson into…
lemire Jul 24, 2021
b6aff44
Syncing the singleheader files.
lemire Jul 24, 2021
2907912
Guarding the peek/advance.
lemire Jul 24, 2021
450cb7b
Merge branch 'dlemire/nopadding' of github.com:simdjson/simdjson into…
lemire Jul 24, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Don't step off the end of the index buffer
  • Loading branch information
jkeiser committed Mar 21, 2021
commit a3343031192147e759e1dac5d3b8815a1f10d221
36 changes: 36 additions & 0 deletions include/simdjson/generic/ondemand/json_iterator-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ simdjson_really_inline json_iterator::json_iterator(const uint8_t *buf, ondemand
_depth{1}
{
logger::log_headers();
assert_more_tokens(1);
}

// GCC 7 warns when the first line of this function is inlined away into oblivion due to the caller
Expand All @@ -36,6 +37,7 @@ SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING
simdjson_warn_unused simdjson_really_inline error_code json_iterator::skip_child(depth_t parent_depth) noexcept {
if (depth() <= parent_depth) { return SUCCESS; }

SIMDJSON_TRY( require_tokens(1) );
switch (*advance()) {
// TODO consider whether matching braces is a requirement: if non-matching braces indicates
// *missing* braces, then future lookups are not in the object/arrays they think they are,
Expand Down Expand Up @@ -111,6 +113,17 @@ simdjson_really_inline void json_iterator::assert_at_root() const noexcept {
#endif
}

simdjson_really_inline void json_iterator::assert_more_tokens(uint32_t required_tokens) const noexcept {
assert_valid_position(token.position() + required_tokens - 1);
}

simdjson_really_inline void json_iterator::assert_valid_position(token_position position) const noexcept {
#ifndef SIMDJSON_CLANG_VISUAL_STUDIO
SIMDJSON_ASSUME( position >= &parser->implementation->structural_indexes[0] );
SIMDJSON_ASSUME( position < &parser->implementation->structural_indexes[parser->implementation->n_structural_indexes] );
#endif
}

simdjson_really_inline bool json_iterator::at_end() const noexcept {
return position() == end_position();
}
Expand All @@ -129,22 +142,42 @@ simdjson_really_inline void json_iterator::abandon() noexcept {
}

simdjson_really_inline const uint8_t *json_iterator::advance() noexcept {
assert_more_tokens();
return token.advance();
}

simdjson_really_inline simdjson_result<const uint8_t *> json_iterator::try_advance(uint32_t required_tokens) noexcept {
const uint8_t *json = token.advance();
// Check this *after* we get the pointer, since getting the pointer is more time-sensitive than the branch.
// Also resolves nicely to 0 in the common case of required_tokens == 1.
SIMDJSON_TRY( require_tokens(required_tokens - 1) );
return json;
}

simdjson_really_inline error_code json_iterator::require_tokens(uint32_t required_tokens) noexcept {
if (position() + required_tokens > end_position()) {
return report_error(TAPE_ERROR, "Document ended early");
}
return SUCCESS;
}

simdjson_really_inline const uint8_t *json_iterator::peek(int32_t delta) const noexcept {
assert_more_tokens(delta+1);
return token.peek(delta);
}

simdjson_really_inline uint32_t json_iterator::peek_length(int32_t delta) const noexcept {
assert_more_tokens(delta+1);
return token.peek_length(delta);
}

simdjson_really_inline const uint8_t *json_iterator::peek(token_position position) const noexcept {
assert_valid_position(position);
return token.peek(position);
}

simdjson_really_inline uint32_t json_iterator::peek_length(token_position position) const noexcept {
assert_valid_position(position);
return token.peek_length(position);
}

Expand Down Expand Up @@ -190,6 +223,7 @@ simdjson_really_inline error_code json_iterator::report_error(error_code _error,
simdjson_really_inline token_position json_iterator::position() const noexcept {
return token.position();
}

simdjson_really_inline void json_iterator::reenter_child(token_position position, depth_t child_depth) noexcept {
SIMDJSON_ASSUME(child_depth >= 1 && child_depth < INT32_MAX);
SIMDJSON_ASSUME(_depth == child_depth - 1);
Expand All @@ -203,9 +237,11 @@ simdjson_really_inline void json_iterator::reenter_child(token_position position
}

#ifdef SIMDJSON_DEVELOPMENT_CHECKS

simdjson_really_inline token_position json_iterator::start_position(depth_t depth) const noexcept {
return parser->start_positions[depth];
}

simdjson_really_inline void json_iterator::set_start_position(depth_t depth, token_position position) noexcept {
parser->start_positions[depth] = position;
}
Expand Down
30 changes: 29 additions & 1 deletion include/simdjson/generic/ondemand/json_iterator.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,38 @@ class json_iterator {
simdjson_really_inline void abandon() noexcept;

/**
* Advance the current token.
* Advance the current token without modifying depth.
*/
simdjson_really_inline const uint8_t *advance() noexcept;

/**
* Advance the current token by one, without modifying depth.
*
* @param requiremed_tokens The number of tokens that must exist. Only advances one token.
*
* @error TAPE_ERROR If there are not at least required_tokens tokens remaining.
*/
simdjson_really_inline simdjson_result<const uint8_t *> try_advance(uint32_t required_tokens=1) noexcept;

/**
* Return an error unless there are enough tokens left.
*
* @param required_tokens The number of tokens that must exist.
* @error TAPE_ERROR If there are not at least required_tokens tokens remaining.
*/
simdjson_really_inline error_code require_tokens(uint32_t required_tokens=1) noexcept;
/**
* Assert that there are at least the given number of tokens left.
*
* Has no effect in release builds.
*/
simdjson_really_inline void assert_more_tokens(uint32_t required_tokens=1) const noexcept;
/**
* Assert that the given position addresses an actual token (is within bounds).
*
* Has no effect in release builds.
*/
simdjson_really_inline void assert_valid_position(token_position position) const noexcept;
/**
* Get the JSON text for a given token (relative).
*
Expand Down
14 changes: 5 additions & 9 deletions include/simdjson/generic/ondemand/object-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,20 +34,16 @@ simdjson_really_inline simdjson_result<value> object::find_field(const std::stri
}

simdjson_really_inline simdjson_result<object> object::start(value_iterator &iter) noexcept {
// We don't need to know if the object is empty to start iteration, but we do want to know if there
// is an error--thus `simdjson_unused`.
simdjson_unused bool has_value;
SIMDJSON_TRY( iter.start_object().get(has_value) );
SIMDJSON_TRY( iter.start_object().error() );
return object(iter);
}
simdjson_really_inline simdjson_result<object> object::start_root(value_iterator &iter) noexcept {
simdjson_unused bool has_value;
SIMDJSON_TRY( iter.start_root_object().get(has_value) );
SIMDJSON_TRY( iter.start_root_object().error() );
return object(iter);
}
simdjson_really_inline object object::started(value_iterator &iter) noexcept {
simdjson_unused bool has_value = iter.started_object();
return iter;
simdjson_really_inline simdjson_result<object> object::started(value_iterator &iter) noexcept {
SIMDJSON_TRY( iter.started_object().error() );
return object(iter);
}
simdjson_really_inline object object::resume(const value_iterator &iter) noexcept {
return iter;
Expand Down
2 changes: 1 addition & 1 deletion include/simdjson/generic/ondemand/object.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ class object {
protected:
static simdjson_really_inline simdjson_result<object> start(value_iterator &iter) noexcept;
static simdjson_really_inline simdjson_result<object> start_root(value_iterator &iter) noexcept;
static simdjson_really_inline object started(value_iterator &iter) noexcept;
static simdjson_really_inline simdjson_result<object> started(value_iterator &iter) noexcept;
static simdjson_really_inline object resume(const value_iterator &iter) noexcept;
simdjson_really_inline object(const value_iterator &iter) noexcept;

Expand Down
4 changes: 2 additions & 2 deletions include/simdjson/generic/ondemand/token_iterator-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ namespace ondemand {

simdjson_really_inline token_iterator::token_iterator(
const uint8_t *_buf,
token_position _position
) noexcept : buf{_buf}, _position{_position}
token_position position
) noexcept : buf{_buf}, _position{position}
{
}

Expand Down
55 changes: 43 additions & 12 deletions include/simdjson/generic/ondemand/value_iterator-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,22 @@ simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator
simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator::start_root_object() noexcept {
bool result;
SIMDJSON_TRY( start_object().get(result) );
if (*_json_iter->peek_last() != '}') { return _json_iter->report_error(TAPE_ERROR, "object invalid: { at beginning of document unmatched by } at end of document"); }
if (*_json_iter->peek_last() != '}') {
return _json_iter->report_error(TAPE_ERROR, "object invalid: { at beginning of document unmatched by } at end of document");
}
return result;
}

simdjson_warn_unused simdjson_really_inline bool value_iterator::started_object() noexcept {
simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator::started_object() noexcept {
assert_at_container_start();
SIMDJSON_TRY( _json_iter->require_tokens(1) );
if (*_json_iter->peek() == '}') {
logger::log_value(*_json_iter, "empty object");
_json_iter->advance();
_json_iter->ascend_to(depth()-1);
return false;
}
logger::log_start_value(*_json_iter, "object");
SIMDJSON_TRY( _json_iter->require_tokens(3) ); // Make sure we have three tokens: "x" : value
#ifdef SIMDJSON_DEVELOPMENT_CHECKS
_json_iter->set_start_position(_depth, start_position());
#endif
Expand All @@ -42,12 +45,14 @@ simdjson_warn_unused simdjson_really_inline bool value_iterator::started_object(
simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator::has_next_field() noexcept {
assert_at_next();

SIMDJSON_TRY( error_unless_more_tokens() );
switch (*_json_iter->advance()) {
case '}':
logger::log_end_value(*_json_iter, "object");
_json_iter->ascend_to(depth()-1);
return false;
case ',':
SIMDJSON_TRY( error_unless_more_tokens(3) ); // Make sure we have three tokens: "x" : value
return true;
default:
return _json_iter->report_error(TAPE_ERROR, "Missing comma between object fields");
Expand Down Expand Up @@ -252,7 +257,7 @@ simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator
// don't check errors in this bit.)
_json_iter->reenter_child(start_position() + 1, _depth);

has_value = started_object();
SIMDJSON_TRY( started_object().get(has_value) );
while (_json_iter->position() < search_start) {
SIMDJSON_ASSUME(has_value); // we should reach search_start before ever reaching the end of the object
SIMDJSON_ASSUME( _json_iter->_depth == _depth ); // We must be at the start of a field
Expand Down Expand Up @@ -290,6 +295,7 @@ simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator
simdjson_warn_unused simdjson_really_inline simdjson_result<raw_json_string> value_iterator::field_key() noexcept {
assert_at_next();

// started_object() and has_next_field() already checked that we have a key
const uint8_t *key = _json_iter->advance();
if (*(key++) != '"') { return _json_iter->report_error(TAPE_ERROR, "Object key is not a string"); }
return raw_json_string(key);
Expand All @@ -298,6 +304,7 @@ simdjson_warn_unused simdjson_really_inline simdjson_result<raw_json_string> val
simdjson_warn_unused simdjson_really_inline error_code value_iterator::field_value() noexcept {
assert_at_next();

// started_object() and has_next_field() already checked that we have a : and a value token
if (*_json_iter->advance() != ':') { return _json_iter->report_error(TAPE_ERROR, "Missing colon in object field"); }
_json_iter->descend_to(depth()+1);
return SUCCESS;
Expand All @@ -319,13 +326,13 @@ simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator

simdjson_warn_unused simdjson_really_inline bool value_iterator::started_array() noexcept {
assert_at_container_start();
SIMDJSON_TRY( _json_iter->require_tokens(1) );
if (*_json_iter->peek() == ']') {
logger::log_value(*_json_iter, "empty array");
_json_iter->advance();
_json_iter->ascend_to(depth()-1);
return false;
}
logger::log_start_value(*_json_iter, "array");
_json_iter->descend_to(depth()+1);
#ifdef SIMDJSON_DEVELOPMENT_CHECKS
_json_iter->set_start_position(_depth, start_position());
Expand All @@ -336,12 +343,16 @@ simdjson_warn_unused simdjson_really_inline bool value_iterator::started_array()
simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator::has_next_element() noexcept {
assert_at_next();

switch (*_json_iter->advance()) {
const uint8_t *json;
logger::log_event(*this, "has_next_element");
SIMDJSON_TRY( _json_iter->try_advance().get(json) )
switch (*json) {
case ']':
logger::log_end_value(*_json_iter, "array");
_json_iter->ascend_to(depth()-1);
return false;
case ',':
SIMDJSON_TRY( _json_iter->require_tokens(1) );
_json_iter->descend_to(depth()+1);
return true;
default:
Expand Down Expand Up @@ -501,7 +512,7 @@ simdjson_really_inline uint32_t value_iterator::peek_start_length() const noexce
return _json_iter->peek_length(start_position());
}

simdjson_really_inline const uint8_t *value_iterator::advance_start(const char *type) const noexcept {
simdjson_really_inline const uint8_t *value_iterator::advance_start(const char *type) noexcept {
logger::log_value(*_json_iter, start_position(), depth(), type);
// If we're not at the position anymore, we don't want to advance the cursor.
if (!is_at_start()) { return peek_start(); }
Expand All @@ -512,7 +523,7 @@ simdjson_really_inline const uint8_t *value_iterator::advance_start(const char *
_json_iter->ascend_to(depth()-1);
return result;
}
simdjson_really_inline error_code value_iterator::advance_container_start(const char *type, const uint8_t *&json) const noexcept {
simdjson_really_inline error_code value_iterator::advance_container_start(const char *type, const uint8_t *&json) noexcept {
logger::log_start_value(*_json_iter, start_position(), depth(), type);

// If we're not at the position anymore, we don't want to advance the cursor.
Expand All @@ -524,12 +535,13 @@ simdjson_really_inline error_code value_iterator::advance_container_start(const
return SUCCESS;
}

// Get the JSON and advance the cursor, decreasing depth to signify that we have retrieved the value.
// Get the JSON and advance the cursor
assert_at_start();
json = _json_iter->advance();
return SUCCESS;
}
simdjson_really_inline const uint8_t *value_iterator::advance_root_scalar(const char *type) const noexcept {

simdjson_really_inline const uint8_t *value_iterator::advance_root_scalar(const char *type) noexcept {
logger::log_value(*_json_iter, start_position(), depth(), type);
if (!is_at_start()) { return peek_start(); }

Expand All @@ -538,7 +550,7 @@ simdjson_really_inline const uint8_t *value_iterator::advance_root_scalar(const
_json_iter->ascend_to(depth()-1);
return result;
}
simdjson_really_inline const uint8_t *value_iterator::advance_non_root_scalar(const char *type) const noexcept {
simdjson_really_inline const uint8_t *value_iterator::advance_non_root_scalar(const char *type) noexcept {
logger::log_value(*_json_iter, start_position(), depth(), type);
if (!is_at_start()) { return peek_start(); }

Expand All @@ -553,6 +565,13 @@ simdjson_really_inline error_code value_iterator::incorrect_type_error(const cha
return INCORRECT_TYPE;
}

simdjson_really_inline error_code value_iterator::error_unless_more_tokens(uint32_t tokens) const noexcept {
if ((position() + tokens) > end_position()) {
return _json_iter->report_error(TAPE_ERROR, "Document ended early");
}
return SUCCESS;
}

simdjson_really_inline bool value_iterator::is_at_start() const noexcept {
return position() == start_position();
}
Expand Down Expand Up @@ -633,7 +652,19 @@ simdjson_really_inline token_position value_iterator::start_position() const noe
}

simdjson_really_inline token_position value_iterator::position() const noexcept {
return _json_iter->token.position();
return _json_iter->position();
}

simdjson_really_inline token_position value_iterator::end_position() const noexcept {
return _json_iter->end_position();
}

simdjson_really_inline token_position value_iterator::last_position() const noexcept {
return _json_iter->last_position();
}

simdjson_really_inline error_code value_iterator::report_error(error_code error, const char *message) noexcept {
return _json_iter->report_error(error, message);
}

} // namespace ondemand
Expand Down
Loading