1namespace simdjson {
2namespace SIMDJSON_IMPLEMENTATION {
3namespace ondemand {
4
5simdjson_inline simdjson_result<value> object::find_field_unordered(const std::string_view key) & noexcept {
6 bool has_value;
7 SIMDJSON_TRY( iter.find_field_unordered_raw(key).get(has_value) );
8 if (!has_value) { return NO_SUCH_FIELD; }
9 return value(iter.child());
10}
11simdjson_inline simdjson_result<value> object::find_field_unordered(const std::string_view key) && noexcept {
12 bool has_value;
13 SIMDJSON_TRY( iter.find_field_unordered_raw(key).get(has_value) );
14 if (!has_value) { return NO_SUCH_FIELD; }
15 return value(iter.child());
16}
17simdjson_inline simdjson_result<value> object::operator[](const std::string_view key) & noexcept {
18 return find_field_unordered(key);
19}
20simdjson_inline simdjson_result<value> object::operator[](const std::string_view key) && noexcept {
21 return std::forward<object>(t&: *this).find_field_unordered(key);
22}
23simdjson_inline simdjson_result<value> object::find_field(const std::string_view key) & noexcept {
24 bool has_value;
25 SIMDJSON_TRY( iter.find_field_raw(key).get(has_value) );
26 if (!has_value) { return NO_SUCH_FIELD; }
27 return value(iter.child());
28}
29simdjson_inline simdjson_result<value> object::find_field(const std::string_view key) && noexcept {
30 bool has_value;
31 SIMDJSON_TRY( iter.find_field_raw(key).get(has_value) );
32 if (!has_value) { return NO_SUCH_FIELD; }
33 return value(iter.child());
34}
35
36simdjson_inline simdjson_result<object> object::start(value_iterator &iter) noexcept {
37 SIMDJSON_TRY( iter.start_object().error() );
38 return object(iter);
39}
40simdjson_inline simdjson_result<object> object::start_root(value_iterator &iter) noexcept {
41 SIMDJSON_TRY( iter.start_root_object().error() );
42 return object(iter);
43}
44simdjson_inline error_code object::consume() noexcept {
45 if(iter.is_at_key()) {
46 /**
47 * whenever you are pointing at a key, calling skip_child() is
48 * unsafe because you will hit a string and you will assume that
49 * it is string value, and this mistake will lead you to make bad
50 * depth computation.
51 */
52 /**
53 * We want to 'consume' the key. We could really
54 * just do _json_iter->return_current_and_advance(); at this
55 * point, but, for clarity, we will use the high-level API to
56 * eat the key. We assume that the compiler optimizes away
57 * most of the work.
58 */
59 simdjson_unused raw_json_string actual_key;
60 auto error = iter.field_key().get(value&: actual_key);
61 if (error) { iter.abandon(); return error; };
62 // Let us move to the value while we are at it.
63 if ((error = iter.field_value())) { iter.abandon(); return error; }
64 }
65 auto error_skip = iter.json_iter().skip_child(parent_depth: iter.depth()-1);
66 if(error_skip) { iter.abandon(); }
67 return error_skip;
68}
69
70simdjson_inline simdjson_result<std::string_view> object::raw_json() noexcept {
71 const uint8_t * starting_point{iter.peek_start()};
72 auto error = consume();
73 if(error) { return error; }
74 const uint8_t * final_point{iter._json_iter->peek(delta: 0)};
75 return std::string_view(reinterpret_cast<const char*>(starting_point), size_t(final_point - starting_point));
76}
77
78simdjson_inline simdjson_result<object> object::started(value_iterator &iter) noexcept {
79 SIMDJSON_TRY( iter.started_object().error() );
80 return object(iter);
81}
82
83simdjson_inline object object::resume(const value_iterator &iter) noexcept {
84 return iter;
85}
86
87simdjson_inline object::object(const value_iterator &_iter) noexcept
88 : iter{_iter}
89{
90}
91
92simdjson_inline simdjson_result<object_iterator> object::begin() noexcept {
93#if SIMDJSON_DEVELOPMENT_CHECKS
94 if (!iter.is_at_iterator_start()) { return OUT_OF_ORDER_ITERATION; }
95#endif
96 return object_iterator(iter);
97}
98simdjson_inline simdjson_result<object_iterator> object::end() noexcept {
99 return object_iterator(iter);
100}
101
102inline simdjson_result<value> object::at_pointer(std::string_view json_pointer) noexcept {
103 if (json_pointer[0] != '/') { return INVALID_JSON_POINTER; }
104 json_pointer = json_pointer.substr(pos: 1);
105 size_t slash = json_pointer.find(c: '/');
106 std::string_view key = json_pointer.substr(pos: 0, n: slash);
107 // Grab the child with the given key
108 simdjson_result<value> child;
109
110 // If there is an escape character in the key, unescape it and then get the child.
111 size_t escape = key.find(c: '~');
112 if (escape != std::string_view::npos) {
113 // Unescape the key
114 std::string unescaped(key);
115 do {
116 switch (unescaped[escape+1]) {
117 case '0':
118 unescaped.replace(pos: escape, n1: 2, s: "~");
119 break;
120 case '1':
121 unescaped.replace(pos: escape, n1: 2, s: "/");
122 break;
123 default:
124 return INVALID_JSON_POINTER; // "Unexpected ~ escape character in JSON pointer");
125 }
126 escape = unescaped.find(c: '~', pos: escape+1);
127 } while (escape != std::string::npos);
128 child = find_field(key: unescaped); // Take note find_field does not unescape keys when matching
129 } else {
130 child = find_field(key);
131 }
132 if(child.error()) {
133 return child; // we do not continue if there was an error
134 }
135 // If there is a /, we have to recurse and look up more of the path
136 if (slash != std::string_view::npos) {
137 child = child.at_pointer(json_pointer: json_pointer.substr(pos: slash));
138 }
139 return child;
140}
141
142simdjson_inline simdjson_result<size_t> object::count_fields() & noexcept {
143 size_t count{0};
144 // Important: we do not consume any of the values.
145 for(simdjson_unused auto v : *this) { count++; }
146 // The above loop will always succeed, but we want to report errors.
147 if(iter.error()) { return iter.error(); }
148 // We need to move back at the start because we expect users to iterate through
149 // the object after counting the number of elements.
150 iter.reset_object();
151 return count;
152}
153
154simdjson_inline simdjson_result<bool> object::is_empty() & noexcept {
155 bool is_not_empty;
156 auto error = iter.reset_object().get(value&: is_not_empty);
157 if(error) { return error; }
158 return !is_not_empty;
159}
160
161simdjson_inline simdjson_result<bool> object::reset() & noexcept {
162 return iter.reset_object();
163}
164
165} // namespace ondemand
166} // namespace SIMDJSON_IMPLEMENTATION
167} // namespace simdjson
168
169namespace simdjson {
170
171simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object>::simdjson_result(SIMDJSON_IMPLEMENTATION::ondemand::object &&value) noexcept
172 : implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::object>(std::forward<SIMDJSON_IMPLEMENTATION::ondemand::object>(t&: value)) {}
173simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object>::simdjson_result(error_code error) noexcept
174 : implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::object>(error) {}
175
176simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object_iterator> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object>::begin() noexcept {
177 if (error()) { return error(); }
178 return first.begin();
179}
180simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object_iterator> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object>::end() noexcept {
181 if (error()) { return error(); }
182 return first.end();
183}
184simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object>::find_field_unordered(std::string_view key) & noexcept {
185 if (error()) { return error(); }
186 return first.find_field_unordered(key);
187}
188simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object>::find_field_unordered(std::string_view key) && noexcept {
189 if (error()) { return error(); }
190 return std::forward<SIMDJSON_IMPLEMENTATION::ondemand::object>(t&: first).find_field_unordered(key);
191}
192simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object>::operator[](std::string_view key) & noexcept {
193 if (error()) { return error(); }
194 return first[key];
195}
196simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object>::operator[](std::string_view key) && noexcept {
197 if (error()) { return error(); }
198 return std::forward<SIMDJSON_IMPLEMENTATION::ondemand::object>(t&: first)[key];
199}
200simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object>::find_field(std::string_view key) & noexcept {
201 if (error()) { return error(); }
202 return first.find_field(key);
203}
204simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object>::find_field(std::string_view key) && noexcept {
205 if (error()) { return error(); }
206 return std::forward<SIMDJSON_IMPLEMENTATION::ondemand::object>(t&: first).find_field(key);
207}
208
209simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object>::at_pointer(std::string_view json_pointer) noexcept {
210 if (error()) { return error(); }
211 return first.at_pointer(json_pointer);
212}
213
214inline simdjson_result<bool> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object>::reset() noexcept {
215 if (error()) { return error(); }
216 return first.reset();
217}
218
219inline simdjson_result<bool> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object>::is_empty() noexcept {
220 if (error()) { return error(); }
221 return first.is_empty();
222}
223
224simdjson_inline simdjson_result<size_t> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object>::count_fields() & noexcept {
225 if (error()) { return error(); }
226 return first.count_fields();
227}
228
229} // namespace simdjson
230