simdjson  3.1.6
Ridiculously Fast JSON
object_iterator-inl.h
1 namespace simdjson {
2 namespace SIMDJSON_IMPLEMENTATION {
3 namespace ondemand {
4 
5 //
6 // object_iterator
7 //
8 
9 simdjson_inline object_iterator::object_iterator(const value_iterator &_iter) noexcept
10  : iter{_iter}
11 {}
12 
13 simdjson_inline simdjson_result<field> object_iterator::operator*() noexcept {
14  error_code error = iter.error();
15  if (error) { iter.abandon(); return error; }
16  auto result = field::start(iter);
17  // TODO this is a safety rail ... users should exit loops as soon as they receive an error.
18  // Nonetheless, let's see if performance is OK with this if statement--the compiler may give it to us for free.
19  if (result.error()) { iter.abandon(); }
20  return result;
21 }
22 simdjson_inline bool object_iterator::operator==(const object_iterator &other) const noexcept {
23  return !(*this != other);
24 }
25 simdjson_inline bool object_iterator::operator!=(const object_iterator &) const noexcept {
26  return iter.is_open();
27 }
28 
29 SIMDJSON_PUSH_DISABLE_WARNINGS
30 SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING
31 simdjson_inline object_iterator &object_iterator::operator++() noexcept {
32  // TODO this is a safety rail ... users should exit loops as soon as they receive an error.
33  // Nonetheless, let's see if performance is OK with this if statement--the compiler may give it to us for free.
34  if (!iter.is_open()) { return *this; } // Iterator will be released if there is an error
35 
36  simdjson_unused error_code error;
37  if ((error = iter.skip_child() )) { return *this; }
38 
39  simdjson_unused bool has_value;
40  if ((error = iter.has_next_field().get(has_value) )) { return *this; };
41  return *this;
42 }
43 SIMDJSON_POP_DISABLE_WARNINGS
44 
45 //
46 // ### Live States
47 //
48 // While iterating or looking up values, depth >= iter.depth. at_start may vary. Error is
49 // always SUCCESS:
50 //
51 // - Start: This is the state when the object is first found and the iterator is just past the {.
52 // In this state, at_start == true.
53 // - Next: After we hand a scalar value to the user, or an array/object which they then fully
54 // iterate over, the iterator is at the , or } before the next value. In this state,
55 // depth == iter.depth, at_start == false, and error == SUCCESS.
56 // - Unfinished Business: When we hand an array/object to the user which they do not fully
57 // iterate over, we need to finish that iteration by skipping child values until we reach the
58 // Next state. In this state, depth > iter.depth, at_start == false, and error == SUCCESS.
59 //
60 // ## Error States
61 //
62 // In error states, we will yield exactly one more value before stopping. iter.depth == depth
63 // and at_start is always false. We decrement after yielding the error, moving to the Finished
64 // state.
65 //
66 // - Chained Error: When the object iterator is part of an error chain--for example, in
67 // `for (auto tweet : doc["tweets"])`, where the tweet field may be missing or not be an
68 // object--we yield that error in the loop, exactly once. In this state, error != SUCCESS and
69 // iter.depth == depth, and at_start == false. We decrement depth when we yield the error.
70 // - Missing Comma Error: When the iterator ++ method discovers there is no comma between fields,
71 // we flag that as an error and treat it exactly the same as a Chained Error. In this state,
72 // error == TAPE_ERROR, iter.depth == depth, and at_start == false.
73 //
74 // Errors that occur while reading a field to give to the user (such as when the key is not a
75 // string or the field is missing a colon) are yielded immediately. Depth is then decremented,
76 // moving to the Finished state without transitioning through an Error state at all.
77 //
78 // ## Terminal State
79 //
80 // The terminal state has iter.depth < depth. at_start is always false.
81 //
82 // - Finished: When we have reached a }, we are finished. We signal this by decrementing depth.
83 // In this state, iter.depth < depth, at_start == false, and error == SUCCESS.
84 //
85 
86 } // namespace ondemand
87 } // namespace SIMDJSON_IMPLEMENTATION
88 } // namespace simdjson
89 
90 namespace simdjson {
91 
92 simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object_iterator>::simdjson_result(
93  SIMDJSON_IMPLEMENTATION::ondemand::object_iterator &&value
94 ) noexcept
95  : implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::object_iterator>(std::forward<SIMDJSON_IMPLEMENTATION::ondemand::object_iterator>(value))
96 {
97  first.iter.assert_is_valid();
98 }
99 simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object_iterator>::simdjson_result(error_code error) noexcept
100  : implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::object_iterator>({}, error)
101 {
102 }
103 
104 simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::field> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object_iterator>::operator*() noexcept {
105  if (error()) { return error(); }
106  return *first;
107 }
108 // If we're iterating and there is an error, return the error once.
109 simdjson_inline bool simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object_iterator>::operator==(const simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object_iterator> &other) const noexcept {
110  if (!first.iter.is_valid()) { return !error(); }
111  return first == other.first;
112 }
113 // If we're iterating and there is an error, return the error once.
114 simdjson_inline bool simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object_iterator>::operator!=(const simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object_iterator> &other) const noexcept {
115  if (!first.iter.is_valid()) { return error(); }
116  return first != other.first;
117 }
118 // Checks for ']' and ','
119 simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object_iterator> &simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object_iterator>::operator++() noexcept {
120  // Clear the error if there is one, so we don't yield it twice
121  if (error()) { second = SUCCESS; return *this; }
122  ++first;
123  return *this;
124 }
125 
126 } // namespace simdjson
simdjson_inline object_iterator() noexcept=default
Create a new invalid object_iterator.
We want to support argument-dependent lookup (ADL).
error_code
All possible errors returned by simdjson.
Definition: error.h:17
@ SUCCESS
No error.
Definition: error.h:18
simdjson_inline error_code error() const noexcept
The error.
Definition: error-inl.h:132