simdjson  3.11.0
Ridiculously Fast JSON
value_iterator-inl.h
1 #ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H
2 
3 #ifndef SIMDJSON_CONDITIONAL_INCLUDE
4 #define SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H
5 #include "simdjson/generic/ondemand/base.h"
6 #include "simdjson/generic/atomparsing.h"
7 #include "simdjson/generic/numberparsing.h"
8 #include "simdjson/generic/ondemand/json_iterator.h"
9 #include "simdjson/generic/ondemand/value_iterator.h"
10 #include "simdjson/generic/ondemand/json_type-inl.h"
11 #include "simdjson/generic/ondemand/raw_json_string-inl.h"
12 #endif // SIMDJSON_CONDITIONAL_INCLUDE
13 
14 namespace simdjson {
15 namespace SIMDJSON_IMPLEMENTATION {
16 namespace ondemand {
17 
18 simdjson_inline value_iterator::value_iterator(
19  json_iterator *json_iter,
20  depth_t depth,
21  token_position start_position
22 ) noexcept : _json_iter{json_iter}, _depth{depth}, _start_position{start_position}
23 {
24 }
25 
26 simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::start_object() noexcept {
27  SIMDJSON_TRY( start_container('{', "Not an object", "object") );
28  return started_object();
29 }
30 
31 simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::start_root_object() noexcept {
32  SIMDJSON_TRY( start_container('{', "Not an object", "object") );
33  return started_root_object();
34 }
35 
36 simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::started_object() noexcept {
37  assert_at_container_start();
38 #if SIMDJSON_DEVELOPMENT_CHECKS
39  _json_iter->set_start_position(_depth, start_position());
40 #endif
41  if (*_json_iter->peek() == '}') {
42  logger::log_value(*_json_iter, "empty object");
43  _json_iter->return_current_and_advance();
44  end_container();
45  return false;
46  }
47  return true;
48 }
49 
50 simdjson_warn_unused simdjson_inline error_code value_iterator::check_root_object() noexcept {
51  // When in streaming mode, we cannot expect peek_last() to be the last structural element of the
52  // current document. It only works in the normal mode where we have indexed a single document.
53  // Note that adding a check for 'streaming' is not expensive since we only have at most
54  // one root element.
55  if ( ! _json_iter->streaming() ) {
56  // The following lines do not fully protect against garbage content within the
57  // object: e.g., `{"a":2} foo }`. Users concerned with garbage content should
58  // call `at_end()` on the document instance at the end of the processing to
59  // ensure that the processing has finished at the end.
60  //
61  if (*_json_iter->peek_last() != '}') {
62  _json_iter->abandon();
63  return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing } at end");
64  }
65  // If the last character is } *and* the first gibberish character is also '}'
66  // then on-demand could accidentally go over. So we need additional checks.
67  // https://github.com/simdjson/simdjson/issues/1834
68  // Checking that the document is balanced requires a full scan which is potentially
69  // expensive, but it only happens in edge cases where the first padding character is
70  // a closing bracket.
71  if ((*_json_iter->peek(_json_iter->end_position()) == '}') && (!_json_iter->balanced())) {
72  _json_iter->abandon();
73  // The exact error would require more work. It will typically be an unclosed object.
74  return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "the document is unbalanced");
75  }
76  }
77  return SUCCESS;
78 }
79 
80 simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::started_root_object() noexcept {
81  auto error = check_root_object();
82  if(error) { return error; }
83  return started_object();
84 }
85 
86 simdjson_warn_unused simdjson_inline error_code value_iterator::end_container() noexcept {
87 #if SIMDJSON_CHECK_EOF
88  if (depth() > 1 && at_end()) { return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing parent ] or }"); }
89  // if (depth() <= 1 && !at_end()) { return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing [ or { at start"); }
90 #endif // SIMDJSON_CHECK_EOF
91  _json_iter->ascend_to(depth()-1);
92  return SUCCESS;
93 }
94 
95 simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::has_next_field() noexcept {
96  assert_at_next();
97 
98  // It's illegal to call this unless there are more tokens: anything that ends in } or ] is
99  // obligated to verify there are more tokens if they are not the top level.
100  switch (*_json_iter->return_current_and_advance()) {
101  case '}':
102  logger::log_end_value(*_json_iter, "object");
103  SIMDJSON_TRY( end_container() );
104  return false;
105  case ',':
106  return true;
107  default:
108  return report_error(TAPE_ERROR, "Missing comma between object fields");
109  }
110 }
111 
112 simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::find_field_raw(const std::string_view key) noexcept {
113  error_code error;
114  bool has_value;
115  //
116  // Initially, the object can be in one of a few different places:
117  //
118  // 1. The start of the object, at the first field:
119  //
120  // ```
121  // { "a": [ 1, 2 ], "b": [ 3, 4 ] }
122  // ^ (depth 2, index 1)
123  // ```
124  if (at_first_field()) {
125  has_value = true;
126 
127  //
128  // 2. When a previous search did not yield a value or the object is empty:
129  //
130  // ```
131  // { "a": [ 1, 2 ], "b": [ 3, 4 ] }
132  // ^ (depth 0)
133  // { }
134  // ^ (depth 0, index 2)
135  // ```
136  //
137  } else if (!is_open()) {
138 #if SIMDJSON_DEVELOPMENT_CHECKS
139  // If we're past the end of the object, we're being iterated out of order.
140  // Note: this is not perfect detection. It's possible the user is inside some other object; if so,
141  // this object iterator will blithely scan that object for fields.
142  if (_json_iter->depth() < depth() - 1) { return OUT_OF_ORDER_ITERATION; }
143 #endif
144  return false;
145 
146  // 3. When a previous search found a field or an iterator yielded a value:
147  //
148  // ```
149  // // When a field was not fully consumed (or not even touched at all)
150  // { "a": [ 1, 2 ], "b": [ 3, 4 ] }
151  // ^ (depth 2)
152  // // When a field was fully consumed
153  // { "a": [ 1, 2 ], "b": [ 3, 4 ] }
154  // ^ (depth 1)
155  // // When the last field was fully consumed
156  // { "a": [ 1, 2 ], "b": [ 3, 4 ] }
157  // ^ (depth 1)
158  // ```
159  //
160  } else {
161  if ((error = skip_child() )) { abandon(); return error; }
162  if ((error = has_next_field().get(has_value) )) { abandon(); return error; }
163 #if SIMDJSON_DEVELOPMENT_CHECKS
164  if (_json_iter->start_position(_depth) != start_position()) { return OUT_OF_ORDER_ITERATION; }
165 #endif
166  }
167  while (has_value) {
168  // Get the key and colon, stopping at the value.
169  raw_json_string actual_key;
170  // size_t max_key_length = _json_iter->peek_length() - 2; // -2 for the two quotes
171  // Note: _json_iter->peek_length() - 2 might overflow if _json_iter->peek_length() < 2.
172  // field_key() advances the pointer and checks that '"' is found (corresponding to a key).
173  // The depth is left unchanged by field_key().
174  if ((error = field_key().get(actual_key) )) { abandon(); return error; };
175  // field_value() will advance and check that we find a ':' separating the
176  // key and the value. It will also increment the depth by one.
177  if ((error = field_value() )) { abandon(); return error; }
178  // If it matches, stop and return
179  // We could do it this way if we wanted to allow arbitrary
180  // key content (including escaped quotes).
181  //if (actual_key.unsafe_is_equal(max_key_length, key)) {
182  // Instead we do the following which may trigger buffer overruns if the
183  // user provides an adversarial key (containing a well placed unescaped quote
184  // character and being longer than the number of bytes remaining in the JSON
185  // input).
186  if (actual_key.unsafe_is_equal(key)) {
187  logger::log_event(*this, "match", key, -2);
188  // If we return here, then we return while pointing at the ':' that we just checked.
189  return true;
190  }
191 
192  // No match: skip the value and see if , or } is next
193  logger::log_event(*this, "no match", key, -2);
194  // The call to skip_child is meant to skip over the value corresponding to the key.
195  // After skip_child(), we are right before the next comma (',') or the final brace ('}').
196  SIMDJSON_TRY( skip_child() ); // Skip the value entirely
197  // The has_next_field() advances the pointer and check that either ',' or '}' is found.
198  // It returns true if ',' is found, false otherwise. If anything other than ',' or '}' is found,
199  // then we are in error and we abort.
200  if ((error = has_next_field().get(has_value) )) { abandon(); return error; }
201  }
202 
203  // If the loop ended, we're out of fields to look at.
204  return false;
205 }
206 
207 SIMDJSON_PUSH_DISABLE_WARNINGS
208 SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING
209 simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::find_field_unordered_raw(const std::string_view key) noexcept {
217  error_code error;
218  bool has_value;
219 
220  // First, we scan from that point to the end.
221  // If we don't find a match, we may loop back around, and scan from the beginning to that point.
222  token_position search_start = _json_iter->position();
223 
224  // We want to know whether we need to go back to the beginning.
225  bool at_first = at_first_field();
227  // Initially, the object can be in one of a few different places:
228  //
229  // 1. At the first key:
230  //
231  // ```
232  // { "a": [ 1, 2 ], "b": [ 3, 4 ] }
233  // ^ (depth 2, index 1)
234  // ```
235  //
236  if (at_first) {
237  has_value = true;
238 
239  // 2. When a previous search did not yield a value or the object is empty:
240  //
241  // ```
242  // { "a": [ 1, 2 ], "b": [ 3, 4 ] }
243  // ^ (depth 0)
244  // { }
245  // ^ (depth 0, index 2)
246  // ```
247  //
248  } else if (!is_open()) {
249 
250 #if SIMDJSON_DEVELOPMENT_CHECKS
251  // If we're past the end of the object, we're being iterated out of order.
252  // Note: this is not perfect detection. It's possible the user is inside some other object; if so,
253  // this object iterator will blithely scan that object for fields.
254  if (_json_iter->depth() < depth() - 1) { return OUT_OF_ORDER_ITERATION; }
255 #endif
256  SIMDJSON_TRY(reset_object().get(has_value));
257  at_first = true;
258  // 3. When a previous search found a field or an iterator yielded a value:
259  //
260  // ```
261  // // When a field was not fully consumed (or not even touched at all)
262  // { "a": [ 1, 2 ], "b": [ 3, 4 ] }
263  // ^ (depth 2)
264  // // When a field was fully consumed
265  // { "a": [ 1, 2 ], "b": [ 3, 4 ] }
266  // ^ (depth 1)
267  // // When the last field was fully consumed
268  // { "a": [ 1, 2 ], "b": [ 3, 4 ] }
269  // ^ (depth 1)
270  // ```
271  //
272  } else {
273  // If someone queried a key but they not did access the value, then we are left pointing
274  // at the ':' and we need to move forward through the value... If the value was
275  // processed then skip_child() does not move the iterator (but may adjust the depth).
276  if ((error = skip_child() )) { abandon(); return error; }
277  search_start = _json_iter->position();
278  if ((error = has_next_field().get(has_value) )) { abandon(); return error; }
279 #if SIMDJSON_DEVELOPMENT_CHECKS
280  if (_json_iter->start_position(_depth) != start_position()) { return OUT_OF_ORDER_ITERATION; }
281 #endif
282  }
283 
284  // After initial processing, we will be in one of two states:
285  //
286  // ```
287  // // At the beginning of a field
288  // { "a": [ 1, 2 ], "b": [ 3, 4 ] }
289  // ^ (depth 1)
290  // { "a": [ 1, 2 ], "b": [ 3, 4 ] }
291  // ^ (depth 1)
292  // // At the end of the object
293  // { "a": [ 1, 2 ], "b": [ 3, 4 ] }
294  // ^ (depth 0)
295  // ```
296  //
297  // Next, we find a match starting from the current position.
298  while (has_value) {
299  SIMDJSON_ASSUME( _json_iter->_depth == _depth ); // We must be at the start of a field
300 
301  // Get the key and colon, stopping at the value.
302  raw_json_string actual_key;
303  // size_t max_key_length = _json_iter->peek_length() - 2; // -2 for the two quotes
304  // Note: _json_iter->peek_length() - 2 might overflow if _json_iter->peek_length() < 2.
305  // field_key() advances the pointer and checks that '"' is found (corresponding to a key).
306  // The depth is left unchanged by field_key().
307  if ((error = field_key().get(actual_key) )) { abandon(); return error; };
308  // field_value() will advance and check that we find a ':' separating the
309  // key and the value. It will also increment the depth by one.
310  if ((error = field_value() )) { abandon(); return error; }
311 
312  // If it matches, stop and return
313  // We could do it this way if we wanted to allow arbitrary
314  // key content (including escaped quotes).
315  // if (actual_key.unsafe_is_equal(max_key_length, key)) {
316  // Instead we do the following which may trigger buffer overruns if the
317  // user provides an adversarial key (containing a well placed unescaped quote
318  // character and being longer than the number of bytes remaining in the JSON
319  // input).
320  if (actual_key.unsafe_is_equal(key)) {
321  logger::log_event(*this, "match", key, -2);
322  // If we return here, then we return while pointing at the ':' that we just checked.
323  return true;
324  }
325 
326  // No match: skip the value and see if , or } is next
327  logger::log_event(*this, "no match", key, -2);
328  // The call to skip_child is meant to skip over the value corresponding to the key.
329  // After skip_child(), we are right before the next comma (',') or the final brace ('}').
330  SIMDJSON_TRY( skip_child() );
331  // The has_next_field() advances the pointer and check that either ',' or '}' is found.
332  // It returns true if ',' is found, false otherwise. If anything other than ',' or '}' is found,
333  // then we are in error and we abort.
334  if ((error = has_next_field().get(has_value) )) { abandon(); return error; }
335  }
336  // Performance note: it maybe wasteful to rewind to the beginning when there might be
337  // no other query following. Indeed, it would require reskipping the whole object.
338  // Instead, you can just stay where you are. If there is a new query, there is always time
339  // to rewind.
340  if(at_first) { return false; }
341 
342  // If we reach the end without finding a match, search the rest of the fields starting at the
343  // beginning of the object.
344  // (We have already run through the object before, so we've already validated its structure. We
345  // don't check errors in this bit.)
346  SIMDJSON_TRY(reset_object().get(has_value));
347  while (true) {
348  SIMDJSON_ASSUME(has_value); // we should reach search_start before ever reaching the end of the object
349  SIMDJSON_ASSUME( _json_iter->_depth == _depth ); // We must be at the start of a field
350 
351  // Get the key and colon, stopping at the value.
352  raw_json_string actual_key;
353  // size_t max_key_length = _json_iter->peek_length() - 2; // -2 for the two quotes
354  // Note: _json_iter->peek_length() - 2 might overflow if _json_iter->peek_length() < 2.
355  // field_key() advances the pointer and checks that '"' is found (corresponding to a key).
356  // The depth is left unchanged by field_key().
357  error = field_key().get(actual_key); SIMDJSON_ASSUME(!error);
358  // field_value() will advance and check that we find a ':' separating the
359  // key and the value. It will also increment the depth by one.
360  error = field_value(); SIMDJSON_ASSUME(!error);
361 
362  // If it matches, stop and return
363  // We could do it this way if we wanted to allow arbitrary
364  // key content (including escaped quotes).
365  // if (actual_key.unsafe_is_equal(max_key_length, key)) {
366  // Instead we do the following which may trigger buffer overruns if the
367  // user provides an adversarial key (containing a well placed unescaped quote
368  // character and being longer than the number of bytes remaining in the JSON
369  // input).
370  if (actual_key.unsafe_is_equal(key)) {
371  logger::log_event(*this, "match", key, -2);
372  // If we return here, then we return while pointing at the ':' that we just checked.
373  return true;
374  }
375 
376  // No match: skip the value and see if , or } is next
377  logger::log_event(*this, "no match", key, -2);
378  // The call to skip_child is meant to skip over the value corresponding to the key.
379  // After skip_child(), we are right before the next comma (',') or the final brace ('}').
380  SIMDJSON_TRY( skip_child() );
381  // If we reached the end of the key-value pair we started from, then we know
382  // that the key is not there so we return false. We are either right before
383  // the next comma or the final brace.
384  if(_json_iter->position() == search_start) { return false; }
385  // The has_next_field() advances the pointer and check that either ',' or '}' is found.
386  // It returns true if ',' is found, false otherwise. If anything other than ',' or '}' is found,
387  // then we are in error and we abort.
388  error = has_next_field().get(has_value); SIMDJSON_ASSUME(!error);
389  // If we make the mistake of exiting here, then we could be left pointing at a key
390  // in the middle of an object. That's not an allowable state.
391  }
392  // If the loop ended, we're out of fields to look at. The program should
393  // never reach this point.
394  return false;
395 }
396 SIMDJSON_POP_DISABLE_WARNINGS
397 
398 simdjson_warn_unused simdjson_inline simdjson_result<raw_json_string> value_iterator::field_key() noexcept {
399  assert_at_next();
400 
401  const uint8_t *key = _json_iter->return_current_and_advance();
402  if (*(key++) != '"') { return report_error(TAPE_ERROR, "Object key is not a string"); }
403  return raw_json_string(key);
404 }
405 
406 simdjson_warn_unused simdjson_inline error_code value_iterator::field_value() noexcept {
407  assert_at_next();
408 
409  if (*_json_iter->return_current_and_advance() != ':') { return report_error(TAPE_ERROR, "Missing colon in object field"); }
410  _json_iter->descend_to(depth()+1);
411  return SUCCESS;
412 }
413 
414 simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::start_array() noexcept {
415  SIMDJSON_TRY( start_container('[', "Not an array", "array") );
416  return started_array();
417 }
418 
419 simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::start_root_array() noexcept {
420  SIMDJSON_TRY( start_container('[', "Not an array", "array") );
421  return started_root_array();
422 }
423 
424 inline std::string value_iterator::to_string() const noexcept {
425  auto answer = std::string("value_iterator [ depth : ") + std::to_string(_depth) + std::string(", ");
426  if(_json_iter != nullptr) { answer += _json_iter->to_string(); }
427  answer += std::string(" ]");
428  return answer;
429 }
430 
431 simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::started_array() noexcept {
432  assert_at_container_start();
433  if (*_json_iter->peek() == ']') {
434  logger::log_value(*_json_iter, "empty array");
435  _json_iter->return_current_and_advance();
436  SIMDJSON_TRY( end_container() );
437  return false;
438  }
439  _json_iter->descend_to(depth()+1);
440 #if SIMDJSON_DEVELOPMENT_CHECKS
441  _json_iter->set_start_position(_depth, start_position());
442 #endif
443  return true;
444 }
445 
446 simdjson_warn_unused simdjson_inline error_code value_iterator::check_root_array() noexcept {
447  // When in streaming mode, we cannot expect peek_last() to be the last structural element of the
448  // current document. It only works in the normal mode where we have indexed a single document.
449  // Note that adding a check for 'streaming' is not expensive since we only have at most
450  // one root element.
451  if ( ! _json_iter->streaming() ) {
452  // The following lines do not fully protect against garbage content within the
453  // array: e.g., `[1, 2] foo]`. Users concerned with garbage content should
454  // also call `at_end()` on the document instance at the end of the processing to
455  // ensure that the processing has finished at the end.
456  //
457  if (*_json_iter->peek_last() != ']') {
458  _json_iter->abandon();
459  return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing ] at end");
460  }
461  // If the last character is ] *and* the first gibberish character is also ']'
462  // then on-demand could accidentally go over. So we need additional checks.
463  // https://github.com/simdjson/simdjson/issues/1834
464  // Checking that the document is balanced requires a full scan which is potentially
465  // expensive, but it only happens in edge cases where the first padding character is
466  // a closing bracket.
467  if ((*_json_iter->peek(_json_iter->end_position()) == ']') && (!_json_iter->balanced())) {
468  _json_iter->abandon();
469  // The exact error would require more work. It will typically be an unclosed array.
470  return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "the document is unbalanced");
471  }
472  }
473  return SUCCESS;
474 }
475 
476 simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::started_root_array() noexcept {
477  auto error = check_root_array();
478  if (error) { return error; }
479  return started_array();
480 }
481 
482 simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::has_next_element() noexcept {
483  assert_at_next();
484 
485  logger::log_event(*this, "has_next_element");
486  switch (*_json_iter->return_current_and_advance()) {
487  case ']':
488  logger::log_end_value(*_json_iter, "array");
489  SIMDJSON_TRY( end_container() );
490  return false;
491  case ',':
492  _json_iter->descend_to(depth()+1);
493  return true;
494  default:
495  return report_error(TAPE_ERROR, "Missing comma between array elements");
496  }
497 }
498 
499 simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::parse_bool(const uint8_t *json) const noexcept {
500  auto not_true = atomparsing::str4ncmp(json, "true");
501  auto not_false = atomparsing::str4ncmp(json, "fals") | (json[4] ^ 'e');
502  bool error = (not_true && not_false) || jsoncharutils::is_not_structural_or_whitespace(json[not_true ? 5 : 4]);
503  if (error) { return incorrect_type_error("Not a boolean"); }
504  return simdjson_result<bool>(!not_true);
505 }
506 simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::parse_null(const uint8_t *json) const noexcept {
507  bool is_null_string = !atomparsing::str4ncmp(json, "null") && jsoncharutils::is_structural_or_whitespace(json[4]);
508  // if we start with 'n', we must be a null
509  if(!is_null_string && json[0]=='n') { return incorrect_type_error("Not a null but starts with n"); }
510  return is_null_string;
511 }
512 
513 simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> value_iterator::get_string(bool allow_replacement) noexcept {
514  return get_raw_json_string().unescape(json_iter(), allow_replacement);
515 }
516 template <typename string_type>
517 simdjson_warn_unused simdjson_inline error_code value_iterator::get_string(string_type& receiver, bool allow_replacement) noexcept {
518  std::string_view content;
519  auto err = get_string(allow_replacement).get(content);
520  if (err) { return err; }
521  receiver = content;
522  return SUCCESS;
523 }
524 simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> value_iterator::get_wobbly_string() noexcept {
525  return get_raw_json_string().unescape_wobbly(json_iter());
526 }
527 simdjson_warn_unused simdjson_inline simdjson_result<raw_json_string> value_iterator::get_raw_json_string() noexcept {
528  auto json = peek_scalar("string");
529  if (*json != '"') { return incorrect_type_error("Not a string"); }
530  advance_scalar("string");
531  return raw_json_string(json+1);
532 }
533 simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> value_iterator::get_uint64() noexcept {
534  auto result = numberparsing::parse_unsigned(peek_non_root_scalar("uint64"));
535  if(result.error() == SUCCESS) { advance_non_root_scalar("uint64"); }
536  return result;
537 }
538 simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> value_iterator::get_uint64_in_string() noexcept {
539  auto result = numberparsing::parse_unsigned_in_string(peek_non_root_scalar("uint64"));
540  if(result.error() == SUCCESS) { advance_non_root_scalar("uint64"); }
541  return result;
542 }
543 simdjson_warn_unused simdjson_inline simdjson_result<int64_t> value_iterator::get_int64() noexcept {
544  auto result = numberparsing::parse_integer(peek_non_root_scalar("int64"));
545  if(result.error() == SUCCESS) { advance_non_root_scalar("int64"); }
546  return result;
547 }
548 simdjson_warn_unused simdjson_inline simdjson_result<int64_t> value_iterator::get_int64_in_string() noexcept {
549  auto result = numberparsing::parse_integer_in_string(peek_non_root_scalar("int64"));
550  if(result.error() == SUCCESS) { advance_non_root_scalar("int64"); }
551  return result;
552 }
553 simdjson_warn_unused simdjson_inline simdjson_result<double> value_iterator::get_double() noexcept {
554  auto result = numberparsing::parse_double(peek_non_root_scalar("double"));
555  if(result.error() == SUCCESS) { advance_non_root_scalar("double"); }
556  return result;
557 }
558 simdjson_warn_unused simdjson_inline simdjson_result<double> value_iterator::get_double_in_string() noexcept {
559  auto result = numberparsing::parse_double_in_string(peek_non_root_scalar("double"));
560  if(result.error() == SUCCESS) { advance_non_root_scalar("double"); }
561  return result;
562 }
563 simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::get_bool() noexcept {
564  auto result = parse_bool(peek_non_root_scalar("bool"));
565  if(result.error() == SUCCESS) { advance_non_root_scalar("bool"); }
566  return result;
567 }
568 simdjson_inline simdjson_result<bool> value_iterator::is_null() noexcept {
569  bool is_null_value;
570  SIMDJSON_TRY(parse_null(peek_non_root_scalar("null")).get(is_null_value));
571  if(is_null_value) { advance_non_root_scalar("null"); }
572  return is_null_value;
573 }
574 simdjson_inline bool value_iterator::is_negative() noexcept {
575  return numberparsing::is_negative(peek_non_root_scalar("numbersign"));
576 }
577 simdjson_inline bool value_iterator::is_root_negative() noexcept {
578  return numberparsing::is_negative(peek_root_scalar("numbersign"));
579 }
580 simdjson_inline simdjson_result<bool> value_iterator::is_integer() noexcept {
581  return numberparsing::is_integer(peek_non_root_scalar("integer"));
582 }
583 simdjson_inline simdjson_result<number_type> value_iterator::get_number_type() noexcept {
584  return numberparsing::get_number_type(peek_non_root_scalar("integer"));
585 }
586 simdjson_inline simdjson_result<number> value_iterator::get_number() noexcept {
587  number num;
588  error_code error = numberparsing::parse_number(peek_non_root_scalar("number"), num);
589  if(error) { return error; }
590  return num;
591 }
592 
593 simdjson_inline simdjson_result<bool> value_iterator::is_root_integer(bool check_trailing) noexcept {
594  auto max_len = peek_root_length();
595  auto json = peek_root_scalar("is_root_integer");
596  uint8_t tmpbuf[20+1+1]{}; // <20 digits> is the longest possible unsigned integer
597  tmpbuf[20+1] = '\0'; // make sure that buffer is always null terminated.
598  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 20+1)) {
599  return false; // if there are more than 20 characters, it cannot be represented as an integer.
600  }
601  auto answer = numberparsing::is_integer(tmpbuf);
602  // If the parsing was a success, we must still check that it is
603  // a single scalar. Note that we parse first because of cases like '[]' where
604  // getting TRAILING_CONTENT is wrong.
605  if(check_trailing && (answer.error() == SUCCESS) && (!_json_iter->is_single_token())) { return TRAILING_CONTENT; }
606  return answer;
607 }
608 
609 simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::number_type> value_iterator::get_root_number_type(bool check_trailing) noexcept {
610  auto max_len = peek_root_length();
611  auto json = peek_root_scalar("number");
612  // Per https://www.exploringbinary.com/maximum-number-of-decimal-digits-in-binary-floating-point-numbers/,
613  // 1074 is the maximum number of significant fractional digits. Add 8 more digits for the biggest
614  // number: -0.<fraction>e-308.
615  uint8_t tmpbuf[1074+8+1+1];
616  tmpbuf[1074+8+1] = '\0'; // make sure that buffer is always null terminated.
617  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 1074+8+1)) {
618  if(numberparsing::check_if_integer(json, max_len)) {
619  if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
620  logger::log_error(*_json_iter, start_position(), depth(), "Found big integer");
621  return number_type::big_integer;
622  }
623  logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 1082 characters and not a big integer");
624  return NUMBER_ERROR;
625  }
626  auto answer = numberparsing::get_number_type(tmpbuf);
627  if (check_trailing && (answer.error() == SUCCESS) && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
628  return answer;
629 }
630 simdjson_inline simdjson_result<number> value_iterator::get_root_number(bool check_trailing) noexcept {
631  auto max_len = peek_root_length();
632  auto json = peek_root_scalar("number");
633  // Per https://www.exploringbinary.com/maximum-number-of-decimal-digits-in-binary-floating-point-numbers/,
634  // 1074 is the maximum number of significant fractional digits. Add 8 more digits for the biggest
635  // number: -0.<fraction>e-308.
636  // NOTE: the current approach doesn't work for very big integer numbers containing more than 1074 digits.
637  uint8_t tmpbuf[1074+8+1+1];
638  tmpbuf[1074+8+1] = '\0'; // make sure that buffer is always null terminated.
639  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 1074+8+1)) {
640  if(numberparsing::check_if_integer(json, max_len)) {
641  if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
642  logger::log_error(*_json_iter, start_position(), depth(), "Found big integer");
643  return BIGINT_ERROR;
644  }
645  logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 1082 characters and not a big integer");
646  return NUMBER_ERROR;
647  }
648  number num;
649  error_code error = numberparsing::parse_number(tmpbuf, num);
650  if(error) { return error; }
651  if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
652  advance_root_scalar("number");
653  return num;
654 }
655 simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> value_iterator::get_root_string(bool check_trailing, bool allow_replacement) noexcept {
656  return get_root_raw_json_string(check_trailing).unescape(json_iter(), allow_replacement);
657 }
658 template <typename string_type>
659 simdjson_warn_unused simdjson_inline error_code value_iterator::get_root_string(string_type& receiver, bool check_trailing, bool allow_replacement) noexcept {
660  std::string_view content;
661  auto err = get_root_string(check_trailing, allow_replacement).get(content);
662  if (err) { return err; }
663  receiver = content;
664  return SUCCESS;
665 }
666 simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> value_iterator::get_root_wobbly_string(bool check_trailing) noexcept {
667  return get_root_raw_json_string(check_trailing).unescape_wobbly(json_iter());
668 }
669 simdjson_warn_unused simdjson_inline simdjson_result<raw_json_string> value_iterator::get_root_raw_json_string(bool check_trailing) noexcept {
670  auto json = peek_scalar("string");
671  if (*json != '"') { return incorrect_type_error("Not a string"); }
672  if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
673  advance_scalar("string");
674  return raw_json_string(json+1);
675 }
676 simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> value_iterator::get_root_uint64(bool check_trailing) noexcept {
677  auto max_len = peek_root_length();
678  auto json = peek_root_scalar("uint64");
679  uint8_t tmpbuf[20+1+1]{}; // <20 digits> is the longest possible unsigned integer
680  tmpbuf[20+1] = '\0'; // make sure that buffer is always null terminated.
681  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 20+1)) {
682  logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 20 characters");
683  return NUMBER_ERROR;
684  }
685  auto result = numberparsing::parse_unsigned(tmpbuf);
686  if(result.error() == SUCCESS) {
687  if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
688  advance_root_scalar("uint64");
689  }
690  return result;
691 }
692 simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> value_iterator::get_root_uint64_in_string(bool check_trailing) noexcept {
693  auto max_len = peek_root_length();
694  auto json = peek_root_scalar("uint64");
695  uint8_t tmpbuf[20+1+1]{}; // <20 digits> is the longest possible unsigned integer
696  tmpbuf[20+1] = '\0'; // make sure that buffer is always null terminated.
697  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 20+1)) {
698  logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 20 characters");
699  return NUMBER_ERROR;
700  }
701  auto result = numberparsing::parse_unsigned_in_string(tmpbuf);
702  if(result.error() == SUCCESS) {
703  if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
704  advance_root_scalar("uint64");
705  }
706  return result;
707 }
708 simdjson_warn_unused simdjson_inline simdjson_result<int64_t> value_iterator::get_root_int64(bool check_trailing) noexcept {
709  auto max_len = peek_root_length();
710  auto json = peek_root_scalar("int64");
711  uint8_t tmpbuf[20+1+1]; // -<19 digits> is the longest possible integer
712  tmpbuf[20+1] = '\0'; // make sure that buffer is always null terminated.
713  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 20+1)) {
714  logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 20 characters");
715  return NUMBER_ERROR;
716  }
717 
718  auto result = numberparsing::parse_integer(tmpbuf);
719  if(result.error() == SUCCESS) {
720  if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
721  advance_root_scalar("int64");
722  }
723  return result;
724 }
725 simdjson_warn_unused simdjson_inline simdjson_result<int64_t> value_iterator::get_root_int64_in_string(bool check_trailing) noexcept {
726  auto max_len = peek_root_length();
727  auto json = peek_root_scalar("int64");
728  uint8_t tmpbuf[20+1+1]; // -<19 digits> is the longest possible integer
729  tmpbuf[20+1] = '\0'; // make sure that buffer is always null terminated.
730  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 20+1)) {
731  logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 20 characters");
732  return NUMBER_ERROR;
733  }
734 
735  auto result = numberparsing::parse_integer_in_string(tmpbuf);
736  if(result.error() == SUCCESS) {
737  if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
738  advance_root_scalar("int64");
739  }
740  return result;
741 }
742 simdjson_warn_unused simdjson_inline simdjson_result<double> value_iterator::get_root_double(bool check_trailing) noexcept {
743  auto max_len = peek_root_length();
744  auto json = peek_root_scalar("double");
745  // Per https://www.exploringbinary.com/maximum-number-of-decimal-digits-in-binary-floating-point-numbers/,
746  // 1074 is the maximum number of significant fractional digits. Add 8 more digits for the biggest
747  // number: -0.<fraction>e-308.
748  uint8_t tmpbuf[1074+8+1+1]; // +1 for null termination.
749  tmpbuf[1074+8+1] = '\0'; // make sure that buffer is always null terminated.
750  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 1074+8+1)) {
751  logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 1082 characters");
752  return NUMBER_ERROR;
753  }
754  auto result = numberparsing::parse_double(tmpbuf);
755  if(result.error() == SUCCESS) {
756  if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
757  advance_root_scalar("double");
758  }
759  return result;
760 }
761 
762 simdjson_warn_unused simdjson_inline simdjson_result<double> value_iterator::get_root_double_in_string(bool check_trailing) noexcept {
763  auto max_len = peek_root_length();
764  auto json = peek_root_scalar("double");
765  // Per https://www.exploringbinary.com/maximum-number-of-decimal-digits-in-binary-floating-point-numbers/,
766  // 1074 is the maximum number of significant fractional digits. Add 8 more digits for the biggest
767  // number: -0.<fraction>e-308.
768  uint8_t tmpbuf[1074+8+1+1]; // +1 for null termination.
769  tmpbuf[1074+8+1] = '\0'; // make sure that buffer is always null terminated.
770  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 1074+8+1)) {
771  logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 1082 characters");
772  return NUMBER_ERROR;
773  }
774  auto result = numberparsing::parse_double_in_string(tmpbuf);
775  if(result.error() == SUCCESS) {
776  if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
777  advance_root_scalar("double");
778  }
779  return result;
780 }
781 simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::get_root_bool(bool check_trailing) noexcept {
782  auto max_len = peek_root_length();
783  auto json = peek_root_scalar("bool");
784  uint8_t tmpbuf[5+1+1]; // +1 for null termination
785  tmpbuf[5+1] = '\0'; // make sure that buffer is always null terminated.
786  if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 5+1)) { return incorrect_type_error("Not a boolean"); }
787  auto result = parse_bool(tmpbuf);
788  if(result.error() == SUCCESS) {
789  if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
790  advance_root_scalar("bool");
791  }
792  return result;
793 }
794 simdjson_inline simdjson_result<bool> value_iterator::is_root_null(bool check_trailing) noexcept {
795  auto max_len = peek_root_length();
796  auto json = peek_root_scalar("null");
797  bool result = (max_len >= 4 && !atomparsing::str4ncmp(json, "null") &&
798  (max_len == 4 || jsoncharutils::is_structural_or_whitespace(json[4])));
799  if(result) { // we have something that looks like a null.
800  if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
801  advance_root_scalar("null");
802  } else if (json[0] == 'n') {
803  return incorrect_type_error("Not a null but starts with n");
804  }
805  return result;
806 }
807 
808 simdjson_warn_unused simdjson_inline error_code value_iterator::skip_child() noexcept {
809  SIMDJSON_ASSUME( _json_iter->token._position > _start_position );
810  SIMDJSON_ASSUME( _json_iter->_depth >= _depth );
811 
812  return _json_iter->skip_child(depth());
813 }
814 
815 simdjson_inline value_iterator value_iterator::child() const noexcept {
816  assert_at_child();
817  return { _json_iter, depth()+1, _json_iter->token.position() };
818 }
819 
820 // GCC 7 warns when the first line of this function is inlined away into oblivion due to the caller
821 // relating depth and iterator depth, which is a desired effect. It does not happen if is_open is
822 // marked non-inline.
823 SIMDJSON_PUSH_DISABLE_WARNINGS
824 SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING
825 simdjson_inline bool value_iterator::is_open() const noexcept {
826  return _json_iter->depth() >= depth();
827 }
828 SIMDJSON_POP_DISABLE_WARNINGS
829 
830 simdjson_inline bool value_iterator::at_end() const noexcept {
831  return _json_iter->at_end();
832 }
833 
834 simdjson_inline bool value_iterator::at_start() const noexcept {
835  return _json_iter->token.position() == start_position();
836 }
837 
838 simdjson_inline bool value_iterator::at_first_field() const noexcept {
839  SIMDJSON_ASSUME( _json_iter->token._position > _start_position );
840  return _json_iter->token.position() == start_position() + 1;
841 }
842 
843 simdjson_inline void value_iterator::abandon() noexcept {
844  _json_iter->abandon();
845 }
846 
847 simdjson_warn_unused simdjson_inline depth_t value_iterator::depth() const noexcept {
848  return _depth;
849 }
850 simdjson_warn_unused simdjson_inline error_code value_iterator::error() const noexcept {
851  return _json_iter->error;
852 }
853 simdjson_warn_unused simdjson_inline uint8_t *&value_iterator::string_buf_loc() noexcept {
854  return _json_iter->string_buf_loc();
855 }
856 simdjson_warn_unused simdjson_inline const json_iterator &value_iterator::json_iter() const noexcept {
857  return *_json_iter;
858 }
859 simdjson_warn_unused simdjson_inline json_iterator &value_iterator::json_iter() noexcept {
860  return *_json_iter;
861 }
862 
863 simdjson_inline const uint8_t *value_iterator::peek_start() const noexcept {
864  return _json_iter->peek(start_position());
865 }
866 simdjson_inline uint32_t value_iterator::peek_start_length() const noexcept {
867  return _json_iter->peek_length(start_position());
868 }
869 simdjson_inline uint32_t value_iterator::peek_root_length() const noexcept {
870  return _json_iter->peek_root_length(start_position());
871 }
872 
873 simdjson_inline const uint8_t *value_iterator::peek_scalar(const char *type) noexcept {
874  logger::log_value(*_json_iter, start_position(), depth(), type);
875  // If we're not at the position anymore, we don't want to advance the cursor.
876  if (!is_at_start()) { return peek_start(); }
877 
878  // Get the JSON and advance the cursor, decreasing depth to signify that we have retrieved the value.
879  assert_at_start();
880  return _json_iter->peek();
881 }
882 
883 simdjson_inline void value_iterator::advance_scalar(const char *type) noexcept {
884  logger::log_value(*_json_iter, start_position(), depth(), type);
885  // If we're not at the position anymore, we don't want to advance the cursor.
886  if (!is_at_start()) { return; }
887 
888  // Get the JSON and advance the cursor, decreasing depth to signify that we have retrieved the value.
889  assert_at_start();
890  _json_iter->return_current_and_advance();
891  _json_iter->ascend_to(depth()-1);
892 }
893 
894 simdjson_inline error_code value_iterator::start_container(uint8_t start_char, const char *incorrect_type_message, const char *type) noexcept {
895  logger::log_start_value(*_json_iter, start_position(), depth(), type);
896  // If we're not at the position anymore, we don't want to advance the cursor.
897  const uint8_t *json;
898  if (!is_at_start()) {
899 #if SIMDJSON_DEVELOPMENT_CHECKS
900  if (!is_at_iterator_start()) { return OUT_OF_ORDER_ITERATION; }
901 #endif
902  json = peek_start();
903  if (*json != start_char) { return incorrect_type_error(incorrect_type_message); }
904  } else {
905  assert_at_start();
911  json = _json_iter->peek();
912  if (*json != start_char) { return incorrect_type_error(incorrect_type_message); }
913  _json_iter->return_current_and_advance();
914  }
915 
916 
917  return SUCCESS;
918 }
919 
920 
921 simdjson_inline const uint8_t *value_iterator::peek_root_scalar(const char *type) noexcept {
922  logger::log_value(*_json_iter, start_position(), depth(), type);
923  if (!is_at_start()) { return peek_start(); }
924 
925  assert_at_root();
926  return _json_iter->peek();
927 }
928 simdjson_inline const uint8_t *value_iterator::peek_non_root_scalar(const char *type) noexcept {
929  logger::log_value(*_json_iter, start_position(), depth(), type);
930  if (!is_at_start()) { return peek_start(); }
931 
932  assert_at_non_root_start();
933  return _json_iter->peek();
934 }
935 
936 simdjson_inline void value_iterator::advance_root_scalar(const char *type) noexcept {
937  logger::log_value(*_json_iter, start_position(), depth(), type);
938  if (!is_at_start()) { return; }
939 
940  assert_at_root();
941  _json_iter->return_current_and_advance();
942  _json_iter->ascend_to(depth()-1);
943 }
944 simdjson_inline void value_iterator::advance_non_root_scalar(const char *type) noexcept {
945  logger::log_value(*_json_iter, start_position(), depth(), type);
946  if (!is_at_start()) { return; }
947 
948  assert_at_non_root_start();
949  _json_iter->return_current_and_advance();
950  _json_iter->ascend_to(depth()-1);
951 }
952 
953 simdjson_inline error_code value_iterator::incorrect_type_error(const char *message) const noexcept {
954  logger::log_error(*_json_iter, start_position(), depth(), message);
955  return INCORRECT_TYPE;
956 }
957 
958 simdjson_inline bool value_iterator::is_at_start() const noexcept {
959  return position() == start_position();
960 }
961 
962 simdjson_inline bool value_iterator::is_at_key() const noexcept {
963  // Keys are at the same depth as the object.
964  // Note here that we could be safer and check that we are within an object,
965  // but we do not.
966  return _depth == _json_iter->_depth && *_json_iter->peek() == '"';
967 }
968 
969 simdjson_inline bool value_iterator::is_at_iterator_start() const noexcept {
970  // We can legitimately be either at the first value ([1]), or after the array if it's empty ([]).
971  auto delta = position() - start_position();
972  return delta == 1 || delta == 2;
973 }
974 
975 inline void value_iterator::assert_at_start() const noexcept {
976  SIMDJSON_ASSUME( _json_iter->token._position == _start_position );
977  SIMDJSON_ASSUME( _json_iter->_depth == _depth );
978  SIMDJSON_ASSUME( _depth > 0 );
979 }
980 
981 inline void value_iterator::assert_at_container_start() const noexcept {
982  SIMDJSON_ASSUME( _json_iter->token._position == _start_position + 1 );
983  SIMDJSON_ASSUME( _json_iter->_depth == _depth );
984  SIMDJSON_ASSUME( _depth > 0 );
985 }
986 
987 inline void value_iterator::assert_at_next() const noexcept {
988  SIMDJSON_ASSUME( _json_iter->token._position > _start_position );
989  SIMDJSON_ASSUME( _json_iter->_depth == _depth );
990  SIMDJSON_ASSUME( _depth > 0 );
991 }
992 
993 simdjson_inline void value_iterator::move_at_start() noexcept {
994  _json_iter->_depth = _depth;
995  _json_iter->token.set_position(_start_position);
996 }
997 
998 simdjson_inline void value_iterator::move_at_container_start() noexcept {
999  _json_iter->_depth = _depth;
1000  _json_iter->token.set_position(_start_position + 1);
1001 }
1002 
1003 simdjson_inline simdjson_result<bool> value_iterator::reset_array() noexcept {
1004  if(error()) { return error(); }
1005  move_at_container_start();
1006  return started_array();
1007 }
1008 
1009 simdjson_inline simdjson_result<bool> value_iterator::reset_object() noexcept {
1010  if(error()) { return error(); }
1011  move_at_container_start();
1012  return started_object();
1013 }
1014 
1015 inline void value_iterator::assert_at_child() const noexcept {
1016  SIMDJSON_ASSUME( _json_iter->token._position > _start_position );
1017  SIMDJSON_ASSUME( _json_iter->_depth == _depth + 1 );
1018  SIMDJSON_ASSUME( _depth > 0 );
1019 }
1020 
1021 inline void value_iterator::assert_at_root() const noexcept {
1022  assert_at_start();
1023  SIMDJSON_ASSUME( _depth == 1 );
1024 }
1025 
1026 inline void value_iterator::assert_at_non_root_start() const noexcept {
1027  assert_at_start();
1028  SIMDJSON_ASSUME( _depth > 1 );
1029 }
1030 
1031 inline void value_iterator::assert_is_valid() const noexcept {
1032  SIMDJSON_ASSUME( _json_iter != nullptr );
1033 }
1034 
1035 simdjson_inline bool value_iterator::is_valid() const noexcept {
1036  return _json_iter != nullptr;
1037 }
1038 
1039 simdjson_inline simdjson_result<json_type> value_iterator::type() const noexcept {
1040  switch (*peek_start()) {
1041  case '{':
1042  return json_type::object;
1043  case '[':
1044  return json_type::array;
1045  case '"':
1046  return json_type::string;
1047  case 'n':
1048  return json_type::null;
1049  case 't': case 'f':
1050  return json_type::boolean;
1051  case '-':
1052  case '0': case '1': case '2': case '3': case '4':
1053  case '5': case '6': case '7': case '8': case '9':
1054  return json_type::number;
1055  default:
1056  return TAPE_ERROR;
1057  }
1058 }
1059 
1060 simdjson_inline token_position value_iterator::start_position() const noexcept {
1061  return _start_position;
1062 }
1063 
1064 simdjson_inline token_position value_iterator::position() const noexcept {
1065  return _json_iter->position();
1066 }
1067 
1068 simdjson_inline token_position value_iterator::end_position() const noexcept {
1069  return _json_iter->end_position();
1070 }
1071 
1072 simdjson_inline token_position value_iterator::last_position() const noexcept {
1073  return _json_iter->last_position();
1074 }
1075 
1076 simdjson_inline error_code value_iterator::report_error(error_code error, const char *message) noexcept {
1077  return _json_iter->report_error(error, message);
1078 }
1079 
1080 } // namespace ondemand
1081 } // namespace SIMDJSON_IMPLEMENTATION
1082 } // namespace simdjson
1083 
1084 namespace simdjson {
1085 
1086 simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value_iterator>::simdjson_result(SIMDJSON_IMPLEMENTATION::ondemand::value_iterator &&value) noexcept
1087  : implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::value_iterator>(std::forward<SIMDJSON_IMPLEMENTATION::ondemand::value_iterator>(value)) {}
1088 simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value_iterator>::simdjson_result(error_code error) noexcept
1089  : implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::value_iterator>(error) {}
1090 
1091 } // namespace simdjson
1092 
1093 #endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H
A string escaped per JSON rules, terminated with quote (").
simdjson_inline bool unsafe_is_equal(size_t length, std::string_view target) const noexcept
This compares the current instance to the std::string_view target: returns true if they are byte-by-b...
@ object
A JSON object ( { "a": 1, "b" 2, ... } )
@ number
A JSON number ( 1 or -2.3 or 4.5e6 ...)
@ string
A JSON string ( "a" or "hello world\n" ...)
int32_t depth_t
Represents the depth of a JSON value (number of nested arrays/objects).
Definition: base.h:18
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:37
@ OUT_OF_ORDER_ITERATION
tried to iterate an array or object out of order (checked when SIMDJSON_DEVELOPMENT_CHECKS=1)
Definition: error.h:46
@ TAPE_ERROR
Something went wrong, this is a generic error.
Definition: error.h:23
@ SUCCESS
No error.
Definition: error.h:20
@ TRAILING_CONTENT
Unexpected trailing content in the JSON input.
Definition: error.h:51
@ INCOMPLETE_ARRAY_OR_OBJECT
The document ends early.
Definition: error.h:48
@ NUMBER_ERROR
Problem while parsing a number.
Definition: error.h:29
@ BIGINT_ERROR
The integer value exceeds 64 bits.
Definition: error.h:30
The result of a simdjson operation that could fail.
Definition: error.h:215