Add find_field / find_field_unordered to object
This commit is contained in:
parent
b8426584fc
commit
195acc3e45
|
@ -12,43 +12,46 @@ simdjson_really_inline document document::start(json_iterator &&iter) noexcept {
|
|||
return document(std::forward<json_iterator>(iter));
|
||||
}
|
||||
|
||||
simdjson_really_inline value document::as_value() noexcept {
|
||||
return as_value_iterator();
|
||||
simdjson_really_inline value_iterator document::resume_value_iterator() noexcept {
|
||||
return value_iterator(&iter, 1, iter.root_checkpoint());
|
||||
}
|
||||
simdjson_really_inline value_iterator document::as_value_iterator() noexcept {
|
||||
simdjson_really_inline value_iterator document::get_root_value_iterator() noexcept {
|
||||
iter.assert_at_root();
|
||||
return value_iterator(&iter, 1, iter.root_checkpoint());
|
||||
return resume_value_iterator();
|
||||
}
|
||||
simdjson_really_inline value_iterator document::as_non_root_value_iterator() noexcept {
|
||||
return value_iterator(&iter, 1, iter.root_checkpoint());
|
||||
simdjson_really_inline value document::resume_value() noexcept {
|
||||
return resume_value_iterator();
|
||||
}
|
||||
simdjson_really_inline value document::get_root_value() noexcept {
|
||||
return get_root_value_iterator();
|
||||
}
|
||||
|
||||
simdjson_really_inline simdjson_result<array> document::get_array() & noexcept {
|
||||
return as_value().get_array();
|
||||
return get_root_value().get_array();
|
||||
}
|
||||
simdjson_really_inline simdjson_result<object> document::get_object() & noexcept {
|
||||
return as_value().get_object();
|
||||
return get_root_value().get_object();
|
||||
}
|
||||
simdjson_really_inline simdjson_result<uint64_t> document::get_uint64() noexcept {
|
||||
return as_value_iterator().require_root_uint64();
|
||||
return get_root_value_iterator().require_root_uint64();
|
||||
}
|
||||
simdjson_really_inline simdjson_result<int64_t> document::get_int64() noexcept {
|
||||
return as_value_iterator().require_root_int64();
|
||||
return get_root_value_iterator().require_root_int64();
|
||||
}
|
||||
simdjson_really_inline simdjson_result<double> document::get_double() noexcept {
|
||||
return as_value_iterator().require_root_double();
|
||||
return get_root_value_iterator().require_root_double();
|
||||
}
|
||||
simdjson_really_inline simdjson_result<std::string_view> document::get_string() & noexcept {
|
||||
return as_value().get_string();
|
||||
return get_root_value().get_string();
|
||||
}
|
||||
simdjson_really_inline simdjson_result<raw_json_string> document::get_raw_json_string() & noexcept {
|
||||
return as_value().get_raw_json_string();
|
||||
return get_root_value().get_raw_json_string();
|
||||
}
|
||||
simdjson_really_inline simdjson_result<bool> document::get_bool() noexcept {
|
||||
return as_value_iterator().require_root_bool();
|
||||
return get_root_value_iterator().require_root_bool();
|
||||
}
|
||||
simdjson_really_inline bool document::is_null() noexcept {
|
||||
return as_value_iterator().is_root_null();
|
||||
return get_root_value_iterator().is_root_null();
|
||||
}
|
||||
|
||||
template<> simdjson_really_inline simdjson_result<array> document::get() & noexcept { return get_array(); }
|
||||
|
@ -89,21 +92,24 @@ simdjson_really_inline simdjson_result<array_iterator> document::begin() & noexc
|
|||
simdjson_really_inline simdjson_result<array_iterator> document::end() & noexcept {
|
||||
return {};
|
||||
}
|
||||
|
||||
simdjson_really_inline simdjson_result<value> document::find_field(std::string_view key) & noexcept {
|
||||
return resume_value().find_field(key);
|
||||
}
|
||||
simdjson_really_inline simdjson_result<value> document::find_field(const char *key) & noexcept {
|
||||
return resume_value().find_field(key);
|
||||
}
|
||||
simdjson_really_inline simdjson_result<value> document::find_field_unordered(std::string_view key) & noexcept {
|
||||
return resume_value().find_field_unordered(key);
|
||||
}
|
||||
simdjson_really_inline simdjson_result<value> document::find_field_unordered(const char *key) & noexcept {
|
||||
return resume_value().find_field_unordered(key);
|
||||
}
|
||||
simdjson_really_inline simdjson_result<value> document::operator[](std::string_view key) & noexcept {
|
||||
if (iter.at_root()) {
|
||||
return get_object()[key];
|
||||
} else {
|
||||
// If we're not at the root, this is not the first key we've grabbed
|
||||
return object::resume(as_non_root_value_iterator())[key];
|
||||
}
|
||||
return resume_value()[key];
|
||||
}
|
||||
simdjson_really_inline simdjson_result<value> document::operator[](const char *key) & noexcept {
|
||||
if (iter.at_root()) {
|
||||
return get_object()[key];
|
||||
} else {
|
||||
// If we're not at the root, this is not the first key we've grabbed
|
||||
return object::resume(as_non_root_value_iterator())[key];
|
||||
}
|
||||
return resume_value()[key];
|
||||
}
|
||||
|
||||
} // namespace ondemand
|
||||
|
@ -136,6 +142,14 @@ simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_
|
|||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::end() & noexcept {
|
||||
return {};
|
||||
}
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::find_field_unordered(std::string_view key) & noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first.find_field_unordered(key);
|
||||
}
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::find_field_unordered(const char *key) & noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first.find_field_unordered(key);
|
||||
}
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::operator[](std::string_view key) & noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first[key];
|
||||
|
@ -144,6 +158,14 @@ simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>
|
|||
if (error()) { return error(); }
|
||||
return first[key];
|
||||
}
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::find_field(std::string_view key) & noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first.find_field(key);
|
||||
}
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::find_field(const char *key) & noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first.find_field(key);
|
||||
}
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::get_array() & noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first.get_array();
|
||||
|
|
|
@ -206,30 +206,64 @@ public:
|
|||
simdjson_really_inline simdjson_result<array_iterator> end() & noexcept;
|
||||
|
||||
/**
|
||||
* Look up a field by name on an object.
|
||||
* Look up a field by name on an object (order-sensitive).
|
||||
*
|
||||
* Important notes:
|
||||
* The following code reads z, then y, then x, and thus will not retrieve x or y if fed the
|
||||
* JSON `{ "x": 1, "y": 2, "z": 3 }`:
|
||||
*
|
||||
* * **Raw Keys:** The lookup will be done against the *raw* key, and will not unescape keys.
|
||||
* e.g. `object["a"]` will match `{ "a": 1 }`, but will *not* match `{ "\u0061": 1 }`.
|
||||
* * **Once Only:** You may only look up a single field on a document. To look up multiple fields,
|
||||
* use `.get_object()` or cast to `object`.
|
||||
* ```c++
|
||||
* simdjson::builtin::ondemand::parser parser;
|
||||
* auto obj = parser.parse(R"( { "x": 1, "y": 2, "z": 3 } )"_padded);
|
||||
* double z = obj.find_field("z");
|
||||
* double y = obj.find_field("y");
|
||||
* double x = obj.find_field("x");
|
||||
* ```
|
||||
*
|
||||
* **Raw Keys:** The lookup will be done against the *raw* key, and will not unescape keys.
|
||||
* e.g. `object["a"]` will match `{ "a": 1 }`, but will *not* match `{ "\u0061": 1 }`.
|
||||
*
|
||||
* @param key The key to look up.
|
||||
* @returns The value of the field, NO_SUCH_FIELD if the field is not in the object, or
|
||||
* INCORRECT_TYPE if the JSON value is not an array.
|
||||
* @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
|
||||
*/
|
||||
simdjson_really_inline simdjson_result<value> find_field(std::string_view key) & noexcept;
|
||||
/** @overload simdjson_really_inline simdjson_result<value> find_field(std::string_view key) & noexcept; */
|
||||
simdjson_really_inline simdjson_result<value> find_field(const char *key) & noexcept;
|
||||
|
||||
/**
|
||||
* Look up a field by name on an object, without regard to key order.
|
||||
*
|
||||
* **Performance Notes:** This is a bit less performant than find_field(), though its effect varies
|
||||
* and often appears negligible. It starts out normally, starting out at the last field; but if
|
||||
* the field is not found, it scans from the beginning of the object to see if it missed it. That
|
||||
* missing case has a non-cache-friendly bump and lots of extra scanning, especially if the object
|
||||
* in question is large. The fact that the extra code is there also bumps the executable size.
|
||||
*
|
||||
* It is the default, however, because it would be highly surprising (and hard to debug) if the
|
||||
* default behavior failed to look up a field just because it was in the wrong order--and many
|
||||
* APIs assume this. Therefore, you must be explicit if you want to treat objects as out of order.
|
||||
*
|
||||
* Use find_field() if you are sure fields will be in order (or are willing to treat it as if the
|
||||
* field wasn't there when they aren't).
|
||||
*
|
||||
* @param key The key to look up.
|
||||
* @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
|
||||
*/
|
||||
simdjson_really_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept;
|
||||
/** @overload simdjson_really_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */
|
||||
simdjson_really_inline simdjson_result<value> find_field_unordered(const char *key) & noexcept;
|
||||
/** @overload simdjson_really_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */
|
||||
simdjson_really_inline simdjson_result<value> operator[](std::string_view key) & noexcept;
|
||||
/** @overload simdjson_really_inline simdjson_result<value> operator[](std::string_view key) & noexcept; */
|
||||
/** @overload simdjson_really_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */
|
||||
simdjson_really_inline simdjson_result<value> operator[](const char *key) & noexcept;
|
||||
|
||||
protected:
|
||||
simdjson_really_inline document(ondemand::json_iterator &&iter) noexcept;
|
||||
simdjson_really_inline const uint8_t *text(uint32_t idx) const noexcept;
|
||||
|
||||
simdjson_really_inline value as_value() noexcept;
|
||||
simdjson_really_inline value_iterator as_value_iterator() noexcept;
|
||||
simdjson_really_inline value_iterator as_non_root_value_iterator() noexcept;
|
||||
simdjson_really_inline value_iterator resume_value_iterator() noexcept;
|
||||
simdjson_really_inline value_iterator get_root_value_iterator() noexcept;
|
||||
simdjson_really_inline value resume_value() noexcept;
|
||||
simdjson_really_inline value get_root_value() noexcept;
|
||||
static simdjson_really_inline document start(ondemand::json_iterator &&iter) noexcept;
|
||||
|
||||
//
|
||||
|
@ -290,8 +324,12 @@ public:
|
|||
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator> begin() & noexcept;
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator> end() & noexcept;
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field(std::string_view key) & noexcept;
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field(const char *key) & noexcept;
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> operator[](std::string_view key) & noexcept;
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> operator[](const char *key) & noexcept;
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field_unordered(std::string_view key) & noexcept;
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field_unordered(const char *key) & noexcept;
|
||||
};
|
||||
|
||||
} // namespace simdjson
|
||||
|
|
|
@ -132,11 +132,13 @@ simdjson_really_inline uint32_t json_iterator::peek_length(int32_t delta) const
|
|||
}
|
||||
|
||||
simdjson_really_inline void json_iterator::ascend_to(depth_t parent_depth) noexcept {
|
||||
SIMDJSON_ASSUME(parent_depth >= 0 && parent_depth < INT32_MAX - 1);
|
||||
SIMDJSON_ASSUME(_depth == parent_depth + 1);
|
||||
_depth = parent_depth;
|
||||
}
|
||||
|
||||
simdjson_really_inline void json_iterator::descend_to(depth_t child_depth) noexcept {
|
||||
SIMDJSON_ASSUME(child_depth >= 1 && child_depth < INT32_MAX);
|
||||
SIMDJSON_ASSUME(_depth == child_depth - 1);
|
||||
_depth = child_depth;
|
||||
}
|
||||
|
|
|
@ -2,55 +2,31 @@ namespace simdjson {
|
|||
namespace SIMDJSON_IMPLEMENTATION {
|
||||
namespace ondemand {
|
||||
|
||||
//
|
||||
// ### Live States
|
||||
//
|
||||
// While iterating or looking up values, depth >= iter.depth. at_start may vary. Error is
|
||||
// always SUCCESS:
|
||||
//
|
||||
// - Start: This is the state when the object is first found and the iterator is just past the {.
|
||||
// In this state, at_start == true.
|
||||
// - Next: After we hand a scalar value to the user, or an array/object which they then fully
|
||||
// iterate over, the iterator is at the , or } before the next value. In this state,
|
||||
// depth == iter.depth, at_start == false, and error == SUCCESS.
|
||||
// - Unfinished Business: When we hand an array/object to the user which they do not fully
|
||||
// iterate over, we need to finish that iteration by skipping child values until we reach the
|
||||
// Next state. In this state, depth > iter.depth, at_start == false, and error == SUCCESS.
|
||||
//
|
||||
// ## Error States
|
||||
//
|
||||
// In error states, we will yield exactly one more value before stopping. iter.depth == depth
|
||||
// and at_start is always false. We decrement after yielding the error, moving to the Finished
|
||||
// state.
|
||||
//
|
||||
// - Chained Error: When the object iterator is part of an error chain--for example, in
|
||||
// `for (auto tweet : doc["tweets"])`, where the tweet field may be missing or not be an
|
||||
// object--we yield that error in the loop, exactly once. In this state, error != SUCCESS and
|
||||
// iter.depth == depth, and at_start == false. We decrement depth when we yield the error.
|
||||
// - Missing Comma Error: When the iterator ++ method discovers there is no comma between fields,
|
||||
// we flag that as an error and treat it exactly the same as a Chained Error. In this state,
|
||||
// error == TAPE_ERROR, iter.depth == depth, and at_start == false.
|
||||
//
|
||||
// Errors that occur while reading a field to give to the user (such as when the key is not a
|
||||
// string or the field is missing a colon) are yielded immediately. Depth is then decremented,
|
||||
// moving to the Finished state without transitioning through an Error state at all.
|
||||
//
|
||||
// ## Terminal State
|
||||
//
|
||||
// The terminal state has iter.depth < depth. at_start is always false.
|
||||
//
|
||||
// - Finished: When we have reached a }, we are finished. We signal this by decrementing depth.
|
||||
// In this state, iter.depth < depth, at_start == false, and error == SUCCESS.
|
||||
//
|
||||
|
||||
simdjson_really_inline simdjson_result<value> object::find_field_unordered(const std::string_view key) & noexcept {
|
||||
bool has_value;
|
||||
SIMDJSON_TRY( iter.find_field_unordered_raw(key).get(has_value) );
|
||||
if (!has_value) { return NO_SUCH_FIELD; }
|
||||
return value(iter.child());
|
||||
}
|
||||
simdjson_really_inline simdjson_result<value> object::find_field_unordered(const std::string_view key) && noexcept {
|
||||
bool has_value;
|
||||
SIMDJSON_TRY( iter.find_field_unordered_raw(key).get(has_value) );
|
||||
if (!has_value) { return NO_SUCH_FIELD; }
|
||||
return value(iter.child());
|
||||
}
|
||||
simdjson_really_inline simdjson_result<value> object::operator[](const std::string_view key) & noexcept {
|
||||
return find_field_unordered(key);
|
||||
}
|
||||
simdjson_really_inline simdjson_result<value> object::operator[](const std::string_view key) && noexcept {
|
||||
return find_field_unordered(key);
|
||||
}
|
||||
simdjson_really_inline simdjson_result<value> object::find_field(const std::string_view key) & noexcept {
|
||||
bool has_value;
|
||||
SIMDJSON_TRY( iter.find_field_raw(key).get(has_value) );
|
||||
if (!has_value) { return NO_SUCH_FIELD; }
|
||||
return value(iter.child());
|
||||
}
|
||||
|
||||
simdjson_really_inline simdjson_result<value> object::operator[](const std::string_view key) && noexcept {
|
||||
simdjson_really_inline simdjson_result<value> object::find_field(const std::string_view key) && noexcept {
|
||||
bool has_value;
|
||||
SIMDJSON_TRY( iter.find_field_raw(key).get(has_value) );
|
||||
if (!has_value) { return NO_SUCH_FIELD; }
|
||||
|
@ -108,6 +84,14 @@ simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object
|
|||
if (error()) { return error(); }
|
||||
return first.end();
|
||||
}
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object>::find_field_unordered(std::string_view key) & noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first.find_field_unordered(key);
|
||||
}
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object>::find_field_unordered(std::string_view key) && noexcept {
|
||||
if (error()) { return error(); }
|
||||
return std::forward<SIMDJSON_IMPLEMENTATION::ondemand::object>(first).find_field_unordered(key);
|
||||
}
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object>::operator[](std::string_view key) & noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first[key];
|
||||
|
@ -116,5 +100,13 @@ simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>
|
|||
if (error()) { return error(); }
|
||||
return std::forward<SIMDJSON_IMPLEMENTATION::ondemand::object>(first)[key];
|
||||
}
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object>::find_field(std::string_view key) & noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first.find_field(key);
|
||||
}
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object>::find_field(std::string_view key) && noexcept {
|
||||
if (error()) { return error(); }
|
||||
return std::forward<SIMDJSON_IMPLEMENTATION::ondemand::object>(first).find_field(key);
|
||||
}
|
||||
|
||||
} // namespace simdjson
|
||||
|
|
|
@ -20,29 +20,54 @@ public:
|
|||
simdjson_really_inline object_iterator end() noexcept;
|
||||
|
||||
/**
|
||||
* Look up a field by name on an object.
|
||||
* Look up a field by name on an object (order-sensitive).
|
||||
*
|
||||
* Important notes:
|
||||
* The following code reads z, then y, then x, and thus will not retrieve x or y if fed the
|
||||
* JSON `{ "x": 1, "y": 2, "z": 3 }`:
|
||||
*
|
||||
* * **Raw Keys:** The lookup will be done against the *raw* key, and will not unescape keys.
|
||||
* e.g. `object["a"]` will match `{ "a": 1 }`, but will *not* match `{ "\u0061": 1 }`.
|
||||
* * **Order Sensitive:** Each field lookup will only move forward in the object. In particular,
|
||||
* the following code reads z, then y, then x, and thus will not retrieve x or y if fed the
|
||||
* JSON `{ "x": 1, "y": 2, "z": 3 }`:
|
||||
* ```c++
|
||||
* simdjson::builtin::ondemand::parser parser;
|
||||
* auto obj = parser.parse(R"( { "x": 1, "y": 2, "z": 3 } )"_padded);
|
||||
* double z = obj.find_field("z");
|
||||
* double y = obj.find_field("y");
|
||||
* double x = obj.find_field("x");
|
||||
* ```
|
||||
*
|
||||
* ```c++
|
||||
* simdjson::builtin::ondemand::parser parser;
|
||||
* auto obj = parser.parse(R"( { "x": 1, "y": 2, "z": 3 } )"_padded);
|
||||
* double z = obj["z"];
|
||||
* double y = obj["y"];
|
||||
* double x = obj["x"];
|
||||
* ```
|
||||
* **Raw Keys:** The lookup will be done against the *raw* key, and will not unescape keys.
|
||||
* e.g. `object["a"]` will match `{ "a": 1 }`, but will *not* match `{ "\u0061": 1 }`.
|
||||
*
|
||||
* @param key The key to look up.
|
||||
* @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
|
||||
*/
|
||||
simdjson_really_inline simdjson_result<value> find_field(std::string_view key) & noexcept;
|
||||
/** @overload simdjson_really_inline simdjson_result<value> find_field(std::string_view key) & noexcept; */
|
||||
simdjson_really_inline simdjson_result<value> find_field(std::string_view key) && noexcept;
|
||||
|
||||
/**
|
||||
* Look up a field by name on an object, without regard to key order.
|
||||
*
|
||||
* **Performance Notes:** This is a bit less performant than find_field(), though its effect varies
|
||||
* and often appears negligible. It starts out normally, starting out at the last field; but if
|
||||
* the field is not found, it scans from the beginning of the object to see if it missed it. That
|
||||
* missing case has a non-cache-friendly bump and lots of extra scanning, especially if the object
|
||||
* in question is large. The fact that the extra code is there also bumps the executable size.
|
||||
*
|
||||
* It is the default, however, because it would be highly surprising (and hard to debug) if the
|
||||
* default behavior failed to look up a field just because it was in the wrong order--and many
|
||||
* APIs assume this. Therefore, you must be explicit if you want to treat objects as out of order.
|
||||
*
|
||||
* Use find_field() if you are sure fields will be in order (or are willing to treat it as if the
|
||||
* field wasn't there when they aren't).
|
||||
*
|
||||
* @param key The key to look up.
|
||||
* @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
|
||||
*/
|
||||
simdjson_really_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept;
|
||||
/** @overload simdjson_really_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */
|
||||
simdjson_really_inline simdjson_result<value> find_field_unordered(std::string_view key) && noexcept;
|
||||
/** @overload simdjson_really_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */
|
||||
simdjson_really_inline simdjson_result<value> operator[](std::string_view key) & noexcept;
|
||||
/** @overload simdjson_really_inline simdjson_result<value> operator[](std::string_view key) & noexcept; */
|
||||
/** @overload simdjson_really_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */
|
||||
simdjson_really_inline simdjson_result<value> operator[](std::string_view key) && noexcept;
|
||||
|
||||
protected:
|
||||
|
@ -76,6 +101,10 @@ public:
|
|||
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object_iterator> begin() noexcept;
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object_iterator> end() noexcept;
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field(std::string_view key) & noexcept;
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field(std::string_view key) && noexcept;
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field_unordered(std::string_view key) & noexcept;
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field_unordered(std::string_view key) && noexcept;
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> operator[](std::string_view key) & noexcept;
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> operator[](std::string_view key) && noexcept;
|
||||
};
|
||||
|
|
|
@ -6,6 +6,13 @@ simdjson_really_inline value::value(const value_iterator &_iter) noexcept
|
|||
: iter{_iter}
|
||||
{
|
||||
}
|
||||
simdjson_really_inline value value::start(const value_iterator &iter) noexcept {
|
||||
return iter;
|
||||
}
|
||||
simdjson_really_inline value value::resume(const value_iterator &iter) noexcept {
|
||||
return iter;
|
||||
}
|
||||
|
||||
simdjson_really_inline simdjson_result<array> value::get_array() && noexcept {
|
||||
return array::start(iter);
|
||||
}
|
||||
|
@ -18,6 +25,21 @@ simdjson_really_inline simdjson_result<object> value::get_object() && noexcept {
|
|||
simdjson_really_inline simdjson_result<object> value::get_object() & noexcept {
|
||||
return object::try_start(iter);
|
||||
}
|
||||
simdjson_really_inline simdjson_result<object> value::start_or_resume_object() & noexcept {
|
||||
if (iter.at_start()) {
|
||||
return get_object();
|
||||
} else {
|
||||
return object::resume(iter);
|
||||
}
|
||||
}
|
||||
simdjson_really_inline simdjson_result<object> value::start_or_resume_object() && noexcept {
|
||||
if (iter.at_start()) {
|
||||
return get_object();
|
||||
} else {
|
||||
return object::resume(iter);
|
||||
}
|
||||
}
|
||||
|
||||
simdjson_really_inline simdjson_result<raw_json_string> value::get_raw_json_string() && noexcept {
|
||||
return iter.require_raw_json_string();
|
||||
}
|
||||
|
@ -145,17 +167,43 @@ simdjson_really_inline simdjson_result<array_iterator> value::end() & noexcept {
|
|||
return {};
|
||||
}
|
||||
|
||||
simdjson_really_inline simdjson_result<value> value::find_field(std::string_view key) & noexcept {
|
||||
return start_or_resume_object().find_field(key);
|
||||
}
|
||||
simdjson_really_inline simdjson_result<value> value::find_field(std::string_view key) && noexcept {
|
||||
return std::forward<value>(*this).start_or_resume_object().find_field(key);
|
||||
}
|
||||
simdjson_really_inline simdjson_result<value> value::find_field(const char *key) & noexcept {
|
||||
return start_or_resume_object().find_field(key);
|
||||
}
|
||||
simdjson_really_inline simdjson_result<value> value::find_field(const char *key) && noexcept {
|
||||
return std::forward<value>(*this).start_or_resume_object().find_field(key);
|
||||
}
|
||||
|
||||
simdjson_really_inline simdjson_result<value> value::find_field_unordered(std::string_view key) & noexcept {
|
||||
return start_or_resume_object().find_field_unordered(key);
|
||||
}
|
||||
simdjson_really_inline simdjson_result<value> value::find_field_unordered(std::string_view key) && noexcept {
|
||||
return std::forward<value>(*this).start_or_resume_object().find_field_unordered(key);
|
||||
}
|
||||
simdjson_really_inline simdjson_result<value> value::find_field_unordered(const char *key) & noexcept {
|
||||
return start_or_resume_object().find_field_unordered(key);
|
||||
}
|
||||
simdjson_really_inline simdjson_result<value> value::find_field_unordered(const char *key) && noexcept {
|
||||
return std::forward<value>(*this).start_or_resume_object().find_field_unordered(key);
|
||||
}
|
||||
|
||||
simdjson_really_inline simdjson_result<value> value::operator[](std::string_view key) & noexcept {
|
||||
return get_object()[key];
|
||||
return start_or_resume_object()[key];
|
||||
}
|
||||
simdjson_really_inline simdjson_result<value> value::operator[](std::string_view key) && noexcept {
|
||||
return std::forward<value>(*this).get_object()[key];
|
||||
return std::forward<value>(*this).start_or_resume_object()[key];
|
||||
}
|
||||
simdjson_really_inline simdjson_result<value> value::operator[](const char *key) & noexcept {
|
||||
return get_object()[key];
|
||||
return start_or_resume_object()[key];
|
||||
}
|
||||
simdjson_really_inline simdjson_result<value> value::operator[](const char *key) && noexcept {
|
||||
return std::forward<value>(*this).get_object()[key];
|
||||
return std::forward<value>(*this).start_or_resume_object()[key];
|
||||
}
|
||||
|
||||
} // namespace ondemand
|
||||
|
@ -188,6 +236,40 @@ simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_
|
|||
return {};
|
||||
}
|
||||
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::find_field(std::string_view key) & noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first.find_field(key);
|
||||
}
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::find_field(std::string_view key) && noexcept {
|
||||
if (error()) { return error(); }
|
||||
return std::forward<SIMDJSON_IMPLEMENTATION::ondemand::value>(first).find_field(key);
|
||||
}
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::find_field(const char *key) & noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first.find_field(key);
|
||||
}
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::find_field(const char *key) && noexcept {
|
||||
if (error()) { return error(); }
|
||||
return std::forward<SIMDJSON_IMPLEMENTATION::ondemand::value>(first).find_field(key);
|
||||
}
|
||||
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::find_field_unordered(std::string_view key) & noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first.find_field_unordered(key);
|
||||
}
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::find_field_unordered(std::string_view key) && noexcept {
|
||||
if (error()) { return error(); }
|
||||
return std::forward<SIMDJSON_IMPLEMENTATION::ondemand::value>(first).find_field_unordered(key);
|
||||
}
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::find_field_unordered(const char *key) & noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first.find_field_unordered(key);
|
||||
}
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::find_field_unordered(const char *key) && noexcept {
|
||||
if (error()) { return error(); }
|
||||
return std::forward<SIMDJSON_IMPLEMENTATION::ondemand::value>(first).find_field_unordered(key);
|
||||
}
|
||||
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::operator[](std::string_view key) & noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first[key];
|
||||
|
|
|
@ -245,32 +245,71 @@ public:
|
|||
simdjson_really_inline simdjson_result<array_iterator> end() & noexcept;
|
||||
|
||||
/**
|
||||
* Look up a field by name on an object.
|
||||
* Look up a field by name on an object (order-sensitive).
|
||||
*
|
||||
* Important notes:
|
||||
* The following code reads z, then y, then x, and thus will not retrieve x or y if fed the
|
||||
* JSON `{ "x": 1, "y": 2, "z": 3 }`:
|
||||
*
|
||||
* * **Raw Keys:** The lookup will be done against the *raw* key, and will not unescape keys.
|
||||
* e.g. `object["a"]` will match `{ "a": 1 }`, but will *not* match `{ "\u0061": 1 }`.
|
||||
* * **Once Only:** You may only look up a single field on a value. To look up multiple fields,
|
||||
* you must cast to object or call `.get_object()`.
|
||||
* ```c++
|
||||
* simdjson::builtin::ondemand::parser parser;
|
||||
* auto obj = parser.parse(R"( { "x": 1, "y": 2, "z": 3 } )"_padded);
|
||||
* double z = obj.find_field("z");
|
||||
* double y = obj.find_field("y");
|
||||
* double x = obj.find_field("x");
|
||||
* ```
|
||||
*
|
||||
* **Raw Keys:** The lookup will be done against the *raw* key, and will not unescape keys.
|
||||
* e.g. `object["a"]` will match `{ "a": 1 }`, but will *not* match `{ "\u0061": 1 }`.
|
||||
*
|
||||
* @param key The key to look up.
|
||||
* @returns The value of the field, NO_SUCH_FIELD if the field is not in the object, or
|
||||
* INCORRECT_TYPE if the JSON value is not an array.
|
||||
* @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
|
||||
*/
|
||||
simdjson_really_inline simdjson_result<value> find_field(std::string_view key) & noexcept;
|
||||
/** @overload simdjson_really_inline simdjson_result<value> find_field(std::string_view key) & noexcept; */
|
||||
simdjson_really_inline simdjson_result<value> find_field(std::string_view key) && noexcept;
|
||||
/** @overload simdjson_really_inline simdjson_result<value> find_field(std::string_view key) & noexcept; */
|
||||
simdjson_really_inline simdjson_result<value> find_field(const char *key) & noexcept;
|
||||
/** @overload simdjson_really_inline simdjson_result<value> find_field(std::string_view key) & noexcept; */
|
||||
simdjson_really_inline simdjson_result<value> find_field(const char *key) && noexcept;
|
||||
|
||||
/**
|
||||
* Look up a field by name on an object, without regard to key order.
|
||||
*
|
||||
* **Performance Notes:** This is a bit less performant than find_field(), though its effect varies
|
||||
* and often appears negligible. It starts out normally, starting out at the last field; but if
|
||||
* the field is not found, it scans from the beginning of the object to see if it missed it. That
|
||||
* missing case has a non-cache-friendly bump and lots of extra scanning, especially if the object
|
||||
* in question is large. The fact that the extra code is there also bumps the executable size.
|
||||
*
|
||||
* It is the default, however, because it would be highly surprising (and hard to debug) if the
|
||||
* default behavior failed to look up a field just because it was in the wrong order--and many
|
||||
* APIs assume this. Therefore, you must be explicit if you want to treat objects as out of order.
|
||||
*
|
||||
* Use find_field() if you are sure fields will be in order (or are willing to treat it as if the
|
||||
* field wasn't there when they aren't).
|
||||
*
|
||||
* @param key The key to look up.
|
||||
* @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
|
||||
*/
|
||||
simdjson_really_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept;
|
||||
/** @overload simdjson_really_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */
|
||||
simdjson_really_inline simdjson_result<value> find_field_unordered(std::string_view key) && noexcept;
|
||||
/** @overload simdjson_really_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */
|
||||
simdjson_really_inline simdjson_result<value> find_field_unordered(const char *key) & noexcept;
|
||||
/** @overload simdjson_really_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */
|
||||
simdjson_really_inline simdjson_result<value> find_field_unordered(const char *key) && noexcept;
|
||||
/** @overload simdjson_really_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */
|
||||
simdjson_really_inline simdjson_result<value> operator[](std::string_view key) & noexcept;
|
||||
/** @overload simdjson_really_inline simdjson_result<value> operator[](std::string_view key) & noexcept; */
|
||||
/** @overload simdjson_really_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */
|
||||
simdjson_really_inline simdjson_result<value> operator[](std::string_view key) && noexcept;
|
||||
/** @overload simdjson_really_inline simdjson_result<value> operator[](std::string_view key) & noexcept; */
|
||||
/** @overload simdjson_really_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */
|
||||
simdjson_really_inline simdjson_result<value> operator[](const char *key) & noexcept;
|
||||
/** @overload simdjson_really_inline simdjson_result<value> operator[](std::string_view key) & noexcept; */
|
||||
/** @overload simdjson_really_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */
|
||||
simdjson_really_inline simdjson_result<value> operator[](const char *key) && noexcept;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Create a value.
|
||||
*
|
||||
* Use value::read() instead of this.
|
||||
*/
|
||||
simdjson_really_inline value(const value_iterator &iter) noexcept;
|
||||
|
||||
|
@ -279,6 +318,25 @@ protected:
|
|||
*/
|
||||
simdjson_really_inline void skip() noexcept;
|
||||
|
||||
/**
|
||||
* Start a value at the current position.
|
||||
*
|
||||
* (It should already be started; this is just a self-documentation method.)
|
||||
*/
|
||||
static simdjson_really_inline value start(const value_iterator &iter) noexcept;
|
||||
|
||||
/**
|
||||
* Resume a value.
|
||||
*/
|
||||
static simdjson_really_inline value resume(const value_iterator &iter) noexcept;
|
||||
|
||||
/**
|
||||
* Get the object, starting or resuming it as necessary
|
||||
*/
|
||||
simdjson_really_inline simdjson_result<object> start_or_resume_object() & noexcept;
|
||||
/** @overload simdjson_really_inline simdjson_result<object> start_or_resume_object() & noexcept; */
|
||||
simdjson_really_inline simdjson_result<object> start_or_resume_object() && noexcept;
|
||||
|
||||
// simdjson_really_inline void log_value(const char *type) const noexcept;
|
||||
// simdjson_really_inline void log_error(const char *message) const noexcept;
|
||||
|
||||
|
@ -362,25 +420,66 @@ public:
|
|||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator> end() & noexcept;
|
||||
|
||||
/**
|
||||
* Look up a field by name on an object.
|
||||
* Look up a field by name on an object (order-sensitive).
|
||||
*
|
||||
* Important notes:
|
||||
* The following code reads z, then y, then x, and thus will not retrieve x or y if fed the
|
||||
* JSON `{ "x": 1, "y": 2, "z": 3 }`:
|
||||
*
|
||||
* * **Raw Keys:** The lookup will be done against the *raw* key, and will not unescape keys.
|
||||
* e.g. `object["a"]` will match `{ "a": 1 }`, but will *not* match `{ "\u0061": 1 }`.
|
||||
* * **Once Only:** You may only look up a single field on a value. To look up multiple fields,
|
||||
* you must cast to object or call `.get_object()`.
|
||||
* ```c++
|
||||
* simdjson::builtin::ondemand::parser parser;
|
||||
* auto obj = parser.parse(R"( { "x": 1, "y": 2, "z": 3 } )"_padded);
|
||||
* double z = obj.find_field("z");
|
||||
* double y = obj.find_field("y");
|
||||
* double x = obj.find_field("x");
|
||||
* ```
|
||||
*
|
||||
* **Raw Keys:** The lookup will be done against the *raw* key, and will not unescape keys.
|
||||
* e.g. `object["a"]` will match `{ "a": 1 }`, but will *not* match `{ "\u0061": 1 }`.
|
||||
*
|
||||
* @param key The key to look up.
|
||||
* @returns The value of the field, NO_SUCH_FIELD if the field is not in the object, or
|
||||
* INCORRECT_TYPE if the JSON value is not an array.
|
||||
* @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
|
||||
*/
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field(std::string_view key) & noexcept;
|
||||
/** @overload simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field(std::string_view key) & noexcept; */
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field(std::string_view key) && noexcept;
|
||||
/** @overload simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field(std::string_view key) & noexcept; */
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field(const char *key) & noexcept;
|
||||
/** @overload simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field(std::string_view key) & noexcept; */
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field(const char *key) && noexcept;
|
||||
|
||||
/**
|
||||
* Look up a field by name on an object, without regard to key order.
|
||||
*
|
||||
* **Performance Notes:** This is a bit less performant than find_field(), though its effect varies
|
||||
* and often appears negligible. It starts out normally, starting out at the last field; but if
|
||||
* the field is not found, it scans from the beginning of the object to see if it missed it. That
|
||||
* missing case has a non-cache-friendly bump and lots of extra scanning, especially if the object
|
||||
* in question is large. The fact that the extra code is there also bumps the executable size.
|
||||
*
|
||||
* It is the default, however, because it would be highly surprising (and hard to debug) if the
|
||||
* default behavior failed to look up a field just because it was in the wrong order--and many
|
||||
* APIs assume this. Therefore, you must be explicit if you want to treat objects as out of order.
|
||||
*
|
||||
* Use find_field() if you are sure fields will be in order (or are willing to treat it as if the
|
||||
* field wasn't there when they aren't).
|
||||
*
|
||||
* @param key The key to look up.
|
||||
* @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
|
||||
*/
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field_unordered(std::string_view key) & noexcept;
|
||||
/** @overload simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field_unordered(std::string_view key) & noexcept; */
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field_unordered(std::string_view key) && noexcept;
|
||||
/** @overload simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field_unordered(std::string_view key) & noexcept; */
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field_unordered(const char *key) & noexcept;
|
||||
/** @overload simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field_unordered(std::string_view key) & noexcept; */
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field_unordered(const char *key) && noexcept;
|
||||
/** @overload simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field_unordered(std::string_view key) & noexcept; */
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> operator[](std::string_view key) & noexcept;
|
||||
/** @overload simdjson_really_inline simdjson_result<value> operator[](std::string_view key) & noexcept; */
|
||||
/** @overload simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field_unordered(std::string_view key) & noexcept; */
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> operator[](std::string_view key) && noexcept;
|
||||
/** @overload simdjson_really_inline simdjson_result<value> operator[](std::string_view key) & noexcept; */
|
||||
/** @overload simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field_unordered(std::string_view key) & noexcept; */
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> operator[](const char *key) & noexcept;
|
||||
/** @overload simdjson_really_inline simdjson_result<value> operator[](std::string_view key) & noexcept; */
|
||||
/** @overload simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field_unordered(std::string_view key) & noexcept; */
|
||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> operator[](const char *key) && noexcept;
|
||||
};
|
||||
|
||||
|
|
|
@ -55,6 +55,73 @@ simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator
|
|||
error_code error;
|
||||
bool has_value;
|
||||
|
||||
//
|
||||
// Initially, the object can be in one of a few different places:
|
||||
//
|
||||
// 1. The start of the object, at the first field:
|
||||
//
|
||||
// ```
|
||||
// { "a": [ 1, 2 ], "b": [ 3, 4 ] }
|
||||
// ^ (depth 2, index 1)
|
||||
// ```
|
||||
//
|
||||
// 2. When a previous search did not yield a value or the object is empty:
|
||||
//
|
||||
// ```
|
||||
// { "a": [ 1, 2 ], "b": [ 3, 4 ] }
|
||||
// ^ (depth 0)
|
||||
// { }
|
||||
// ^ (depth 0, index 2)
|
||||
// ```
|
||||
//
|
||||
if (!is_open()) { return false; }
|
||||
if (at_first_field()) {
|
||||
has_value = true;
|
||||
|
||||
// 3. When a previous search found a field or an iterator yielded a value:
|
||||
//
|
||||
// ```
|
||||
// // When a field was not fully consumed (or not even touched at all)
|
||||
// { "a": [ 1, 2 ], "b": [ 3, 4 ] }
|
||||
// ^ (depth 2)
|
||||
// // When a field was fully consumed
|
||||
// { "a": [ 1, 2 ], "b": [ 3, 4 ] }
|
||||
// ^ (depth 1)
|
||||
// // When the last field was fully consumed
|
||||
// { "a": [ 1, 2 ], "b": [ 3, 4 ] }
|
||||
// ^ (depth 1)
|
||||
// ```
|
||||
//
|
||||
} else {
|
||||
if ((error = skip_child() )) { abandon(); return error; }
|
||||
if ((error = has_next_field().get(has_value) )) { abandon(); return error; }
|
||||
}
|
||||
while (has_value) {
|
||||
// Get the key and colon, stopping at the value.
|
||||
raw_json_string actual_key;
|
||||
if ((error = field_key().get(actual_key) )) { abandon(); return error; };
|
||||
if ((error = field_value() )) { abandon(); return error; }
|
||||
|
||||
// If it matches, stop and return
|
||||
if (actual_key == key) {
|
||||
logger::log_event(*this, "match", key, -2);
|
||||
return true;
|
||||
}
|
||||
|
||||
// No match: skip the value and see if , or } is next
|
||||
logger::log_event(*this, "no match", key, -2);
|
||||
SIMDJSON_TRY( skip_child() ); // Skip the value entirely
|
||||
if ((error = has_next_field().get(has_value) )) { abandon(); return error; }
|
||||
}
|
||||
|
||||
// If the loop ended, we're out of fields to look at.
|
||||
return false;
|
||||
}
|
||||
|
||||
simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator::find_field_unordered_raw(const std::string_view key) noexcept {
|
||||
error_code error;
|
||||
bool has_value;
|
||||
|
||||
//
|
||||
// Initially, the object can be in one of a few different places:
|
||||
//
|
||||
|
@ -476,6 +543,14 @@ simdjson_really_inline bool value_iterator::is_open() const noexcept {
|
|||
return _json_iter->depth() >= depth();
|
||||
}
|
||||
|
||||
simdjson_really_inline bool value_iterator::at_eof() const noexcept {
|
||||
return _json_iter->at_eof();
|
||||
}
|
||||
|
||||
simdjson_really_inline bool value_iterator::at_start() const noexcept {
|
||||
return _json_iter->token.index == _start_index;
|
||||
}
|
||||
|
||||
simdjson_really_inline bool value_iterator::at_first_field() const noexcept {
|
||||
SIMDJSON_ASSUME( _json_iter->token.index > _start_index );
|
||||
return _json_iter->token.index == _start_index + 1;
|
||||
|
|
|
@ -50,6 +50,11 @@ public:
|
|||
*/
|
||||
simdjson_really_inline bool at_eof() const noexcept;
|
||||
|
||||
/**
|
||||
* Tell whether the iterator is at the start of the value
|
||||
*/
|
||||
simdjson_really_inline bool at_start() const noexcept;
|
||||
|
||||
/**
|
||||
* Tell whether the value is open--if the value has not been used, or the array/object is still open.
|
||||
*/
|
||||
|
@ -148,7 +153,8 @@ public:
|
|||
simdjson_warn_unused simdjson_really_inline error_code find_field(const std::string_view key) noexcept;
|
||||
|
||||
/**
|
||||
* Find the next field with the given key, *without* unescaping.
|
||||
* Find the next field with the given key, *without* unescaping. This assumes object order: it
|
||||
* will not find the field if it was already passed when looking for some *other* field.
|
||||
*
|
||||
* Assumes you have called next_field() or otherwise matched the previous value.
|
||||
*
|
||||
|
@ -165,6 +171,26 @@ public:
|
|||
*/
|
||||
simdjson_warn_unused simdjson_really_inline simdjson_result<bool> find_field_raw(const std::string_view key) noexcept;
|
||||
|
||||
/**
|
||||
* Find the field with the given key without regard to order, and *without* unescaping.
|
||||
*
|
||||
* This is an unordered object lookup: if the field is not found initially, it will cycle around and scan from the beginning.
|
||||
*
|
||||
* Assumes you have called next_field() or otherwise matched the previous value.
|
||||
*
|
||||
* This means the iterator must be sitting at the next key:
|
||||
*
|
||||
* ```
|
||||
* { "a": 1, "b": 2 }
|
||||
* ^
|
||||
* ```
|
||||
*
|
||||
* Key is *raw JSON,* meaning it will be matched against the verbatim JSON without attempting to
|
||||
* unescape it. This works well for typical ASCII and UTF-8 keys (almost all of them), but may
|
||||
* fail to match some keys with escapes (\u, \n, etc.).
|
||||
*/
|
||||
simdjson_warn_unused simdjson_really_inline simdjson_result<bool> find_field_unordered_raw(const std::string_view key) noexcept;
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
|
|
|
@ -1202,6 +1202,175 @@ namespace dom_api_tests {
|
|||
ASSERT_ERROR( doc_result["d"], NO_SUCH_FIELD );
|
||||
return true;
|
||||
}));
|
||||
|
||||
json = R"({ "outer": { "a": 1, "b": 2, "c/d": 3 } })"_padded;
|
||||
SUBTEST("ondemand::value", test_ondemand_doc(json, [&](auto doc_result) {
|
||||
ondemand::value object;
|
||||
ASSERT_SUCCESS( doc_result["outer"].get(object) );
|
||||
ASSERT_EQUAL( object["a"].get_uint64().first, 1 );
|
||||
ASSERT_EQUAL( object["b"].get_uint64().first, 2 );
|
||||
ASSERT_EQUAL( object["c/d"].get_uint64().first, 3 );
|
||||
|
||||
ASSERT_EQUAL( object["a"].get_uint64().first, 1 );
|
||||
ASSERT_ERROR( object["d"], NO_SUCH_FIELD );
|
||||
return true;
|
||||
}));
|
||||
SUBTEST("ondemand::value", test_ondemand_doc(json, [&](auto doc_result) {
|
||||
simdjson_result<ondemand::value> object = doc_result["outer"];
|
||||
ASSERT_EQUAL( object["a"].get_uint64().first, 1 );
|
||||
ASSERT_EQUAL( object["b"].get_uint64().first, 2 );
|
||||
ASSERT_EQUAL( object["c/d"].get_uint64().first, 3 );
|
||||
|
||||
ASSERT_EQUAL( object["a"].get_uint64().first, 1 );
|
||||
ASSERT_ERROR( object["d"], NO_SUCH_FIELD );
|
||||
return true;
|
||||
}));
|
||||
TEST_SUCCEED();
|
||||
}
|
||||
|
||||
bool object_find_field_unordered() {
|
||||
TEST_START();
|
||||
auto json = R"({ "a": 1, "b": 2, "c/d": 3})"_padded;
|
||||
SUBTEST("ondemand::object", test_ondemand_doc(json, [&](auto doc_result) {
|
||||
ondemand::object object;
|
||||
ASSERT_SUCCESS( doc_result.get(object) );
|
||||
|
||||
ASSERT_EQUAL( object.find_field_unordered("a").get_uint64().first, 1 );
|
||||
ASSERT_EQUAL( object.find_field_unordered("b").get_uint64().first, 2 );
|
||||
ASSERT_EQUAL( object.find_field_unordered("c/d").get_uint64().first, 3 );
|
||||
|
||||
ASSERT_EQUAL( object.find_field_unordered("a").get_uint64().first, 1 );
|
||||
ASSERT_ERROR( object.find_field_unordered("d"), NO_SUCH_FIELD );
|
||||
return true;
|
||||
}));
|
||||
SUBTEST("simdjson_result<ondemand::object>", test_ondemand_doc(json, [&](auto doc_result) {
|
||||
simdjson_result<ondemand::object> object;
|
||||
object = doc_result.get_object();
|
||||
|
||||
ASSERT_EQUAL( object.find_field_unordered("a").get_uint64().first, 1 );
|
||||
ASSERT_EQUAL( object.find_field_unordered("b").get_uint64().first, 2 );
|
||||
ASSERT_EQUAL( object.find_field_unordered("c/d").get_uint64().first, 3 );
|
||||
|
||||
ASSERT_EQUAL( object.find_field_unordered("a").get_uint64().first, 1 );
|
||||
ASSERT_ERROR( object.find_field_unordered("d"), NO_SUCH_FIELD );
|
||||
return true;
|
||||
}));
|
||||
SUBTEST("ondemand::document", test_ondemand_doc(json, [&](auto doc_result) {
|
||||
ondemand::document doc;
|
||||
ASSERT_SUCCESS( std::move(doc_result).get(doc) );
|
||||
ASSERT_EQUAL( doc.find_field_unordered("a").get_uint64().first, 1 );
|
||||
ASSERT_EQUAL( doc.find_field_unordered("b").get_uint64().first, 2 );
|
||||
ASSERT_EQUAL( doc.find_field_unordered("c/d").get_uint64().first, 3 );
|
||||
|
||||
ASSERT_EQUAL( doc.find_field_unordered("a").get_uint64().first, 1 );
|
||||
ASSERT_ERROR( doc.find_field_unordered("d"), NO_SUCH_FIELD );
|
||||
return true;
|
||||
}));
|
||||
SUBTEST("simdjson_result<ondemand::document>", test_ondemand_doc(json, [&](auto doc_result) {
|
||||
ASSERT_EQUAL( doc_result.find_field_unordered("a").get_uint64().first, 1 );
|
||||
ASSERT_EQUAL( doc_result.find_field_unordered("b").get_uint64().first, 2 );
|
||||
ASSERT_EQUAL( doc_result.find_field_unordered("c/d").get_uint64().first, 3 );
|
||||
|
||||
ASSERT_EQUAL( doc_result.find_field_unordered("a").get_uint64().first, 1 );
|
||||
ASSERT_ERROR( doc_result.find_field_unordered("d"), NO_SUCH_FIELD );
|
||||
return true;
|
||||
}));
|
||||
|
||||
json = R"({ "outer": { "a": 1, "b": 2, "c/d": 3 } })"_padded;
|
||||
SUBTEST("ondemand::value", test_ondemand_doc(json, [&](auto doc_result) {
|
||||
ondemand::value object;
|
||||
ASSERT_SUCCESS( doc_result.find_field_unordered("outer").get(object) );
|
||||
ASSERT_EQUAL( object.find_field_unordered("a").get_uint64().first, 1 );
|
||||
ASSERT_EQUAL( object.find_field_unordered("b").get_uint64().first, 2 );
|
||||
ASSERT_EQUAL( object.find_field_unordered("c/d").get_uint64().first, 3 );
|
||||
|
||||
ASSERT_EQUAL( object.find_field_unordered("a").get_uint64().first, 1 );
|
||||
ASSERT_ERROR( object.find_field_unordered("d"), NO_SUCH_FIELD );
|
||||
return true;
|
||||
}));
|
||||
SUBTEST("simdjson_result<ondemand::value>", test_ondemand_doc(json, [&](auto doc_result) {
|
||||
simdjson_result<ondemand::value> object = doc_result.find_field_unordered("outer");
|
||||
ASSERT_EQUAL( object.find_field_unordered("a").get_uint64().first, 1 );
|
||||
ASSERT_EQUAL( object.find_field_unordered("b").get_uint64().first, 2 );
|
||||
ASSERT_EQUAL( object.find_field_unordered("c/d").get_uint64().first, 3 );
|
||||
|
||||
ASSERT_EQUAL( object.find_field_unordered("a").get_uint64().first, 1 );
|
||||
ASSERT_ERROR( object.find_field_unordered("d"), NO_SUCH_FIELD );
|
||||
return true;
|
||||
}));
|
||||
TEST_SUCCEED();
|
||||
}
|
||||
|
||||
bool object_find_field() {
|
||||
TEST_START();
|
||||
auto json = R"({ "a": 1, "b": 2, "c/d": 3})"_padded;
|
||||
SUBTEST("ondemand::object", test_ondemand_doc(json, [&](auto doc_result) {
|
||||
ondemand::object object;
|
||||
ASSERT_SUCCESS( doc_result.get(object) );
|
||||
|
||||
ASSERT_EQUAL( object.find_field("a").get_uint64().first, 1 );
|
||||
ASSERT_EQUAL( object.find_field("b").get_uint64().first, 2 );
|
||||
ASSERT_EQUAL( object.find_field("c/d").get_uint64().first, 3 );
|
||||
|
||||
ASSERT_ERROR( object.find_field("a"), NO_SUCH_FIELD );
|
||||
ASSERT_ERROR( object.find_field("d"), NO_SUCH_FIELD );
|
||||
return true;
|
||||
}));
|
||||
SUBTEST("simdjson_result<ondemand::object>", test_ondemand_doc(json, [&](auto doc_result) {
|
||||
simdjson_result<ondemand::object> object;
|
||||
object = doc_result.get_object();
|
||||
|
||||
ASSERT_EQUAL( object.find_field("a").get_uint64().first, 1 );
|
||||
ASSERT_EQUAL( object.find_field("b").get_uint64().first, 2 );
|
||||
ASSERT_EQUAL( object.find_field("c/d").get_uint64().first, 3 );
|
||||
|
||||
ASSERT_ERROR( object.find_field("a"), NO_SUCH_FIELD );
|
||||
ASSERT_ERROR( object.find_field("d"), NO_SUCH_FIELD );
|
||||
return true;
|
||||
}));
|
||||
SUBTEST("ondemand::document", test_ondemand_doc(json, [&](auto doc_result) {
|
||||
ondemand::document doc;
|
||||
ASSERT_SUCCESS( std::move(doc_result).get(doc) );
|
||||
ASSERT_EQUAL( doc.find_field("a").get_uint64().first, 1 );
|
||||
ASSERT_EQUAL( doc.find_field("b").get_uint64().first, 2 );
|
||||
ASSERT_EQUAL( doc.find_field("c/d").get_uint64().first, 3 );
|
||||
|
||||
ASSERT_ERROR( doc.find_field("a"), NO_SUCH_FIELD );
|
||||
ASSERT_ERROR( doc.find_field("d"), NO_SUCH_FIELD );
|
||||
return true;
|
||||
}));
|
||||
SUBTEST("simdjson_result<ondemand::document>", test_ondemand_doc(json, [&](auto doc_result) {
|
||||
ASSERT_EQUAL( doc_result.find_field("a").get_uint64().first, 1 );
|
||||
ASSERT_EQUAL( doc_result.find_field("b").get_uint64().first, 2 );
|
||||
ASSERT_EQUAL( doc_result.find_field("c/d").get_uint64().first, 3 );
|
||||
|
||||
ASSERT_ERROR( doc_result.find_field("a"), NO_SUCH_FIELD );
|
||||
ASSERT_ERROR( doc_result.find_field("d"), NO_SUCH_FIELD );
|
||||
return true;
|
||||
}));
|
||||
|
||||
json = R"({ "outer": { "a": 1, "b": 2, "c/d": 3 } })"_padded;
|
||||
SUBTEST("ondemand::value", test_ondemand_doc(json, [&](auto doc_result) {
|
||||
ondemand::value object;
|
||||
ASSERT_SUCCESS( doc_result.find_field("outer").get(object) );
|
||||
ASSERT_EQUAL( object.find_field("a").get_uint64().first, 1 );
|
||||
ASSERT_EQUAL( object.find_field("b").get_uint64().first, 2 );
|
||||
ASSERT_EQUAL( object.find_field("c/d").get_uint64().first, 3 );
|
||||
|
||||
ASSERT_ERROR( object.find_field("a"), NO_SUCH_FIELD );
|
||||
ASSERT_ERROR( object.find_field("d"), NO_SUCH_FIELD );
|
||||
return true;
|
||||
}));
|
||||
SUBTEST("simdjson_result<ondemand::value>", test_ondemand_doc(json, [&](auto doc_result) {
|
||||
simdjson_result<ondemand::value> object = doc_result.find_field("outer");
|
||||
ASSERT_EQUAL( object.find_field("a").get_uint64().first, 1 );
|
||||
ASSERT_EQUAL( object.find_field("b").get_uint64().first, 2 );
|
||||
ASSERT_EQUAL( object.find_field("c/d").get_uint64().first, 3 );
|
||||
|
||||
ASSERT_ERROR( object.find_field("a"), NO_SUCH_FIELD );
|
||||
ASSERT_ERROR( object.find_field("d"), NO_SUCH_FIELD );
|
||||
return true;
|
||||
}));
|
||||
TEST_SUCCEED();
|
||||
}
|
||||
|
||||
|
@ -1387,6 +1556,8 @@ namespace dom_api_tests {
|
|||
boolean_values() &&
|
||||
null_value() &&
|
||||
object_index() &&
|
||||
object_find_field_unordered() &&
|
||||
object_find_field() &&
|
||||
nested_object_index() &&
|
||||
iterate_object_partial_children() &&
|
||||
iterate_array_partial_children() &&
|
||||
|
@ -1413,7 +1584,7 @@ namespace ordering_tests {
|
|||
|
||||
auto json = "{\"coordinates\":[{\"x\":1.1,\"y\":2.2,\"z\":3.3}]}"_padded;
|
||||
|
||||
bool in_order() {
|
||||
bool in_order_object_index() {
|
||||
TEST_START();
|
||||
ondemand::parser parser{};
|
||||
auto doc = parser.iterate(json);
|
||||
|
@ -1428,7 +1599,37 @@ namespace ordering_tests {
|
|||
return (x == 1.1) && (y == 2.2) && (z == 3.3);
|
||||
}
|
||||
|
||||
bool out_of_order() {
|
||||
bool in_order_object_find_field_unordered() {
|
||||
TEST_START();
|
||||
ondemand::parser parser{};
|
||||
auto doc = parser.iterate(json);
|
||||
double x{0};
|
||||
double y{0};
|
||||
double z{0};
|
||||
for (ondemand::object point_object : doc["coordinates"]) {
|
||||
x += double(point_object.find_field_unordered("x"));
|
||||
y += double(point_object.find_field_unordered("y"));
|
||||
z += double(point_object.find_field_unordered("z"));
|
||||
}
|
||||
return (x == 1.1) && (y == 2.2) && (z == 3.3);
|
||||
}
|
||||
|
||||
bool in_order_object_find_field() {
|
||||
TEST_START();
|
||||
ondemand::parser parser{};
|
||||
auto doc = parser.iterate(json);
|
||||
double x{0};
|
||||
double y{0};
|
||||
double z{0};
|
||||
for (ondemand::object point_object : doc["coordinates"]) {
|
||||
x += double(point_object.find_field("x"));
|
||||
y += double(point_object.find_field("y"));
|
||||
z += double(point_object.find_field("z"));
|
||||
}
|
||||
return (x == 1.1) && (y == 2.2) && (z == 3.3);
|
||||
}
|
||||
|
||||
bool out_of_order_object_index() {
|
||||
TEST_START();
|
||||
ondemand::parser parser{};
|
||||
auto doc = parser.iterate(json);
|
||||
|
@ -1443,7 +1644,37 @@ namespace ordering_tests {
|
|||
return (x == 1.1) && (y == 2.2) && (z == 3.3);
|
||||
}
|
||||
|
||||
bool foreach_lookup() {
|
||||
bool out_of_order_object_find_field_unordered() {
|
||||
TEST_START();
|
||||
ondemand::parser parser{};
|
||||
auto doc = parser.iterate(json);
|
||||
double x{0};
|
||||
double y{0};
|
||||
double z{0};
|
||||
for (ondemand::object point_object : doc["coordinates"]) {
|
||||
z += double(point_object.find_field_unordered("z"));
|
||||
x += double(point_object.find_field_unordered("x"));
|
||||
y += double(point_object.find_field_unordered("y"));
|
||||
}
|
||||
return (x == 1.1) && (y == 2.2) && (z == 3.3);
|
||||
}
|
||||
|
||||
bool out_of_order_object_find_field() {
|
||||
TEST_START();
|
||||
ondemand::parser parser{};
|
||||
auto doc = parser.iterate(json);
|
||||
double x{0};
|
||||
double y{0};
|
||||
double z{0};
|
||||
for (ondemand::object point_object : doc["coordinates"]) {
|
||||
z += double(point_object.find_field("z"));
|
||||
ASSERT_ERROR( point_object.find_field("x"), NO_SUCH_FIELD );
|
||||
ASSERT_ERROR( point_object.find_field("y"), NO_SUCH_FIELD );
|
||||
}
|
||||
return (x == 0) && (y == 0) && (z == 3.3);
|
||||
}
|
||||
|
||||
bool foreach_object_field_lookup() {
|
||||
TEST_START();
|
||||
ondemand::parser parser{};
|
||||
auto doc = parser.iterate(json);
|
||||
|
@ -1464,9 +1695,13 @@ namespace ordering_tests {
|
|||
bool run() {
|
||||
return
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
in_order() &&
|
||||
out_of_order() &&
|
||||
foreach_lookup() &&
|
||||
in_order_object_index() &&
|
||||
in_order_object_find_field_unordered() &&
|
||||
in_order_object_find_field() &&
|
||||
out_of_order_object_index() &&
|
||||
out_of_order_object_find_field_unordered() &&
|
||||
out_of_order_object_find_field() &&
|
||||
foreach_object_field_lookup() &&
|
||||
#endif
|
||||
true;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue