simdjson  3.6.2
Ridiculously Fast JSON
array-inl.h
1 #ifndef SIMDJSON_ARRAY_INL_H
2 #define SIMDJSON_ARRAY_INL_H
3 
4 #include <utility>
5 
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/internal/tape_ref-inl.h"
11 
12 #include <limits>
13 
14 namespace simdjson {
15 
16 //
17 // simdjson_result<dom::array> inline implementation
18 //
19 simdjson_inline simdjson_result<dom::array>::simdjson_result() noexcept
20  : internal::simdjson_result_base<dom::array>() {}
21 simdjson_inline simdjson_result<dom::array>::simdjson_result(dom::array value) noexcept
22  : internal::simdjson_result_base<dom::array>(std::forward<dom::array>(value)) {}
23 simdjson_inline simdjson_result<dom::array>::simdjson_result(error_code error) noexcept
24  : internal::simdjson_result_base<dom::array>(error) {}
25 
26 #if SIMDJSON_EXCEPTIONS
27 
28 inline dom::array::iterator simdjson_result<dom::array>::begin() const noexcept(false) {
29  if (error()) { throw simdjson_error(error()); }
30  return first.begin();
31 }
32 inline dom::array::iterator simdjson_result<dom::array>::end() const noexcept(false) {
33  if (error()) { throw simdjson_error(error()); }
34  return first.end();
35 }
36 inline size_t simdjson_result<dom::array>::size() const noexcept(false) {
37  if (error()) { throw simdjson_error(error()); }
38  return first.size();
39 }
40 
41 #endif // SIMDJSON_EXCEPTIONS
42 
43 inline simdjson_result<dom::element> simdjson_result<dom::array>::at_pointer(std::string_view json_pointer) const noexcept {
44  if (error()) { return error(); }
45  return first.at_pointer(json_pointer);
46 }
47 inline simdjson_result<dom::element> simdjson_result<dom::array>::at(size_t index) const noexcept {
48  if (error()) { return error(); }
49  return first.at(index);
50 }
51 
52 namespace dom {
53 
54 //
55 // array inline implementation
56 //
57 simdjson_inline array::array() noexcept : tape{} {}
58 simdjson_inline array::array(const internal::tape_ref &_tape) noexcept : tape{_tape} {}
59 inline array::iterator array::begin() const noexcept {
60  SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
61  return internal::tape_ref(tape.doc, tape.json_index + 1);
62 }
63 inline array::iterator array::end() const noexcept {
64  SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
65  return internal::tape_ref(tape.doc, tape.after_element() - 1);
66 }
67 inline size_t array::size() const noexcept {
68  SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
69  return tape.scope_count();
70 }
71 inline size_t array::number_of_slots() const noexcept {
72  SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
73  return tape.matching_brace_index() - tape.json_index;
74 }
75 inline simdjson_result<element> array::at_pointer(std::string_view json_pointer) const noexcept {
76  SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
77  if(json_pointer.empty()) { // an empty string means that we return the current node
78  return element(this->tape); // copy the current node
79  } else if(json_pointer[0] != '/') { // otherwise there is an error
80  return INVALID_JSON_POINTER;
81  }
82  json_pointer = json_pointer.substr(1);
83  // - means "the append position" or "the element after the end of the array"
84  // We don't support this, because we're returning a real element, not a position.
85  if (json_pointer == "-") { return INDEX_OUT_OF_BOUNDS; }
86 
87  // Read the array index
88  size_t array_index = 0;
89  size_t i;
90  for (i = 0; i < json_pointer.length() && json_pointer[i] != '/'; i++) {
91  uint8_t digit = uint8_t(json_pointer[i] - '0');
92  // Check for non-digit in array index. If it's there, we're trying to get a field in an object
93  if (digit > 9) { return INCORRECT_TYPE; }
94  array_index = array_index*10 + digit;
95  }
96 
97  // 0 followed by other digits is invalid
98  if (i > 1 && json_pointer[0] == '0') { return INVALID_JSON_POINTER; } // "JSON pointer array index has other characters after 0"
99 
100  // Empty string is invalid; so is a "/" with no digits before it
101  if (i == 0) { return INVALID_JSON_POINTER; } // "Empty string in JSON pointer array index"
102 
103  // Get the child
104  auto child = array(tape).at(array_index);
105  // If there is an error, it ends here
106  if(child.error()) {
107  return child;
108  }
109  // If there is a /, we're not done yet, call recursively.
110  if (i < json_pointer.length()) {
111  child = child.at_pointer(json_pointer.substr(i));
112  }
113  return child;
114 }
115 
116 inline simdjson_result<element> array::at(size_t index) const noexcept {
117  SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
118  size_t i=0;
119  for (auto element : *this) {
120  if (i == index) { return element; }
121  i++;
122  }
123  return INDEX_OUT_OF_BOUNDS;
124 }
125 
126 //
127 // array::iterator inline implementation
128 //
129 simdjson_inline array::iterator::iterator(const internal::tape_ref &_tape) noexcept : tape{_tape} { }
130 inline element array::iterator::operator*() const noexcept {
131  return element(tape);
132 }
134  tape.json_index = tape.after_element();
135  return *this;
136 }
138  array::iterator out = *this;
139  ++*this;
140  return out;
141 }
142 inline bool array::iterator::operator!=(const array::iterator& other) const noexcept {
143  return tape.json_index != other.tape.json_index;
144 }
145 inline bool array::iterator::operator==(const array::iterator& other) const noexcept {
146  return tape.json_index == other.tape.json_index;
147 }
148 inline bool array::iterator::operator<(const array::iterator& other) const noexcept {
149  return tape.json_index < other.tape.json_index;
150 }
151 inline bool array::iterator::operator<=(const array::iterator& other) const noexcept {
152  return tape.json_index <= other.tape.json_index;
153 }
154 inline bool array::iterator::operator>=(const array::iterator& other) const noexcept {
155  return tape.json_index >= other.tape.json_index;
156 }
157 inline bool array::iterator::operator>(const array::iterator& other) const noexcept {
158  return tape.json_index > other.tape.json_index;
159 }
160 
161 } // namespace dom
162 
163 
164 } // namespace simdjson
165 
166 #include "simdjson/dom/element-inl.h"
167 
168 #if defined(__cpp_lib_ranges)
169 static_assert(std::ranges::view<simdjson::dom::array>);
170 static_assert(std::ranges::sized_range<simdjson::dom::array>);
171 #if SIMDJSON_EXCEPTIONS
172 static_assert(std::ranges::view<simdjson::simdjson_result<simdjson::dom::array>>);
173 static_assert(std::ranges::sized_range<simdjson::simdjson_result<simdjson::dom::array>>);
174 #endif // SIMDJSON_EXCEPTIONS
175 #endif // defined(__cpp_lib_ranges)
176 
177 #endif // SIMDJSON_ARRAY_INL_H
bool operator!=(const iterator &other) const noexcept
Check if these values come from the same place in the JSON.
Definition: array-inl.h:142
iterator & operator++() noexcept
Get the next value.
Definition: array-inl.h:133
value_type operator*() const noexcept
Get the actual value.
Definition: array-inl.h:130
JSON array.
Definition: array.h:13
size_t number_of_slots() const noexcept
Get the total number of slots used by this array on the tape.
Definition: array-inl.h:71
iterator end() const noexcept
One past the last array element.
Definition: array-inl.h:63
size_t size() const noexcept
Get the size of the array (number of immediate children).
Definition: array-inl.h:67
simdjson_result< element > at(size_t index) const noexcept
Get the value at the given index.
Definition: array-inl.h:116
simdjson_result< element > at_pointer(std::string_view json_pointer) const noexcept
Get the value associated with the given JSON pointer.
Definition: array-inl.h:75
simdjson_inline array() noexcept
Create a new, invalid array.
Definition: array-inl.h:57
iterator begin() const noexcept
Return the first array element.
Definition: array-inl.h:59
A JSON element.
Definition: element.h:31
The top level simdjson namespace, containing everything the library provides.
Definition: base.h:8
error_code
All possible errors returned by simdjson.
Definition: error.h:19
@ INCORRECT_TYPE
JSON element has a different type than user expected.
Definition: error.h:36
@ INDEX_OUT_OF_BOUNDS
JSON array index too large.
Definition: error.h:38
@ INVALID_JSON_POINTER
Invalid JSON pointer reference.
Definition: error.h:41
The result of a simdjson operation that could fail.
Definition: error.h:214
simdjson_inline error_code error() const noexcept
The error.
Definition: error-inl.h:131