1#ifndef SIMDJSON_ARRAY_INL_H
2#define SIMDJSON_ARRAY_INL_H
6#include "simdjson/dom/base.h"
7#include "simdjson/dom/array.h"
8#include "simdjson/dom/element.h"
9#include "simdjson/error-inl.h"
10#include "simdjson/jsonpathutil.h"
11#include "simdjson/internal/tape_ref-inl.h"
20simdjson_inline simdjson_result<dom::array>::simdjson_result() noexcept
21 : internal::simdjson_result_base<dom::array>() {}
22simdjson_inline simdjson_result<dom::array>::simdjson_result(dom::array value) noexcept
23 : internal::simdjson_result_base<dom::array>(std::forward<dom::array>(value)) {}
24simdjson_inline simdjson_result<dom::array>::simdjson_result(
error_code error) noexcept
25 : internal::simdjson_result_base<dom::array>(error) {}
27#if SIMDJSON_EXCEPTIONS
29inline dom::array::iterator simdjson_result<dom::array>::begin() const noexcept(false) {
30 if (error()) {
throw simdjson_error(error()); }
33inline dom::array::iterator simdjson_result<dom::array>::end() const noexcept(false) {
34 if (error()) {
throw simdjson_error(error()); }
37inline size_t simdjson_result<dom::array>::size() const noexcept(false) {
38 if (error()) {
throw simdjson_error(error()); }
41inline dom::array::reverse_iterator simdjson_result<dom::array>::rbegin() const noexcept(false) {
42 if (error()) {
throw simdjson_error(error()); }
43 return first.rbegin();
45inline dom::array::reverse_iterator simdjson_result<dom::array>::rend() const noexcept(false) {
46 if (error()) {
throw simdjson_error(error()); }
52inline simdjson_result<dom::element> simdjson_result<dom::array>::at_pointer(std::string_view json_pointer)
const noexcept {
53 if (error()) {
return error(); }
54 return first.at_pointer(json_pointer);
57 inline simdjson_result<dom::element> simdjson_result<dom::array>::at_path(std::string_view json_path)
const noexcept {
58 if (error()) {
return error(); }
61 return at_pointer(json_pointer);
64inline simdjson_result<std::vector<dom::element>> simdjson_result<dom::array>::at_path_with_wildcard(std::string_view json_path)
const noexcept {
68 return first.at_path_with_wildcard(json_path);
71inline simdjson_result<dom::element> simdjson_result<dom::array>::at(
size_t index)
const noexcept {
72 if (error()) {
return error(); }
73 return first.at(index);
76inline std::vector<dom::element>& simdjson_result<dom::array>::get_values(std::vector<dom::element>& out)
const noexcept {
77 return first.get_values(out);
86simdjson_inline
array::array(
const internal::tape_ref &_tape) noexcept : tape{_tape} {}
88 SIMDJSON_DEVELOPMENT_ASSERT(tape.usable());
89 return internal::tape_ref(tape.doc, tape.json_index + 1);
92 SIMDJSON_DEVELOPMENT_ASSERT(tape.usable());
93 return internal::tape_ref(tape.doc, tape.after_element() - 1);
96 SIMDJSON_DEVELOPMENT_ASSERT(tape.usable());
97 return tape.scope_count();
100 SIMDJSON_DEVELOPMENT_ASSERT(tape.usable());
101 const internal::tape_ref end_tape(tape.doc, tape.matching_brace_index() - 1);
102 return reverse_iterator(internal::tape_ref(tape.doc, end_tape.before_element(tape.json_index)), tape.json_index);
105 SIMDJSON_DEVELOPMENT_ASSERT(tape.usable());
109 SIMDJSON_DEVELOPMENT_ASSERT(tape.usable());
110 return tape.matching_brace_index() - tape.json_index;
113 SIMDJSON_DEVELOPMENT_ASSERT(tape.usable());
114 if(json_pointer.empty()) {
116 }
else if(json_pointer[0] !=
'/') {
119 json_pointer = json_pointer.substr(1);
124 size_t array_index = 0;
126 SIMDJSON_TRY(internal::parse_json_pointer_array_index(json_pointer, array_index, i));
129 auto child =
array(tape).
at(array_index);
135 if (i < json_pointer.length()) {
136 child = child.at_pointer(json_pointer.substr(i));
144 return at_pointer(json_pointer);
148 if (current == end) {
155 for (
auto it = current; it != end; ++it) {
156 std::vector<element> child_result;
157 auto error = it->at_path_with_wildcard(path_suffix).get(child_result);
161 accumulator.insert(accumulator.end(),
162 std::make_move_iterator(child_result.begin()),
163 std::make_move_iterator(child_result.end()));
168 SIMDJSON_DEVELOPMENT_ASSERT(tape.usable());
172 if (!json_path.empty() && json_path.front() ==
'$') {
176 if (i >= json_path.size() || (json_path[i] !=
'.' && json_path[i] !=
'[')) {
180 if (json_path.find(
"*") != std::string::npos) {
181 std::vector<element> child_values;
184 (json_path.compare(i, 3,
"[*]") == 0 && json_path.size() == i + 3) ||
185 (json_path.compare(i, 2,
".*") == 0 && json_path.size() == i + 2)
187 get_values(child_values);
191 std::pair<std::string_view, std::string_view> key_and_json_path = get_next_key_and_json_path(json_path);
193 std::string_view key = key_and_json_path.first;
194 json_path = key_and_json_path.second;
196 if (key.size() > 0) {
198 get_values(child_values);
201 std::string json_pointer = std::string(
"/") + std::string(key);
202 auto error = at_pointer(json_pointer).get(pointer_result);
205 child_values.emplace_back(pointer_result);
209 std::vector<element> result = {};
211 if (child_values.size() > 0) {
212 std::vector<element>::iterator child_values_begin = child_values.begin();
213 std::vector<element>::iterator child_values_end = child_values.end();
215 process_json_path_of_child_elements(child_values_begin, child_values_end, json_path, result);
224 auto error = at_path(json_path).get(result);
229 return std::vector<element>{std::move(result)};
234 SIMDJSON_DEVELOPMENT_ASSERT(tape.usable());
237 if (i == index) {
return element; }
244 out.reserve(this->size());
252inline array::operator
element() const noexcept {
259simdjson_inline array::reverse_iterator::reverse_iterator(
const internal::tape_ref &_tape,
size_t _array_start) noexcept
260 : tape{_tape}, array_start{_array_start} { }
261inline element array::reverse_iterator::operator*() const noexcept {
262 return element(tape);
264inline array::reverse_iterator& array::reverse_iterator::operator++() noexcept {
265 tape.json_index = tape.before_element(array_start);
268inline array::reverse_iterator array::reverse_iterator::operator++(
int)
noexcept {
269 reverse_iterator out = *
this;
273inline bool array::reverse_iterator::operator==(
const reverse_iterator& other)
const noexcept {
274 return tape.doc == other.tape.doc && tape.json_index == other.tape.json_index;
276inline bool array::reverse_iterator::operator!=(
const reverse_iterator& other)
const noexcept {
277 return !(*
this == other);
283simdjson_inline array::iterator::iterator(
const internal::tape_ref &_tape) noexcept : tape{_tape} { }
288 tape.json_index = tape.after_element();
297 return tape.json_index != other.tape.json_index;
299inline bool array::iterator::operator==(
const array::iterator& other)
const noexcept {
300 return tape.json_index == other.tape.json_index;
302inline bool array::iterator::operator<(
const array::iterator& other)
const noexcept {
303 return tape.json_index < other.tape.json_index;
305inline bool array::iterator::operator<=(
const array::iterator& other)
const noexcept {
306 return tape.json_index <= other.tape.json_index;
308inline bool array::iterator::operator>=(
const array::iterator& other)
const noexcept {
309 return tape.json_index >= other.tape.json_index;
311inline bool array::iterator::operator>(
const array::iterator& other)
const noexcept {
312 return tape.json_index > other.tape.json_index;
320#include "simdjson/dom/element-inl.h"
322#if SIMDJSON_SUPPORTS_RANGES
323static_assert(std::ranges::view<simdjson::dom::array>);
324static_assert(std::ranges::sized_range<simdjson::dom::array>);
325#if SIMDJSON_EXCEPTIONS
326static_assert(std::ranges::view<simdjson::simdjson_result<simdjson::dom::array>>);
327static_assert(std::ranges::sized_range<simdjson::simdjson_result<simdjson::dom::array>>);
bool operator!=(const iterator &other) const noexcept
Check if these values come from the same place in the JSON.
iterator & operator++() noexcept
Get the next value.
reference operator*() const noexcept
Get the actual value.
A forward iterator that visits the array's elements in reverse order.
std::vector< element > & get_values(std::vector< element > &out) const noexcept
Gets the values of items in an array element This function has linear-time complexity: the values are...
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 number_of_slots() const noexcept
Get the total number of slots used by this array on the tape.
iterator end() const noexcept
One past the last array element.
size_t size() const noexcept
Get the size of the array (number of immediate children).
simdjson_result< element > at(size_t index) const noexcept
Get the value at the given index.
simdjson_result< element > at_pointer(std::string_view json_pointer) const noexcept
Get the value associated with the given JSON pointer.
reverse_iterator rbegin() const noexcept
Return the last array element, or rend() for an empty array.
simdjson_inline array() noexcept
Create a new, invalid array.
simdjson_result< element > at_path(std::string_view json_path) const noexcept
Get the value associated with the given JSONPath expression.
reverse_iterator rend() const noexcept
Return the reverse traversal sentinel, before the first element.
iterator begin() const noexcept
Return the first array element.
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.
The top level simdjson namespace, containing everything the library provides.
error_code
All possible errors returned by simdjson.
@ INDEX_OUT_OF_BOUNDS
JSON array index too large.
@ 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.