1#ifndef SIMDJSON_OBJECT_INL_H
2#define SIMDJSON_OBJECT_INL_H
4#include "simdjson/dom/base.h"
5#include "simdjson/dom/object.h"
6#include "simdjson/dom/document.h"
8#include "simdjson/dom/element-inl.h"
9#include "simdjson/error-inl.h"
10#include "simdjson/jsonpathutil.h"
19simdjson_inline simdjson_result<dom::object>::simdjson_result() noexcept
20 : internal::simdjson_result_base<dom::
object>() {}
21simdjson_inline simdjson_result<dom::object>::simdjson_result(dom::object value) noexcept
22 : internal::simdjson_result_base<dom::object>(std::forward<dom::object>(value)) {}
23simdjson_inline simdjson_result<dom::object>::simdjson_result(
error_code error) noexcept
24 : internal::simdjson_result_base<dom::object>(error) {}
26inline simdjson_result<dom::element> simdjson_result<dom::object>::operator[](std::string_view key)
const noexcept {
27 if (error()) {
return error(); }
30inline simdjson_result<dom::element> simdjson_result<dom::object>::operator[](
const char *key)
const noexcept {
31 if (error()) {
return error(); }
34inline simdjson_result<dom::element> simdjson_result<dom::object>::at_pointer(std::string_view json_pointer)
const noexcept {
35 if (error()) {
return error(); }
36 return first.at_pointer(json_pointer);
38inline simdjson_result<dom::element> simdjson_result<dom::object>::at_path(std::string_view json_path)
const noexcept {
41 return at_pointer(json_pointer);
43inline simdjson_result<std::vector<dom::element>> simdjson_result<dom::object>::at_path_with_wildcard(std::string_view json_path)
const noexcept {
47 return first.at_path_with_wildcard(json_path);
49inline simdjson_result<dom::element> simdjson_result<dom::object>::at_key(std::string_view key)
const noexcept {
50 if (error()) {
return error(); }
51 return first.at_key(key);
53inline std::vector<dom::element>& simdjson_result<dom::object>::get_values(std::vector<dom::element>& out)
const noexcept {
54 return first.get_values(out);
56inline simdjson_result<dom::element> simdjson_result<dom::object>::at_key_case_insensitive(std::string_view key)
const noexcept {
57 if (error()) {
return error(); }
58 return first.at_key_case_insensitive(key);
61#if SIMDJSON_EXCEPTIONS
63inline dom::object::iterator simdjson_result<dom::object>::begin() const noexcept(false) {
64 if (error()) {
throw simdjson_error(error()); }
67inline dom::object::iterator simdjson_result<dom::object>::end() const noexcept(false) {
68 if (error()) {
throw simdjson_error(error()); }
71inline size_t simdjson_result<dom::object>::size() const noexcept(false) {
72 if (error()) {
throw simdjson_error(error()); }
84simdjson_inline
object::object(
const internal::tape_ref &_tape) noexcept : tape{_tape} { }
86 SIMDJSON_DEVELOPMENT_ASSERT(tape.usable());
87 return internal::tape_ref(tape.doc, tape.json_index + 1);
90 SIMDJSON_DEVELOPMENT_ASSERT(tape.usable());
91 return internal::tape_ref(tape.doc, tape.after_element() - 1);
94 SIMDJSON_DEVELOPMENT_ASSERT(tape.usable());
95 return tape.scope_count();
105 SIMDJSON_DEVELOPMENT_ASSERT(tape.usable());
106 if(json_pointer.empty()) {
108 }
else if(json_pointer[0] !=
'/') {
111 json_pointer = json_pointer.substr(1);
112 size_t slash = json_pointer.find(
'/');
113 std::string_view key = json_pointer.substr(0, slash);
118 size_t escape = key.find(
'~');
119 if (escape != std::string_view::npos) {
121 std::string unescaped(key);
123 switch (unescaped[escape+1]) {
125 unescaped.replace(escape, 2,
"~");
128 unescaped.replace(escape, 2,
"/");
133 escape = unescaped.find(
'~', escape+1);
134 }
while (escape != std::string::npos);
135 child = at_key(unescaped);
143 if (slash != std::string_view::npos) {
144 child = child.at_pointer(json_pointer.substr(slash));
152 return at_pointer(json_pointer);
156 if (current == end) {
162 for (
auto it = current; it != end; ++it) {
163 std::vector<element> child_result;
164 auto error = it->at_path_with_wildcard(path_suffix).get(child_result);
168 accumulator.reserve(accumulator.size() + child_result.size());
169 accumulator.insert(accumulator.end(),
170 std::make_move_iterator(child_result.begin()),
171 std::make_move_iterator(child_result.end()));
176 SIMDJSON_DEVELOPMENT_ASSERT(tape.usable());
179 if (json_path.empty()) {
184 if (json_path.front() ==
'$') {
188 if (i >= json_path.size() || (json_path[i] !=
'.' && json_path[i] !=
'[')) {
194 if (json_path.find(
"*") != std::string::npos) {
196 std::vector<element> child_values;
199 (json_path.compare(i, 3,
"[*]") == 0 && json_path.size() == i + 3) ||
200 (json_path.compare(i, 2,
".*") == 0 && json_path.size() == i + 2)
202 get_values(child_values);
206 std::pair<std::string_view, std::string_view> key_and_json_path = get_next_key_and_json_path(json_path);
208 std::string_view key = key_and_json_path.first;
209 json_path = key_and_json_path.second;
211 if (key.size() > 0) {
213 get_values(child_values);
216 auto error = at_pointer(std::string(
"/") + std::string(key)).get(pointer_result);
219 child_values.emplace_back(pointer_result);
223 std::vector<element> result = {};
224 if (child_values.size() > 0) {
226 std::vector<element>::iterator child_values_begin = child_values.begin();
227 std::vector<element>::iterator child_values_end = child_values.end();
229 process_json_path_of_child_elements(child_values_begin, child_values_end, json_path, result);
238 auto error = this->at_path(json_path).get(result);
242 return std::vector<element>{std::move(result)};
248 for (
iterator field = begin(); field != end_field; ++field) {
249 if (field.key_equals(key)) {
250 return field.value();
260 out.reserve(std::distance(begin_field, end_field));
261 for (
iterator field = begin_field; field != end_field; ++field) {
262 out.emplace_back(field.value());
272 for (
iterator field = begin(); field != end_field; ++field) {
273 if (field.key_equals_case_insensitive(key)) {
274 return field.value();
280inline object::operator
element() const noexcept {
287simdjson_inline object::iterator::iterator(
const internal::tape_ref &_tape) noexcept : tape{_tape} { }
292 return tape.json_index != other.tape.json_index;
294inline bool object::iterator::operator==(
const object::iterator& other)
const noexcept {
295 return tape.json_index == other.tape.json_index;
297inline bool object::iterator::operator<(
const object::iterator& other)
const noexcept {
298 return tape.json_index < other.tape.json_index;
300inline bool object::iterator::operator<=(
const object::iterator& other)
const noexcept {
301 return tape.json_index <= other.tape.json_index;
303inline bool object::iterator::operator>=(
const object::iterator& other)
const noexcept {
304 return tape.json_index >= other.tape.json_index;
306inline bool object::iterator::operator>(
const object::iterator& other)
const noexcept {
307 return tape.json_index > other.tape.json_index;
311 tape.json_index = tape.after_element();
320 return tape.get_string_view();
323 return tape.get_string_length();
326 return reinterpret_cast<const char *
>(&tape.doc->string_buf[size_t(tape.tape_value()) +
sizeof(uint32_t)]);
329 return element(internal::tape_ref(tape.doc, tape.json_index + 1));
348 const uint32_t len = key_length();
349 if(o.size() == len) {
351 return (memcmp(o.data(), key_c_str(), len) == 0);
359 const uint32_t len = key_length();
360 if(o.size() == len) {
364 return (simdjson_strncasecmp(o.data(), key_c_str(), len) == 0);
371inline key_value_pair::key_value_pair(std::string_view _key,
element _value) noexcept :
372 key(_key), value(_value) {}
378#if SIMDJSON_SUPPORTS_RANGES
379static_assert(std::ranges::view<simdjson::dom::object>);
380static_assert(std::ranges::sized_range<simdjson::dom::object>);
381#if SIMDJSON_EXCEPTIONS
382static_assert(std::ranges::view<simdjson::simdjson_result<simdjson::dom::object>>);
383static_assert(std::ranges::sized_range<simdjson::simdjson_result<simdjson::dom::object>>);
Key/value pair in an object.
bool operator!=(const iterator &other) const noexcept
Check if these values come from the same place in the JSON.
element value() const noexcept
Get the value of this key/value pair.
bool key_equals(std::string_view o) const noexcept
Returns true if the key in this key/value pair is equal to the provided string_view.
const char * key_c_str() const noexcept
Get the key of this key/value pair.
uint32_t key_length() const noexcept
Get the length (in bytes) of the key in this key/value pair.
reference operator*() const noexcept
Get the actual key/value pair.
bool key_equals_case_insensitive(std::string_view o) const noexcept
Returns true if the key in this key/value pair is equal to the provided string_view in a case-insensi...
std::string_view key() const noexcept
Get the key of this key/value pair.
iterator & operator++() noexcept
Get the next key/value pair.
std::vector< element > & get_values(std::vector< element > &out) const noexcept
Gets the values associated with keys of an object This function has linear-time complexity: the keys ...
void process_json_path_of_child_elements(std::vector< element >::iterator ¤t, std::vector< element >::iterator &end, const std::string_view &path_suffix, std::vector< element > &accumulator) const noexcept
Recursive function which processes the JSON path of each child element.
simdjson_result< element > at_key(std::string_view key) const noexcept
Get the value associated with the given key.
iterator end() const noexcept
One past the last key/value pair.
simdjson_result< std::vector< element > > at_path_with_wildcard(std::string_view json_path) const noexcept
Adds support for JSONPath expression with wildcards '*'.
size_t size() const noexcept
Get the size of the object (number of keys).
simdjson_result< element > at_path(std::string_view json_path) const noexcept
Get the value associated with the given JSONPath expression.
simdjson_result< element > at_key_case_insensitive(std::string_view key) const noexcept
Get the value associated with the given key in a case-insensitive manner.
simdjson_result< element > operator[](std::string_view key) const noexcept
Get the value associated with the given key.
simdjson_result< element > at_pointer(std::string_view json_pointer) const noexcept
Get the value associated with the given JSON pointer.
simdjson_inline object() noexcept
Create a new, invalid object.
iterator begin() const noexcept
Return the first key/value pair.
The top level simdjson namespace, containing everything the library provides.
error_code
All possible errors returned by simdjson.
@ NO_SUCH_FIELD
JSON field not found in object.
@ INVALID_JSON_POINTER
Invalid JSON pointer syntax.
std::string json_path_to_pointer_conversion(std::string_view json_path)
Converts JSONPath to JSON Pointer.
The result of a simdjson operation that could fail.
simdjson_inline error_code error() const noexcept
The error.