simdjson  3.11.0
Ridiculously Fast JSON
object-inl.h
1 #ifndef SIMDJSON_GENERIC_ONDEMAND_OBJECT_INL_H
2 
3 #ifndef SIMDJSON_CONDITIONAL_INCLUDE
4 #define SIMDJSON_GENERIC_ONDEMAND_OBJECT_INL_H
5 #include "simdjson/generic/ondemand/base.h"
6 #include "simdjson/generic/ondemand/field.h"
7 #include "simdjson/generic/ondemand/object.h"
8 #include "simdjson/generic/ondemand/object_iterator.h"
9 #include "simdjson/generic/ondemand/raw_json_string.h"
10 #include "simdjson/generic/ondemand/json_iterator.h"
11 #include "simdjson/generic/ondemand/value-inl.h"
12 #endif // SIMDJSON_CONDITIONAL_INCLUDE
13 
14 namespace simdjson {
15 namespace SIMDJSON_IMPLEMENTATION {
16 namespace ondemand {
17 
18 simdjson_inline simdjson_result<value> object::find_field_unordered(const std::string_view key) & noexcept {
19  bool has_value;
20  SIMDJSON_TRY( iter.find_field_unordered_raw(key).get(has_value) );
21  if (!has_value) {
22  logger::log_line(iter.json_iter(), "ERROR: ", "Cannot find key %.*s", "", -1, 0, logger::log_level::error, static_cast<int>(key.size()), key.data());
23  return NO_SUCH_FIELD;
24  }
25  return value(iter.child());
26 }
27 simdjson_inline simdjson_result<value> object::find_field_unordered(const std::string_view key) && noexcept {
28  bool has_value;
29  SIMDJSON_TRY( iter.find_field_unordered_raw(key).get(has_value) );
30  if (!has_value) {
31  logger::log_line(iter.json_iter(), "ERROR: ", "Cannot find key %.*s", "", -1, 0, logger::log_level::error, static_cast<int>(key.size()), key.data());
32  return NO_SUCH_FIELD;
33  }
34  return value(iter.child());
35 }
36 simdjson_inline simdjson_result<value> object::operator[](const std::string_view key) & noexcept {
37  return find_field_unordered(key);
38 }
39 simdjson_inline simdjson_result<value> object::operator[](const std::string_view key) && noexcept {
40  return std::forward<object>(*this).find_field_unordered(key);
41 }
42 simdjson_inline simdjson_result<value> object::find_field(const std::string_view key) & noexcept {
43  bool has_value;
44  SIMDJSON_TRY( iter.find_field_raw(key).get(has_value) );
45  if (!has_value) {
46  logger::log_line(iter.json_iter(), "ERROR: ", "Cannot find key %.*s", "", -1, 0, logger::log_level::error, static_cast<int>(key.size()), key.data());
47  return NO_SUCH_FIELD;
48  }
49  return value(iter.child());
50 }
51 simdjson_inline simdjson_result<value> object::find_field(const std::string_view key) && noexcept {
52  bool has_value;
53  SIMDJSON_TRY( iter.find_field_raw(key).get(has_value) );
54  if (!has_value) {
55  logger::log_line(iter.json_iter(), "ERROR: ", "Cannot find key %.*s", "", -1, 0, logger::log_level::error, static_cast<int>(key.size()), key.data());
56  return NO_SUCH_FIELD;
57  }
58  return value(iter.child());
59 }
60 
61 simdjson_inline simdjson_result<object> object::start(value_iterator &iter) noexcept {
62  SIMDJSON_TRY( iter.start_object().error() );
63  return object(iter);
64 }
65 simdjson_inline simdjson_result<object> object::start_root(value_iterator &iter) noexcept {
66  SIMDJSON_TRY( iter.start_root_object().error() );
67  return object(iter);
68 }
69 simdjson_inline error_code object::consume() noexcept {
70  if(iter.is_at_key()) {
84  simdjson_unused raw_json_string actual_key;
85  auto error = iter.field_key().get(actual_key);
86  if (error) { iter.abandon(); return error; };
87  // Let us move to the value while we are at it.
88  if ((error = iter.field_value())) { iter.abandon(); return error; }
89  }
90  auto error_skip = iter.json_iter().skip_child(iter.depth()-1);
91  if(error_skip) { iter.abandon(); }
92  return error_skip;
93 }
94 
96  const uint8_t * starting_point{iter.peek_start()};
97  auto error = consume();
98  if(error) { return error; }
99  const uint8_t * final_point{iter._json_iter->peek()};
100  return std::string_view(reinterpret_cast<const char*>(starting_point), size_t(final_point - starting_point));
101 }
102 
103 simdjson_inline simdjson_result<object> object::started(value_iterator &iter) noexcept {
104  SIMDJSON_TRY( iter.started_object().error() );
105  return object(iter);
106 }
107 
108 simdjson_inline object object::resume(const value_iterator &iter) noexcept {
109  return iter;
110 }
111 
112 simdjson_inline object::object(const value_iterator &_iter) noexcept
113  : iter{_iter}
114 {
115 }
116 
117 simdjson_inline simdjson_result<object_iterator> object::begin() noexcept {
118 #if SIMDJSON_DEVELOPMENT_CHECKS
119  if (!iter.is_at_iterator_start()) { return OUT_OF_ORDER_ITERATION; }
120 #endif
121  return object_iterator(iter);
122 }
123 simdjson_inline simdjson_result<object_iterator> object::end() noexcept {
124  return object_iterator(iter);
125 }
126 
127 inline simdjson_result<value> object::at_pointer(std::string_view json_pointer) noexcept {
128  if (json_pointer[0] != '/') { return INVALID_JSON_POINTER; }
129  json_pointer = json_pointer.substr(1);
130  size_t slash = json_pointer.find('/');
131  std::string_view key = json_pointer.substr(0, slash);
132  // Grab the child with the given key
134 
135  // If there is an escape character in the key, unescape it and then get the child.
136  size_t escape = key.find('~');
137  if (escape != std::string_view::npos) {
138  // Unescape the key
139  std::string unescaped(key);
140  do {
141  switch (unescaped[escape+1]) {
142  case '0':
143  unescaped.replace(escape, 2, "~");
144  break;
145  case '1':
146  unescaped.replace(escape, 2, "/");
147  break;
148  default:
149  return INVALID_JSON_POINTER; // "Unexpected ~ escape character in JSON pointer");
150  }
151  escape = unescaped.find('~', escape+1);
152  } while (escape != std::string::npos);
153  child = find_field(unescaped); // Take note find_field does not unescape keys when matching
154  } else {
155  child = find_field(key);
156  }
157  if(child.error()) {
158  return child; // we do not continue if there was an error
159  }
160  // If there is a /, we have to recurse and look up more of the path
161  if (slash != std::string_view::npos) {
162  child = child.at_pointer(json_pointer.substr(slash));
163  }
164  return child;
165 }
166 
167 inline simdjson_result<value> object::at_path(std::string_view json_path) noexcept {
168  auto json_pointer = json_path_to_pointer_conversion(json_path);
169  if (json_pointer == "-1") {
170  return INVALID_JSON_POINTER;
171  }
172  return at_pointer(json_pointer);
173 }
174 
175 simdjson_inline simdjson_result<size_t> object::count_fields() & noexcept {
176  size_t count{0};
177  // Important: we do not consume any of the values.
178  for(simdjson_unused auto v : *this) { count++; }
179  // The above loop will always succeed, but we want to report errors.
180  if(iter.error()) { return iter.error(); }
181  // We need to move back at the start because we expect users to iterate through
182  // the object after counting the number of elements.
183  iter.reset_object();
184  return count;
185 }
186 
187 simdjson_inline simdjson_result<bool> object::is_empty() & noexcept {
188  bool is_not_empty;
189  auto error = iter.reset_object().get(is_not_empty);
190  if(error) { return error; }
191  return !is_not_empty;
192 }
193 
194 simdjson_inline simdjson_result<bool> object::reset() & noexcept {
195  return iter.reset_object();
196 }
197 
198 } // namespace ondemand
199 } // namespace SIMDJSON_IMPLEMENTATION
200 } // namespace simdjson
201 
202 namespace simdjson {
203 
204 simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object>::simdjson_result(SIMDJSON_IMPLEMENTATION::ondemand::object &&value) noexcept
205  : implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::object>(std::forward<SIMDJSON_IMPLEMENTATION::ondemand::object>(value)) {}
206 simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object>::simdjson_result(error_code error) noexcept
207  : implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::object>(error) {}
208 
209 simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object_iterator> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object>::begin() noexcept {
210  if (error()) { return error(); }
211  return first.begin();
212 }
213 simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object_iterator> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object>::end() noexcept {
214  if (error()) { return error(); }
215  return first.end();
216 }
217 simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object>::find_field_unordered(std::string_view key) & noexcept {
218  if (error()) { return error(); }
219  return first.find_field_unordered(key);
220 }
221 simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object>::find_field_unordered(std::string_view key) && noexcept {
222  if (error()) { return error(); }
223  return std::forward<SIMDJSON_IMPLEMENTATION::ondemand::object>(first).find_field_unordered(key);
224 }
225 simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object>::operator[](std::string_view key) & noexcept {
226  if (error()) { return error(); }
227  return first[key];
228 }
229 simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object>::operator[](std::string_view key) && noexcept {
230  if (error()) { return error(); }
231  return std::forward<SIMDJSON_IMPLEMENTATION::ondemand::object>(first)[key];
232 }
233 simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object>::find_field(std::string_view key) & noexcept {
234  if (error()) { return error(); }
235  return first.find_field(key);
236 }
237 simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object>::find_field(std::string_view key) && noexcept {
238  if (error()) { return error(); }
239  return std::forward<SIMDJSON_IMPLEMENTATION::ondemand::object>(first).find_field(key);
240 }
241 
242 simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object>::at_pointer(std::string_view json_pointer) noexcept {
243  if (error()) { return error(); }
244  return first.at_pointer(json_pointer);
245 }
246 
247 simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object>::at_path(
248  std::string_view json_path) noexcept {
249  if (error()) {
250  return error();
251  }
252  return first.at_path(json_path);
253 }
254 
255 inline simdjson_result<bool> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object>::reset() noexcept {
256  if (error()) { return error(); }
257  return first.reset();
258 }
259 
260 inline simdjson_result<bool> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object>::is_empty() noexcept {
261  if (error()) { return error(); }
262  return first.is_empty();
263 }
264 
265 simdjson_inline simdjson_result<size_t> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object>::count_fields() & noexcept {
266  if (error()) { return error(); }
267  return first.count_fields();
268 }
269 
270 simdjson_inline simdjson_result<std::string_view> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object>::raw_json() noexcept {
271  if (error()) { return error(); }
272  return first.raw_json();
273 }
274 } // namespace simdjson
275 
276 #endif // SIMDJSON_GENERIC_ONDEMAND_OBJECT_INL_H
A forward-only JSON object field iterator.
Definition: object.h:17
simdjson_inline object() noexcept=default
Create a new invalid object.
simdjson_inline simdjson_result< value > find_field_unordered(std::string_view key) &noexcept
Look up a field by name on an object, without regard to key order.
Definition: object-inl.h:18
simdjson_inline simdjson_result< std::string_view > raw_json() noexcept
Consumes the object and returns a string_view instance corresponding to the object as represented in ...
Definition: object-inl.h:95
simdjson_inline simdjson_result< value > find_field(std::string_view key) &noexcept
Look up a field by name on an object (order-sensitive).
Definition: object-inl.h:42
simdjson_result< bool > is_empty() &noexcept
This method scans the beginning of the object and checks whether the object is empty.
Definition: object-inl.h:187
simdjson_inline error_code consume() noexcept
Go to the end of the object, no matter where you are right now.
Definition: object-inl.h:69
simdjson_result< bool > reset() &noexcept
Reset the iterator so that we are pointing back at the beginning of the object.
Definition: object-inl.h:194
simdjson_result< value > at_path(std::string_view json_path) noexcept
Get the value associated with the given JSONPath expression.
Definition: object-inl.h:167
simdjson_result< value > at_pointer(std::string_view json_pointer) noexcept
Get the value associated with the given JSON pointer.
Definition: object-inl.h:127
simdjson_inline simdjson_result< size_t > count_fields() &noexcept
This method scans the object and counts the number of key-value pairs.
Definition: object-inl.h:175
A string escaped per JSON rules, terminated with quote (").
An ephemeral JSON value returned during iteration.
Definition: value.h:21
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
@ OUT_OF_ORDER_ITERATION
tried to iterate an array or object out of order (checked when SIMDJSON_DEVELOPMENT_CHECKS=1)
Definition: error.h:46
@ NO_SUCH_FIELD
JSON field not found in object.
Definition: error.h:40
@ INVALID_JSON_POINTER
Invalid JSON pointer syntax.
Definition: error.h:42
std::string json_path_to_pointer_conversion(std::string_view json_path)
Converts JSONPath to JSON Pointer.
Definition: jsonpathutil.h:13
The result of a simdjson operation that could fail.
Definition: error.h:215
simdjson_inline error_code error() const noexcept
The error.
Definition: error-inl.h:131