Check out-of-order error in object index
This commit is contained in:
parent
c5b44f44f9
commit
1bfbb6448a
|
@ -55,11 +55,12 @@ simdjson_really_inline array array::started(value_iterator &iter) noexcept {
|
|||
return array(iter);
|
||||
}
|
||||
|
||||
simdjson_really_inline array_iterator array::begin() noexcept {
|
||||
return iter;
|
||||
simdjson_really_inline simdjson_result<array_iterator> array::begin() noexcept {
|
||||
if (!iter.is_at_container_start()) { return OUT_OF_ORDER_ITERATION; }
|
||||
return array_iterator(iter);
|
||||
}
|
||||
simdjson_really_inline array_iterator array::end() noexcept {
|
||||
return {};
|
||||
simdjson_really_inline simdjson_result<array_iterator> array::end() noexcept {
|
||||
return array_iterator();
|
||||
}
|
||||
|
||||
} // namespace ondemand
|
||||
|
|
|
@ -24,13 +24,13 @@ public:
|
|||
*
|
||||
* Part of the std::iterable interface.
|
||||
*/
|
||||
simdjson_really_inline array_iterator begin() noexcept;
|
||||
simdjson_really_inline simdjson_result<array_iterator> begin() noexcept;
|
||||
/**
|
||||
* Sentinel representing the end of the array.
|
||||
*
|
||||
* Part of the std::iterable interface.
|
||||
*/
|
||||
simdjson_really_inline array_iterator end() noexcept;
|
||||
simdjson_really_inline simdjson_result<array_iterator> end() noexcept;
|
||||
|
||||
protected:
|
||||
/**
|
||||
|
|
|
@ -51,14 +51,12 @@ simdjson_really_inline object::object(const value_iterator &_iter) noexcept
|
|||
{
|
||||
}
|
||||
|
||||
simdjson_really_inline object_iterator object::begin() noexcept {
|
||||
// TODO make it a runtime error if this is violated
|
||||
// Expanded version of SIMDJSON_ASSUME( iter.at_field_start() || !iter.is_open() )
|
||||
SIMDJSON_ASSUME( (iter._json_iter->token.index == iter._start_position + 1) || (iter._json_iter->_depth < iter._depth) );
|
||||
return iter;
|
||||
simdjson_really_inline simdjson_result<object_iterator> object::begin() noexcept {
|
||||
if (!iter.is_at_container_start()) { return OUT_OF_ORDER_ITERATION; }
|
||||
return object_iterator(iter);
|
||||
}
|
||||
simdjson_really_inline object_iterator object::end() noexcept {
|
||||
return {};
|
||||
simdjson_really_inline simdjson_result<object_iterator> object::end() noexcept {
|
||||
return object_iterator();
|
||||
}
|
||||
|
||||
} // namespace ondemand
|
||||
|
|
|
@ -16,8 +16,8 @@ public:
|
|||
*/
|
||||
simdjson_really_inline object() noexcept = default;
|
||||
|
||||
simdjson_really_inline object_iterator begin() noexcept;
|
||||
simdjson_really_inline object_iterator end() noexcept;
|
||||
simdjson_really_inline simdjson_result<object_iterator> begin() noexcept;
|
||||
simdjson_really_inline simdjson_result<object_iterator> end() noexcept;
|
||||
|
||||
/**
|
||||
* Look up a field by name on an object (order-sensitive).
|
||||
|
|
|
@ -58,6 +58,10 @@ simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator
|
|||
// { "a": [ 1, 2 ], "b": [ 3, 4 ] }
|
||||
// ^ (depth 2, index 1)
|
||||
// ```
|
||||
//
|
||||
if (at_first_field()) {
|
||||
has_value = true;
|
||||
|
||||
//
|
||||
// 2. When a previous search did not yield a value or the object is empty:
|
||||
//
|
||||
|
@ -68,15 +72,12 @@ simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator
|
|||
// ^ (depth 0, index 2)
|
||||
// ```
|
||||
//
|
||||
if (!is_open()) {
|
||||
} else if (!is_open()) {
|
||||
// If we're past the end of the object, we're being iterated out of order.
|
||||
// Note: this isn't perfect detection. It's possible the user is inside some other object; if so,
|
||||
// this object iterator will blithely scan that object for fields.
|
||||
if (_json_iter->depth() < depth() - 1) { return OUT_OF_ORDER_ITERATION; }
|
||||
return false;
|
||||
}
|
||||
if (at_first_field()) {
|
||||
has_value = true;
|
||||
has_value = false;
|
||||
|
||||
// 3. When a previous search found a field or an iterator yielded a value:
|
||||
//
|
||||
|
@ -146,6 +147,10 @@ simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator
|
|||
// ```
|
||||
//
|
||||
} else if (!is_open()) {
|
||||
// If we're past the end of the object, we're being iterated out of order.
|
||||
// Note: this isn't perfect detection. It's possible the user is inside some other object; if so,
|
||||
// this object iterator will blithely scan that object for fields.
|
||||
if (_json_iter->depth() < depth() - 1) { return OUT_OF_ORDER_ITERATION; }
|
||||
has_value = false;
|
||||
|
||||
// 3. When a previous search found a field or an iterator yielded a value:
|
||||
|
|
|
@ -562,10 +562,140 @@ namespace error_tests {
|
|||
ASSERT_EQUAL( val.is_null(), true );
|
||||
TEST_SUCCEED();
|
||||
}));
|
||||
TEST_SUCCEED();
|
||||
}
|
||||
|
||||
//
|
||||
// Do it again for bool
|
||||
//
|
||||
bool out_of_order_array_iteration_error() {
|
||||
TEST_START();
|
||||
auto json = R"([ [ 1, 2 ] ])"_padded;
|
||||
SUBTEST("simdjson_result<value>", test_ondemand_doc(json, [&](auto doc) {
|
||||
for (auto element : doc) {
|
||||
for (auto subelement : element) { ASSERT_SUCCESS(subelement); }
|
||||
ASSERT_ERROR( element.begin(), OUT_OF_ORDER_ITERATION );
|
||||
}
|
||||
return true;
|
||||
}));
|
||||
SUBTEST("value", test_ondemand_doc(json, [&](auto doc) {
|
||||
for (auto element : doc) {
|
||||
ondemand::value val;
|
||||
ASSERT_SUCCESS( element.get(val) );
|
||||
for (auto subelement : val) { ASSERT_SUCCESS(subelement); }
|
||||
ASSERT_ERROR( val.begin(), OUT_OF_ORDER_ITERATION );
|
||||
}
|
||||
return true;
|
||||
}));
|
||||
SUBTEST("simdjson_result<array>", test_ondemand_doc(json, [&](auto doc) {
|
||||
for (auto element : doc) {
|
||||
auto arr = element.get_array();
|
||||
for (auto subelement : arr) { ASSERT_SUCCESS(subelement); }
|
||||
ASSERT_ERROR( arr.begin(), OUT_OF_ORDER_ITERATION );
|
||||
}
|
||||
return true;
|
||||
}));
|
||||
SUBTEST("array", test_ondemand_doc(json, [&](auto doc) {
|
||||
for (auto element : doc) {
|
||||
ondemand::array arr;
|
||||
ASSERT_SUCCESS( element.get(arr) );
|
||||
for (auto subelement : arr) { ASSERT_SUCCESS(subelement); }
|
||||
ASSERT_ERROR( arr.begin(), OUT_OF_ORDER_ITERATION );
|
||||
}
|
||||
return true;
|
||||
}));
|
||||
TEST_SUCCEED();
|
||||
}
|
||||
|
||||
bool out_of_order_object_iteration_error() {
|
||||
TEST_START();
|
||||
auto json = R"([ { "x": 1, "y": 2 } ])"_padded;
|
||||
SUBTEST("simdjson_result<object>", test_ondemand_doc(json, [&](auto doc) {
|
||||
for (auto element : doc) {
|
||||
auto obj = element.get_object();
|
||||
for (auto field : obj) { ASSERT_SUCCESS(field); }
|
||||
ASSERT_ERROR( obj.begin(), OUT_OF_ORDER_ITERATION );
|
||||
}
|
||||
return true;
|
||||
}));
|
||||
SUBTEST("object", test_ondemand_doc(json, [&](auto doc) {
|
||||
for (auto element : doc) {
|
||||
ondemand::object obj;
|
||||
ASSERT_SUCCESS( element.get(obj) );
|
||||
for (auto field : obj) { ASSERT_SUCCESS(field); }
|
||||
ASSERT_ERROR( obj.begin(), OUT_OF_ORDER_ITERATION );
|
||||
}
|
||||
return true;
|
||||
}));
|
||||
TEST_SUCCEED();
|
||||
}
|
||||
|
||||
bool out_of_order_object_index_error() {
|
||||
TEST_START();
|
||||
auto json = R"([ { "x": 1, "y": 2 } ])"_padded;
|
||||
SUBTEST("simdjson_result<object>", test_ondemand_doc(json, [&](auto doc) {
|
||||
simdjson_result<ondemand::object> obj;
|
||||
for (auto element : doc) {
|
||||
obj = element.get_object();
|
||||
for (auto field : obj) { ASSERT_SUCCESS(field); }
|
||||
}
|
||||
ASSERT_ERROR( obj["x"], OUT_OF_ORDER_ITERATION );
|
||||
return true;
|
||||
}));
|
||||
SUBTEST("object", test_ondemand_doc(json, [&](auto doc) {
|
||||
ondemand::object obj;
|
||||
for (auto element : doc) {
|
||||
ASSERT_SUCCESS( element.get(obj) );
|
||||
for (auto field : obj) { ASSERT_SUCCESS(field); }
|
||||
}
|
||||
ASSERT_ERROR( obj["x"], OUT_OF_ORDER_ITERATION );
|
||||
return true;
|
||||
}));
|
||||
TEST_SUCCEED();
|
||||
}
|
||||
|
||||
bool out_of_order_object_find_field_error() {
|
||||
TEST_START();
|
||||
auto json = R"([ { "x": 1, "y": 2 } ])"_padded;
|
||||
SUBTEST("simdjson_result<object>", test_ondemand_doc(json, [&](auto doc) {
|
||||
simdjson_result<ondemand::object> obj;
|
||||
for (auto element : doc) {
|
||||
obj = element.get_object();
|
||||
for (auto field : obj) { ASSERT_SUCCESS(field); }
|
||||
}
|
||||
ASSERT_ERROR( obj.find_field("x"), OUT_OF_ORDER_ITERATION );
|
||||
return true;
|
||||
}));
|
||||
SUBTEST("object", test_ondemand_doc(json, [&](auto doc) {
|
||||
ondemand::object obj;
|
||||
for (auto element : doc) {
|
||||
ASSERT_SUCCESS( element.get(obj) );
|
||||
for (auto field : obj) { ASSERT_SUCCESS(field); }
|
||||
}
|
||||
ASSERT_ERROR( obj.find_field("x"), OUT_OF_ORDER_ITERATION );
|
||||
return true;
|
||||
}));
|
||||
TEST_SUCCEED();
|
||||
}
|
||||
|
||||
bool out_of_order_object_find_field_unordered_error() {
|
||||
TEST_START();
|
||||
auto json = R"([ { "x": 1, "y": 2 } ])"_padded;
|
||||
SUBTEST("simdjson_result<object>", test_ondemand_doc(json, [&](auto doc) {
|
||||
simdjson_result<ondemand::object> obj;
|
||||
for (auto element : doc) {
|
||||
obj = element.get_object();
|
||||
for (auto field : obj) { ASSERT_SUCCESS(field); }
|
||||
}
|
||||
ASSERT_ERROR( obj.find_field_unordered("x"), OUT_OF_ORDER_ITERATION );
|
||||
return true;
|
||||
}));
|
||||
SUBTEST("object", test_ondemand_doc(json, [&](auto doc) {
|
||||
ondemand::object obj;
|
||||
for (auto element : doc) {
|
||||
ASSERT_SUCCESS( element.get(obj) );
|
||||
for (auto field : obj) { ASSERT_SUCCESS(field); }
|
||||
}
|
||||
ASSERT_ERROR( obj.find_field_unordered("x"), OUT_OF_ORDER_ITERATION );
|
||||
return true;
|
||||
}));
|
||||
TEST_SUCCEED();
|
||||
}
|
||||
|
||||
|
@ -588,6 +718,11 @@ namespace error_tests {
|
|||
object_lookup_miss_next_error() &&
|
||||
get_fail_then_succeed_bool() &&
|
||||
get_fail_then_succeed_null() &&
|
||||
out_of_order_array_iteration_error() &&
|
||||
out_of_order_object_iteration_error() &&
|
||||
out_of_order_object_index_error() &&
|
||||
out_of_order_object_find_field_error() &&
|
||||
out_of_order_object_find_field_unordered_error() &&
|
||||
true;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue