Descend into fields at the value position, not the key
This commit is contained in:
parent
9934f65987
commit
e4626d233c
|
@ -154,13 +154,10 @@ simdjson_really_inline void json_iterator::ascend_to(depth_t parent_depth) noexc
|
||||||
}
|
}
|
||||||
|
|
||||||
simdjson_really_inline void json_iterator::descend_to(depth_t child_depth) noexcept {
|
simdjson_really_inline void json_iterator::descend_to(depth_t child_depth) noexcept {
|
||||||
descend_to(child_depth, token.index);
|
|
||||||
}
|
|
||||||
simdjson_really_inline void json_iterator::descend_to(depth_t child_depth, token_position start_position) noexcept {
|
|
||||||
SIMDJSON_ASSUME(child_depth >= 1 && child_depth < INT32_MAX);
|
SIMDJSON_ASSUME(child_depth >= 1 && child_depth < INT32_MAX);
|
||||||
SIMDJSON_ASSUME(_depth == child_depth - 1);
|
SIMDJSON_ASSUME(_depth == child_depth - 1);
|
||||||
_depth = child_depth;
|
_depth = child_depth;
|
||||||
parser->start_positions[_depth] = start_position;
|
parser->start_positions[_depth] = token.index;
|
||||||
}
|
}
|
||||||
|
|
||||||
simdjson_really_inline depth_t json_iterator::depth() const noexcept {
|
simdjson_really_inline depth_t json_iterator::depth() const noexcept {
|
||||||
|
@ -181,11 +178,12 @@ simdjson_really_inline error_code json_iterator::report_error(error_code _error,
|
||||||
simdjson_really_inline token_position json_iterator::position() const noexcept {
|
simdjson_really_inline token_position json_iterator::position() const noexcept {
|
||||||
return token.position();
|
return token.position();
|
||||||
}
|
}
|
||||||
simdjson_really_inline void json_iterator::set_position(token_position target_checkpoint) noexcept {
|
simdjson_really_inline void json_iterator::reenter_child(token_position position, depth_t child_depth) noexcept {
|
||||||
token.set_position(target_checkpoint);
|
SIMDJSON_ASSUME(child_depth >= 1 && child_depth < INT32_MAX);
|
||||||
}
|
SIMDJSON_ASSUME(_depth == child_depth - 1);
|
||||||
simdjson_really_inline token_position json_iterator::nested_start_position(depth_t depth) const noexcept {
|
SIMDJSON_ASSUME(position >= parser->start_positions[child_depth]);
|
||||||
return parser->start_positions[depth];
|
token.set_position(position);
|
||||||
|
_depth = child_depth;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -148,7 +148,7 @@ public:
|
||||||
* @param child_depth the expected child depth.
|
* @param child_depth the expected child depth.
|
||||||
*/
|
*/
|
||||||
simdjson_really_inline void descend_to(depth_t parent_depth) noexcept;
|
simdjson_really_inline void descend_to(depth_t parent_depth) noexcept;
|
||||||
simdjson_really_inline void descend_to(depth_t parent_depth, token_position start_position) noexcept;
|
simdjson_really_inline void descend_to(depth_t parent_depth, int32_t delta) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get current depth.
|
* Get current depth.
|
||||||
|
@ -180,8 +180,7 @@ public:
|
||||||
template<int N> simdjson_warn_unused simdjson_really_inline bool advance_to_buffer(uint8_t (&tmpbuf)[N]) noexcept;
|
template<int N> simdjson_warn_unused simdjson_really_inline bool advance_to_buffer(uint8_t (&tmpbuf)[N]) noexcept;
|
||||||
|
|
||||||
simdjson_really_inline token_position position() const noexcept;
|
simdjson_really_inline token_position position() const noexcept;
|
||||||
simdjson_really_inline void set_position(token_position target_checkpoint) noexcept;
|
simdjson_really_inline void reenter_child(token_position position, depth_t child_depth) noexcept;
|
||||||
simdjson_really_inline token_position nested_start_position(depth_t depth) const noexcept;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
simdjson_really_inline json_iterator(const uint8_t *buf, ondemand::parser *parser) noexcept;
|
simdjson_really_inline json_iterator(const uint8_t *buf, ondemand::parser *parser) noexcept;
|
||||||
|
|
|
@ -123,6 +123,7 @@ private:
|
||||||
simdjson_warn_unused error_code allocate(size_t capacity, size_t max_depth=DEFAULT_MAX_DEPTH) noexcept;
|
simdjson_warn_unused error_code allocate(size_t capacity, size_t max_depth=DEFAULT_MAX_DEPTH) noexcept;
|
||||||
|
|
||||||
friend class json_iterator;
|
friend class json_iterator;
|
||||||
|
friend class value_iterator;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ondemand
|
} // namespace ondemand
|
||||||
|
|
|
@ -24,7 +24,6 @@ simdjson_warn_unused simdjson_really_inline bool value_iterator::started_object(
|
||||||
_json_iter->ascend_to(depth()-1);
|
_json_iter->ascend_to(depth()-1);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
_json_iter->descend_to(depth()+1); //, _start_position+3); // skip {"key":
|
|
||||||
logger::log_start_value(*_json_iter, "object");
|
logger::log_start_value(*_json_iter, "object");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -38,7 +37,6 @@ simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator
|
||||||
_json_iter->ascend_to(depth()-1);
|
_json_iter->ascend_to(depth()-1);
|
||||||
return false;
|
return false;
|
||||||
case ',':
|
case ',':
|
||||||
_json_iter->descend_to(depth()+1); //, _json_iter->token.index+2); // index+2 skips "key":
|
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return _json_iter->report_error(TAPE_ERROR, "Missing comma between object fields");
|
return _json_iter->report_error(TAPE_ERROR, "Missing comma between object fields");
|
||||||
|
@ -94,9 +92,9 @@ simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator
|
||||||
// ```
|
// ```
|
||||||
//
|
//
|
||||||
} else {
|
} else {
|
||||||
// if (_json_iter->nested_start_position(depth()) != _start_position+1) { return OUT_OF_ORDER_ITERATION; }
|
|
||||||
if ((error = skip_child() )) { abandon(); return error; }
|
if ((error = skip_child() )) { abandon(); return error; }
|
||||||
if ((error = has_next_field().get(has_value) )) { abandon(); return error; }
|
if ((error = has_next_field().get(has_value) )) { abandon(); return error; }
|
||||||
|
// if (_json_iter->parser->start_positions[_depth] != _start_position) { return OUT_OF_ORDER_ITERATION; }
|
||||||
}
|
}
|
||||||
while (has_value) {
|
while (has_value) {
|
||||||
// Get the key and colon, stopping at the value.
|
// Get the key and colon, stopping at the value.
|
||||||
|
@ -169,10 +167,10 @@ simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator
|
||||||
// ```
|
// ```
|
||||||
//
|
//
|
||||||
} else {
|
} else {
|
||||||
// if (_json_iter->nested_start_position(depth()) != _start_position) { return OUT_OF_ORDER_ITERATION; }
|
|
||||||
// Finish the previous value and see if , or } is next
|
// Finish the previous value and see if , or } is next
|
||||||
if ((error = skip_child() )) { abandon(); return error; }
|
if ((error = skip_child() )) { abandon(); return error; }
|
||||||
if ((error = has_next_field().get(has_value) )) { abandon(); return error; }
|
if ((error = has_next_field().get(has_value) )) { abandon(); return error; }
|
||||||
|
// if (_json_iter->parser->start_positions[_depth] != _start_position) { return OUT_OF_ORDER_ITERATION; }
|
||||||
}
|
}
|
||||||
|
|
||||||
// After initial processing, we will be in one of two states:
|
// After initial processing, we will be in one of two states:
|
||||||
|
@ -195,7 +193,7 @@ simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator
|
||||||
|
|
||||||
// Next, we find a match starting from the current position.
|
// Next, we find a match starting from the current position.
|
||||||
while (has_value) {
|
while (has_value) {
|
||||||
SIMDJSON_ASSUME( _json_iter->_depth == _depth + 1 ); // We must be at the start of a field
|
SIMDJSON_ASSUME( _json_iter->_depth == _depth ); // We must be at the start of a field
|
||||||
|
|
||||||
// Get the key and colon, stopping at the value.
|
// Get the key and colon, stopping at the value.
|
||||||
raw_json_string actual_key;
|
raw_json_string actual_key;
|
||||||
|
@ -218,13 +216,12 @@ simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator
|
||||||
// beginning of the object.
|
// beginning of the object.
|
||||||
// (We have already run through the object before, so we've already validated its structure. We
|
// (We have already run through the object before, so we've already validated its structure. We
|
||||||
// don't check errors in this bit.)
|
// don't check errors in this bit.)
|
||||||
_json_iter->set_position(_start_position + 1);
|
_json_iter->reenter_child(_start_position + 1, _depth);
|
||||||
_json_iter->descend_to(depth()); // , _start_position);
|
|
||||||
|
|
||||||
has_value = started_object();
|
has_value = started_object();
|
||||||
while (_json_iter->position() < search_start) {
|
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(has_value); // we should reach search_start before ever reaching the end of the object
|
||||||
SIMDJSON_ASSUME( _json_iter->_depth == _depth + 1 ); // We must be at the start of a field
|
SIMDJSON_ASSUME( _json_iter->_depth == _depth ); // We must be at the start of a field
|
||||||
|
|
||||||
// Get the key and colon, stopping at the value.
|
// Get the key and colon, stopping at the value.
|
||||||
raw_json_string actual_key;
|
raw_json_string actual_key;
|
||||||
|
@ -248,7 +245,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 {
|
simdjson_warn_unused simdjson_really_inline simdjson_result<raw_json_string> value_iterator::field_key() noexcept {
|
||||||
assert_at_child();
|
assert_at_next();
|
||||||
|
|
||||||
const uint8_t *key = _json_iter->advance();
|
const uint8_t *key = _json_iter->advance();
|
||||||
if (*(key++) != '"') { return _json_iter->report_error(TAPE_ERROR, "Object key is not a string"); }
|
if (*(key++) != '"') { return _json_iter->report_error(TAPE_ERROR, "Object key is not a string"); }
|
||||||
|
@ -256,9 +253,10 @@ 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 {
|
simdjson_warn_unused simdjson_really_inline error_code value_iterator::field_value() noexcept {
|
||||||
assert_at_child();
|
assert_at_next();
|
||||||
|
|
||||||
if (*_json_iter->advance() != ':') { return _json_iter->report_error(TAPE_ERROR, "Missing colon in object field"); }
|
if (*_json_iter->advance() != ':') { return _json_iter->report_error(TAPE_ERROR, "Missing colon in object field"); }
|
||||||
|
_json_iter->descend_to(depth()+1);
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -508,11 +508,8 @@ namespace object_tests {
|
||||||
SUBTEST("ondemand::value", test_ondemand_doc(json, [&](auto doc_result) {
|
SUBTEST("ondemand::value", test_ondemand_doc(json, [&](auto doc_result) {
|
||||||
ondemand::value object;
|
ondemand::value object;
|
||||||
ASSERT_SUCCESS( doc_result["outer"].get(object) );
|
ASSERT_SUCCESS( doc_result["outer"].get(object) );
|
||||||
uint64_t v;
|
ASSERT_EQUAL( object["a"].get_uint64().value_unsafe(), 1 );
|
||||||
ASSERT_SUCCESS( object["a"].get(v) );
|
ASSERT_EQUAL( object["b"].get_uint64().value_unsafe(), 2 );
|
||||||
ASSERT_EQUAL( v, 1 );
|
|
||||||
ASSERT_SUCCESS( object["b"].get(v) );
|
|
||||||
ASSERT_EQUAL( v, 2 );
|
|
||||||
ASSERT_EQUAL( object["c/d"].get_uint64().value_unsafe(), 3 );
|
ASSERT_EQUAL( object["c/d"].get_uint64().value_unsafe(), 3 );
|
||||||
|
|
||||||
ASSERT_EQUAL( object["a"].get_uint64().value_unsafe(), 1 );
|
ASSERT_EQUAL( object["a"].get_uint64().value_unsafe(), 1 );
|
||||||
|
|
Loading…
Reference in New Issue