1 | namespace simdjson { |
2 | namespace SIMDJSON_IMPLEMENTATION { |
3 | namespace ondemand { |
4 | |
5 | simdjson_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 | } |
11 | simdjson_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 | } |
17 | simdjson_inline simdjson_result<value> object::operator[](const std::string_view key) & noexcept { |
18 | return find_field_unordered(key); |
19 | } |
20 | simdjson_inline simdjson_result<value> object::operator[](const std::string_view key) && noexcept { |
21 | return std::forward<object>(t&: *this).find_field_unordered(key); |
22 | } |
23 | simdjson_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 | } |
29 | simdjson_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 | |
36 | simdjson_inline simdjson_result<object> object::start(value_iterator &iter) noexcept { |
37 | SIMDJSON_TRY( iter.start_object().error() ); |
38 | return object(iter); |
39 | } |
40 | simdjson_inline simdjson_result<object> object::start_root(value_iterator &iter) noexcept { |
41 | SIMDJSON_TRY( iter.start_root_object().error() ); |
42 | return object(iter); |
43 | } |
44 | simdjson_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 | |
70 | simdjson_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 | |
78 | simdjson_inline simdjson_result<object> object::started(value_iterator &iter) noexcept { |
79 | SIMDJSON_TRY( iter.started_object().error() ); |
80 | return object(iter); |
81 | } |
82 | |
83 | simdjson_inline object object::resume(const value_iterator &iter) noexcept { |
84 | return iter; |
85 | } |
86 | |
87 | simdjson_inline object::object(const value_iterator &_iter) noexcept |
88 | : iter{_iter} |
89 | { |
90 | } |
91 | |
92 | simdjson_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 | } |
98 | simdjson_inline simdjson_result<object_iterator> object::end() noexcept { |
99 | return object_iterator(iter); |
100 | } |
101 | |
102 | inline 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 | |
142 | simdjson_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 | |
154 | simdjson_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 | |
161 | simdjson_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 | |
169 | namespace simdjson { |
170 | |
171 | simdjson_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)) {} |
173 | simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object>::simdjson_result(error_code error) noexcept |
174 | : implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::object>(error) {} |
175 | |
176 | simdjson_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 | } |
180 | simdjson_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 | } |
184 | simdjson_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 | } |
188 | simdjson_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 | } |
192 | simdjson_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 | } |
196 | simdjson_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 | } |
200 | simdjson_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 | } |
204 | simdjson_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 | |
209 | simdjson_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 | |
214 | inline simdjson_result<bool> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object>::reset() noexcept { |
215 | if (error()) { return error(); } |
216 | return first.reset(); |
217 | } |
218 | |
219 | inline simdjson_result<bool> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object>::is_empty() noexcept { |
220 | if (error()) { return error(); } |
221 | return first.is_empty(); |
222 | } |
223 | |
224 | simdjson_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 | |