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