1 | #include "simdjson/error.h" |
2 | |
3 | namespace simdjson { |
4 | namespace SIMDJSON_IMPLEMENTATION { |
5 | namespace ondemand { |
6 | |
7 | class parser; |
8 | class array; |
9 | class object; |
10 | class value; |
11 | class raw_json_string; |
12 | class array_iterator; |
13 | class document_stream; |
14 | |
15 | /** |
16 | * A JSON document. It holds a json_iterator instance. |
17 | * |
18 | * Used by tokens to get text, and string buffer location. |
19 | * |
20 | * You must keep the document around during iteration. |
21 | */ |
22 | class document { |
23 | public: |
24 | /** |
25 | * Create a new invalid document. |
26 | * |
27 | * Exists so you can declare a variable and later assign to it before use. |
28 | */ |
29 | simdjson_inline document() noexcept = default; |
30 | simdjson_inline document(const document &other) noexcept = delete; // pass your documents by reference, not by copy |
31 | simdjson_inline document(document &&other) noexcept = default; |
32 | simdjson_inline document &operator=(const document &other) noexcept = delete; |
33 | simdjson_inline document &operator=(document &&other) noexcept = default; |
34 | |
35 | /** |
36 | * Cast this JSON value to an array. |
37 | * |
38 | * @returns An object that can be used to iterate the array. |
39 | * @returns INCORRECT_TYPE If the JSON value is not an array. |
40 | */ |
41 | simdjson_inline simdjson_result<array> get_array() & noexcept; |
42 | /** |
43 | * Cast this JSON value to an object. |
44 | * |
45 | * @returns An object that can be used to look up or iterate fields. |
46 | * @returns INCORRECT_TYPE If the JSON value is not an object. |
47 | */ |
48 | simdjson_inline simdjson_result<object> get_object() & noexcept; |
49 | /** |
50 | * Cast this JSON value to an unsigned integer. |
51 | * |
52 | * @returns A signed 64-bit integer. |
53 | * @returns INCORRECT_TYPE If the JSON value is not a 64-bit unsigned integer. |
54 | */ |
55 | simdjson_inline simdjson_result<uint64_t> get_uint64() noexcept; |
56 | /** |
57 | * Cast this JSON value (inside string) to an unsigned integer. |
58 | * |
59 | * @returns A signed 64-bit integer. |
60 | * @returns INCORRECT_TYPE If the JSON value is not a 64-bit unsigned integer. |
61 | */ |
62 | simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept; |
63 | /** |
64 | * Cast this JSON value to a signed integer. |
65 | * |
66 | * @returns A signed 64-bit integer. |
67 | * @returns INCORRECT_TYPE If the JSON value is not a 64-bit integer. |
68 | */ |
69 | simdjson_inline simdjson_result<int64_t> get_int64() noexcept; |
70 | /** |
71 | * Cast this JSON value (inside string) to a signed integer. |
72 | * |
73 | * @returns A signed 64-bit integer. |
74 | * @returns INCORRECT_TYPE If the JSON value is not a 64-bit integer. |
75 | */ |
76 | simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept; |
77 | /** |
78 | * Cast this JSON value to a double. |
79 | * |
80 | * @returns A double. |
81 | * @returns INCORRECT_TYPE If the JSON value is not a valid floating-point number. |
82 | */ |
83 | simdjson_inline simdjson_result<double> get_double() noexcept; |
84 | |
85 | /** |
86 | * Cast this JSON value (inside string) to a double. |
87 | * |
88 | * @returns A double. |
89 | * @returns INCORRECT_TYPE If the JSON value is not a valid floating-point number. |
90 | */ |
91 | simdjson_inline simdjson_result<double> get_double_in_string() noexcept; |
92 | /** |
93 | * Cast this JSON value to a string. |
94 | * |
95 | * The string is guaranteed to be valid UTF-8. |
96 | * |
97 | * Important: Calling get_string() twice on the same document is an error. |
98 | * |
99 | * @param Whether to allow a replacement character for unmatched surrogate pairs. |
100 | * @returns An UTF-8 string. The string is stored in the parser and will be invalidated the next |
101 | * time it parses a document or when it is destroyed. |
102 | * @returns INCORRECT_TYPE if the JSON value is not a string. |
103 | */ |
104 | simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement = false) noexcept; |
105 | /** |
106 | * Cast this JSON value to a string. |
107 | * |
108 | * The string is not guaranteed to be valid UTF-8. See https://simonsapin.github.io/wtf-8/ |
109 | * |
110 | * Important: Calling get_wobbly_string() twice on the same document is an error. |
111 | * |
112 | * @returns An UTF-8 string. The string is stored in the parser and will be invalidated the next |
113 | * time it parses a document or when it is destroyed. |
114 | * @returns INCORRECT_TYPE if the JSON value is not a string. |
115 | */ |
116 | simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept; |
117 | /** |
118 | * Cast this JSON value to a raw_json_string. |
119 | * |
120 | * The string is guaranteed to be valid UTF-8, and may have escapes in it (e.g. \\ or \n). |
121 | * |
122 | * @returns A pointer to the raw JSON for the given string. |
123 | * @returns INCORRECT_TYPE if the JSON value is not a string. |
124 | */ |
125 | simdjson_inline simdjson_result<raw_json_string> get_raw_json_string() noexcept; |
126 | /** |
127 | * Cast this JSON value to a bool. |
128 | * |
129 | * @returns A bool value. |
130 | * @returns INCORRECT_TYPE if the JSON value is not true or false. |
131 | */ |
132 | simdjson_inline simdjson_result<bool> get_bool() noexcept; |
133 | /** |
134 | * Cast this JSON value to a value when the document is an object or an array. |
135 | * |
136 | * @returns A value if a JSON array or object cannot be found. |
137 | * @returns SCALAR_DOCUMENT_AS_VALUE error is the document is a scalar (see is_scalar() function). |
138 | */ |
139 | simdjson_inline simdjson_result<value> get_value() noexcept; |
140 | |
141 | /** |
142 | * Checks if this JSON value is null. If and only if the value is |
143 | * null, then it is consumed (we advance). If we find a token that |
144 | * begins with 'n' but is not 'null', then an error is returned. |
145 | * |
146 | * @returns Whether the value is null. |
147 | * @returns INCORRECT_TYPE If the JSON value begins with 'n' and is not 'null'. |
148 | */ |
149 | simdjson_inline simdjson_result<bool> is_null() noexcept; |
150 | |
151 | /** |
152 | * Get this value as the given type. |
153 | * |
154 | * Supported types: object, array, raw_json_string, string_view, uint64_t, int64_t, double, bool |
155 | * |
156 | * You may use get_double(), get_bool(), get_uint64(), get_int64(), |
157 | * get_object(), get_array(), get_raw_json_string(), or get_string() instead. |
158 | * |
159 | * @returns A value of the given type, parsed from the JSON. |
160 | * @returns INCORRECT_TYPE If the JSON value is not the given type. |
161 | */ |
162 | template<typename T> simdjson_inline simdjson_result<T> get() & noexcept { |
163 | // Unless the simdjson library provides an inline implementation, calling this method should |
164 | // immediately fail. |
165 | static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library." ); |
166 | } |
167 | /** @overload template<typename T> simdjson_result<T> get() & noexcept */ |
168 | template<typename T> simdjson_inline simdjson_result<T> get() && noexcept { |
169 | // Unless the simdjson library provides an inline implementation, calling this method should |
170 | // immediately fail. |
171 | static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library." ); |
172 | } |
173 | |
174 | /** |
175 | * Get this value as the given type. |
176 | * |
177 | * Supported types: object, array, raw_json_string, string_view, uint64_t, int64_t, double, bool, value |
178 | * |
179 | * Be mindful that the document instance must remain in scope while you are accessing object, array and value instances. |
180 | * |
181 | * @param out This is set to a value of the given type, parsed from the JSON. If there is an error, this may not be initialized. |
182 | * @returns INCORRECT_TYPE If the JSON value is not an object. |
183 | * @returns SUCCESS If the parse succeeded and the out parameter was set to the value. |
184 | */ |
185 | template<typename T> simdjson_inline error_code get(T &out) & noexcept; |
186 | /** @overload template<typename T> error_code get(T &out) & noexcept */ |
187 | template<typename T> simdjson_inline error_code get(T &out) && noexcept; |
188 | |
189 | #if SIMDJSON_EXCEPTIONS |
190 | /** |
191 | * Cast this JSON value to an array. |
192 | * |
193 | * @returns An object that can be used to iterate the array. |
194 | * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not an array. |
195 | */ |
196 | simdjson_inline operator array() & noexcept(false); |
197 | /** |
198 | * Cast this JSON value to an object. |
199 | * |
200 | * @returns An object that can be used to look up or iterate fields. |
201 | * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not an object. |
202 | */ |
203 | simdjson_inline operator object() & noexcept(false); |
204 | /** |
205 | * Cast this JSON value to an unsigned integer. |
206 | * |
207 | * @returns A signed 64-bit integer. |
208 | * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not a 64-bit unsigned integer. |
209 | */ |
210 | simdjson_inline operator uint64_t() noexcept(false); |
211 | /** |
212 | * Cast this JSON value to a signed integer. |
213 | * |
214 | * @returns A signed 64-bit integer. |
215 | * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not a 64-bit integer. |
216 | */ |
217 | simdjson_inline operator int64_t() noexcept(false); |
218 | /** |
219 | * Cast this JSON value to a double. |
220 | * |
221 | * @returns A double. |
222 | * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not a valid floating-point number. |
223 | */ |
224 | simdjson_inline operator double() noexcept(false); |
225 | /** |
226 | * Cast this JSON value to a string. |
227 | * |
228 | * The string is guaranteed to be valid UTF-8. |
229 | * |
230 | * @returns An UTF-8 string. The string is stored in the parser and will be invalidated the next |
231 | * time it parses a document or when it is destroyed. |
232 | * @exception simdjson_error(INCORRECT_TYPE) if the JSON value is not a string. |
233 | */ |
234 | simdjson_inline operator std::string_view() noexcept(false); |
235 | /** |
236 | * Cast this JSON value to a raw_json_string. |
237 | * |
238 | * The string is guaranteed to be valid UTF-8, and may have escapes in it (e.g. \\ or \n). |
239 | * |
240 | * @returns A pointer to the raw JSON for the given string. |
241 | * @exception simdjson_error(INCORRECT_TYPE) if the JSON value is not a string. |
242 | */ |
243 | simdjson_inline operator raw_json_string() noexcept(false); |
244 | /** |
245 | * Cast this JSON value to a bool. |
246 | * |
247 | * @returns A bool value. |
248 | * @exception simdjson_error(INCORRECT_TYPE) if the JSON value is not true or false. |
249 | */ |
250 | simdjson_inline operator bool() noexcept(false); |
251 | /** |
252 | * Cast this JSON value to a value. |
253 | * |
254 | * @returns A value value. |
255 | * @exception if a JSON value cannot be found |
256 | */ |
257 | simdjson_inline operator value() noexcept(false); |
258 | #endif |
259 | /** |
260 | * This method scans the array and counts the number of elements. |
261 | * The count_elements method should always be called before you have begun |
262 | * iterating through the array: it is expected that you are pointing at |
263 | * the beginning of the array. |
264 | * The runtime complexity is linear in the size of the array. After |
265 | * calling this function, if successful, the array is 'rewinded' at its |
266 | * beginning as if it had never been accessed. If the JSON is malformed (e.g., |
267 | * there is a missing comma), then an error is returned and it is no longer |
268 | * safe to continue. |
269 | */ |
270 | simdjson_inline simdjson_result<size_t> count_elements() & noexcept; |
271 | /** |
272 | * This method scans the object and counts the number of key-value pairs. |
273 | * The count_fields method should always be called before you have begun |
274 | * iterating through the object: it is expected that you are pointing at |
275 | * the beginning of the object. |
276 | * The runtime complexity is linear in the size of the object. After |
277 | * calling this function, if successful, the object is 'rewinded' at its |
278 | * beginning as if it had never been accessed. If the JSON is malformed (e.g., |
279 | * there is a missing comma), then an error is returned and it is no longer |
280 | * safe to continue. |
281 | * |
282 | * To check that an object is empty, it is more performant to use |
283 | * the is_empty() method. |
284 | */ |
285 | simdjson_inline simdjson_result<size_t> count_fields() & noexcept; |
286 | /** |
287 | * Get the value at the given index in the array. This function has linear-time complexity. |
288 | * This function should only be called once on an array instance since the array iterator is not reset between each call. |
289 | * |
290 | * @return The value at the given index, or: |
291 | * - INDEX_OUT_OF_BOUNDS if the array index is larger than an array length |
292 | */ |
293 | simdjson_inline simdjson_result<value> at(size_t index) & noexcept; |
294 | /** |
295 | * Begin array iteration. |
296 | * |
297 | * Part of the std::iterable interface. |
298 | */ |
299 | simdjson_inline simdjson_result<array_iterator> begin() & noexcept; |
300 | /** |
301 | * Sentinel representing the end of the array. |
302 | * |
303 | * Part of the std::iterable interface. |
304 | */ |
305 | simdjson_inline simdjson_result<array_iterator> end() & noexcept; |
306 | |
307 | /** |
308 | * Look up a field by name on an object (order-sensitive). |
309 | * |
310 | * The following code reads z, then y, then x, and thus will not retrieve x or y if fed the |
311 | * JSON `{ "x": 1, "y": 2, "z": 3 }`: |
312 | * |
313 | * ```c++ |
314 | * simdjson::ondemand::parser parser; |
315 | * auto obj = parser.parse(R"( { "x": 1, "y": 2, "z": 3 } )"_padded); |
316 | * double z = obj.find_field("z"); |
317 | * double y = obj.find_field("y"); |
318 | * double x = obj.find_field("x"); |
319 | * ``` |
320 | * |
321 | * **Raw Keys:** The lookup will be done against the *raw* key, and will not unescape keys. |
322 | * e.g. `object["a"]` will match `{ "a": 1 }`, but will *not* match `{ "\u0061": 1 }`. |
323 | * |
324 | * |
325 | * You must consume the fields on an object one at a time. A request for a new key |
326 | * invalidates previous field values: it makes them unsafe. E.g., the array |
327 | * given by content["bids"].get_array() should not be accessed after you have called |
328 | * content["asks"].get_array(). You can detect such mistakes by first compiling and running |
329 | * the code in Debug mode (or with the macro `SIMDJSON_DEVELOPMENT_CHECKS` set to 1): an |
330 | * OUT_OF_ORDER_ITERATION error is generated. |
331 | * |
332 | * You are expected to access keys only once. You should access the value corresponding to |
333 | * a key a single time. Doing object["mykey"].to_string()and then again object["mykey"].to_string() |
334 | * is an error. |
335 | * |
336 | * @param key The key to look up. |
337 | * @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object. |
338 | */ |
339 | simdjson_inline simdjson_result<value> find_field(std::string_view key) & noexcept; |
340 | /** @overload simdjson_inline simdjson_result<value> find_field(std::string_view key) & noexcept; */ |
341 | simdjson_inline simdjson_result<value> find_field(const char *key) & noexcept; |
342 | |
343 | /** |
344 | * Look up a field by name on an object, without regard to key order. |
345 | * |
346 | * **Performance Notes:** This is a bit less performant than find_field(), though its effect varies |
347 | * and often appears negligible. It starts out normally, starting out at the last field; but if |
348 | * the field is not found, it scans from the beginning of the object to see if it missed it. That |
349 | * missing case has a non-cache-friendly bump and lots of extra scanning, especially if the object |
350 | * in question is large. The fact that the extra code is there also bumps the executable size. |
351 | * |
352 | * It is the default, however, because it would be highly surprising (and hard to debug) if the |
353 | * default behavior failed to look up a field just because it was in the wrong order--and many |
354 | * APIs assume this. Therefore, you must be explicit if you want to treat objects as out of order. |
355 | * |
356 | * Use find_field() if you are sure fields will be in order (or are willing to treat it as if the |
357 | * field wasn't there when they aren't). |
358 | * |
359 | * You must consume the fields on an object one at a time. A request for a new key |
360 | * invalidates previous field values: it makes them unsafe. E.g., the array |
361 | * given by content["bids"].get_array() should not be accessed after you have called |
362 | * content["asks"].get_array(). You can detect such mistakes by first compiling and running |
363 | * the code in Debug mode (or with the macro `SIMDJSON_DEVELOPMENT_CHECKS` set to 1): an |
364 | * OUT_OF_ORDER_ITERATION error is generated. |
365 | * |
366 | * You are expected to access keys only once. You should access the value corresponding to a key |
367 | * a single time. Doing object["mykey"].to_string() and then again object["mykey"].to_string() |
368 | * is an error. |
369 | * |
370 | * @param key The key to look up. |
371 | * @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object. |
372 | */ |
373 | simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; |
374 | /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */ |
375 | simdjson_inline simdjson_result<value> find_field_unordered(const char *key) & noexcept; |
376 | /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */ |
377 | simdjson_inline simdjson_result<value> operator[](std::string_view key) & noexcept; |
378 | /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */ |
379 | simdjson_inline simdjson_result<value> operator[](const char *key) & noexcept; |
380 | |
381 | /** |
382 | * Get the type of this JSON value. It does not validate or consume the value. |
383 | * E.g., you must still call "is_null()" to check that a value is null even if |
384 | * "type()" returns json_type::null. |
385 | * |
386 | * NOTE: If you're only expecting a value to be one type (a typical case), it's generally |
387 | * better to just call .get_double, .get_string, etc. and check for INCORRECT_TYPE (or just |
388 | * let it throw an exception). |
389 | * |
390 | * @error TAPE_ERROR when the JSON value is a bad token like "}" "," or "alse". |
391 | */ |
392 | simdjson_inline simdjson_result<json_type> type() noexcept; |
393 | |
394 | /** |
395 | * Checks whether the document is a scalar (string, number, null, Boolean). |
396 | * Returns false when there it is an array or object. |
397 | * |
398 | * @returns true if the type is string, number, null, Boolean |
399 | * @error TAPE_ERROR when the JSON value is a bad token like "}" "," or "alse". |
400 | */ |
401 | simdjson_inline simdjson_result<bool> is_scalar() noexcept; |
402 | |
403 | /** |
404 | * Checks whether the document is a negative number. |
405 | * |
406 | * @returns true if the number if negative. |
407 | */ |
408 | simdjson_inline bool is_negative() noexcept; |
409 | /** |
410 | * Checks whether the document is an integer number. Note that |
411 | * this requires to partially parse the number string. If |
412 | * the value is determined to be an integer, it may still |
413 | * not parse properly as an integer in subsequent steps |
414 | * (e.g., it might overflow). |
415 | * |
416 | * @returns true if the number if negative. |
417 | */ |
418 | simdjson_inline simdjson_result<bool> is_integer() noexcept; |
419 | /** |
420 | * Determine the number type (integer or floating-point number) as quickly |
421 | * as possible. This function does not fully validate the input. It is |
422 | * useful when you only need to classify the numbers, without parsing them. |
423 | * |
424 | * If you are planning to retrieve the value or you need full validation, |
425 | * consider using the get_number() method instead: it will fully parse |
426 | * and validate the input, and give you access to the type: |
427 | * get_number().get_number_type(). |
428 | * |
429 | * get_number_type() is number_type::unsigned_integer if we have |
430 | * an integer greater or equal to 9223372036854775808 |
431 | * get_number_type() is number_type::signed_integer if we have an |
432 | * integer that is less than 9223372036854775808 |
433 | * Otherwise, get_number_type() has value number_type::floating_point_number |
434 | * |
435 | * This function requires processing the number string, but it is expected |
436 | * to be faster than get_number().get_number_type() because it is does not |
437 | * parse the number value. |
438 | * |
439 | * @returns the type of the number |
440 | */ |
441 | simdjson_inline simdjson_result<number_type> get_number_type() noexcept; |
442 | |
443 | /** |
444 | * Attempt to parse an ondemand::number. An ondemand::number may |
445 | * contain an integer value or a floating-point value, the simdjson |
446 | * library will autodetect the type. Thus it is a dynamically typed |
447 | * number. Before accessing the value, you must determine the detected |
448 | * type. |
449 | * |
450 | * number.get_number_type() is number_type::signed_integer if we have |
451 | * an integer in [-9223372036854775808,9223372036854775808) |
452 | * You can recover the value by calling number.get_int64() and you |
453 | * have that number.is_int64() is true. |
454 | * |
455 | * number.get_number_type() is number_type::unsigned_integer if we have |
456 | * an integer in [9223372036854775808,18446744073709551616) |
457 | * You can recover the value by calling number.get_uint64() and you |
458 | * have that number.is_uint64() is true. |
459 | * |
460 | * Otherwise, number.get_number_type() has value number_type::floating_point_number |
461 | * and we have a binary64 number. |
462 | * You can recover the value by calling number.get_double() and you |
463 | * have that number.is_double() is true. |
464 | * |
465 | * You must check the type before accessing the value: it is an error |
466 | * to call "get_int64()" when number.get_number_type() is not |
467 | * number_type::signed_integer and when number.is_int64() is false. |
468 | */ |
469 | simdjson_warn_unused simdjson_inline simdjson_result<number> get_number() noexcept; |
470 | |
471 | /** |
472 | * Get the raw JSON for this token. |
473 | * |
474 | * The string_view will always point into the input buffer. |
475 | * |
476 | * The string_view will start at the beginning of the token, and include the entire token |
477 | * *as well as all spaces until the next token (or EOF).* This means, for example, that a |
478 | * string token always begins with a " and is always terminated by the final ", possibly |
479 | * followed by a number of spaces. |
480 | * |
481 | * The string_view is *not* null-terminated. If this is a scalar (string, number, |
482 | * boolean, or null), the character after the end of the string_view may be the padded buffer. |
483 | * |
484 | * Tokens include: |
485 | * - { |
486 | * - [ |
487 | * - "a string (possibly with UTF-8 or backslashed characters like \\\")". |
488 | * - -1.2e-100 |
489 | * - true |
490 | * - false |
491 | * - null |
492 | */ |
493 | simdjson_inline simdjson_result<std::string_view> raw_json_token() noexcept; |
494 | |
495 | /** |
496 | * Reset the iterator inside the document instance so we are pointing back at the |
497 | * beginning of the document, as if it had just been created. It invalidates all |
498 | * values, objects and arrays that you have created so far (including unescaped strings). |
499 | */ |
500 | inline void rewind() noexcept; |
501 | /** |
502 | * Returns debugging information. |
503 | */ |
504 | inline std::string to_debug_string() noexcept; |
505 | /** |
506 | * Some unrecoverable error conditions may render the document instance unusable. |
507 | * The is_alive() method returns true when the document is still suitable. |
508 | */ |
509 | inline bool is_alive() noexcept; |
510 | |
511 | /** |
512 | * Returns the current location in the document if in bounds. |
513 | */ |
514 | inline simdjson_result<const char *> current_location() noexcept; |
515 | |
516 | /** |
517 | * Returns the current depth in the document if in bounds. |
518 | * |
519 | * E.g., |
520 | * 0 = finished with document |
521 | * 1 = document root value (could be [ or {, not yet known) |
522 | * 2 = , or } inside root array/object |
523 | * 3 = key or value inside root array/object. |
524 | */ |
525 | simdjson_inline int32_t current_depth() const noexcept; |
526 | |
527 | /** |
528 | * Get the value associated with the given JSON pointer. We use the RFC 6901 |
529 | * https://tools.ietf.org/html/rfc6901 standard. |
530 | * |
531 | * ondemand::parser parser; |
532 | * auto json = R"({ "foo": { "a": [ 10, 20, 30 ] }})"_padded; |
533 | * auto doc = parser.iterate(json); |
534 | * doc.at_pointer("/foo/a/1") == 20 |
535 | * |
536 | * It is allowed for a key to be the empty string: |
537 | * |
538 | * ondemand::parser parser; |
539 | * auto json = R"({ "": { "a": [ 10, 20, 30 ] }})"_padded; |
540 | * auto doc = parser.iterate(json); |
541 | * doc.at_pointer("//a/1") == 20 |
542 | * |
543 | * Note that at_pointer() automatically calls rewind between each call. Thus |
544 | * all values, objects and arrays that you have created so far (including unescaped strings) |
545 | * are invalidated. After calling at_pointer, you need to consume the result: string values |
546 | * should be stored in your own variables, arrays should be decoded and stored in your own array-like |
547 | * structures and so forth. |
548 | * |
549 | * Also note that at_pointer() relies on find_field() which implies that we do not unescape keys when matching |
550 | * |
551 | * @return The value associated with the given JSON pointer, or: |
552 | * - NO_SUCH_FIELD if a field does not exist in an object |
553 | * - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length |
554 | * - INCORRECT_TYPE if a non-integer is used to access an array |
555 | * - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed |
556 | * - SCALAR_DOCUMENT_AS_VALUE if the json_pointer is empty and the document is not a scalar (see is_scalar() function). |
557 | */ |
558 | simdjson_inline simdjson_result<value> at_pointer(std::string_view json_pointer) noexcept; |
559 | /** |
560 | * Consumes the document and returns a string_view instance corresponding to the |
561 | * document as represented in JSON. It points inside the original byte array containing |
562 | * the JSON document. |
563 | */ |
564 | simdjson_inline simdjson_result<std::string_view> raw_json() noexcept; |
565 | protected: |
566 | /** |
567 | * Consumes the document. |
568 | */ |
569 | simdjson_inline error_code consume() noexcept; |
570 | |
571 | simdjson_inline document(ondemand::json_iterator &&iter) noexcept; |
572 | simdjson_inline const uint8_t *text(uint32_t idx) const noexcept; |
573 | |
574 | simdjson_inline value_iterator resume_value_iterator() noexcept; |
575 | simdjson_inline value_iterator get_root_value_iterator() noexcept; |
576 | simdjson_inline simdjson_result<object> start_or_resume_object() noexcept; |
577 | static simdjson_inline document start(ondemand::json_iterator &&iter) noexcept; |
578 | |
579 | // |
580 | // Fields |
581 | // |
582 | json_iterator iter{}; ///< Current position in the document |
583 | static constexpr depth_t DOCUMENT_DEPTH = 0; ///< document depth is always 0 |
584 | |
585 | friend class array_iterator; |
586 | friend class value; |
587 | friend class ondemand::parser; |
588 | friend class object; |
589 | friend class array; |
590 | friend class field; |
591 | friend class token; |
592 | friend class document_stream; |
593 | friend class document_reference; |
594 | }; |
595 | |
596 | |
597 | /** |
598 | * A document_reference is a thin wrapper around a document reference instance. |
599 | */ |
600 | class document_reference { |
601 | public: |
602 | simdjson_inline document_reference() noexcept; |
603 | simdjson_inline document_reference(document &d) noexcept; |
604 | simdjson_inline document_reference(const document_reference &other) noexcept = default; |
605 | simdjson_inline document_reference& operator=(const document_reference &other) noexcept = default; |
606 | simdjson_inline void rewind() noexcept; |
607 | simdjson_inline simdjson_result<array> get_array() & noexcept; |
608 | simdjson_inline simdjson_result<object> get_object() & noexcept; |
609 | simdjson_inline simdjson_result<uint64_t> get_uint64() noexcept; |
610 | simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept; |
611 | simdjson_inline simdjson_result<int64_t> get_int64() noexcept; |
612 | simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept; |
613 | simdjson_inline simdjson_result<double> get_double() noexcept; |
614 | simdjson_inline simdjson_result<double> get_double_in_string() noexcept; |
615 | simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement = false) noexcept; |
616 | simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept; |
617 | simdjson_inline simdjson_result<raw_json_string> get_raw_json_string() noexcept; |
618 | simdjson_inline simdjson_result<bool> get_bool() noexcept; |
619 | simdjson_inline simdjson_result<value> get_value() noexcept; |
620 | |
621 | simdjson_inline simdjson_result<bool> is_null() noexcept; |
622 | simdjson_inline simdjson_result<std::string_view> raw_json() noexcept; |
623 | simdjson_inline operator document&() const noexcept; |
624 | |
625 | #if SIMDJSON_EXCEPTIONS |
626 | simdjson_inline operator array() & noexcept(false); |
627 | simdjson_inline operator object() & noexcept(false); |
628 | simdjson_inline operator uint64_t() noexcept(false); |
629 | simdjson_inline operator int64_t() noexcept(false); |
630 | simdjson_inline operator double() noexcept(false); |
631 | simdjson_inline operator std::string_view() noexcept(false); |
632 | simdjson_inline operator raw_json_string() noexcept(false); |
633 | simdjson_inline operator bool() noexcept(false); |
634 | simdjson_inline operator value() noexcept(false); |
635 | #endif |
636 | simdjson_inline simdjson_result<size_t> count_elements() & noexcept; |
637 | simdjson_inline simdjson_result<size_t> count_fields() & noexcept; |
638 | simdjson_inline simdjson_result<value> at(size_t index) & noexcept; |
639 | simdjson_inline simdjson_result<array_iterator> begin() & noexcept; |
640 | simdjson_inline simdjson_result<array_iterator> end() & noexcept; |
641 | simdjson_inline simdjson_result<value> find_field(std::string_view key) & noexcept; |
642 | simdjson_inline simdjson_result<value> find_field(const char *key) & noexcept; |
643 | simdjson_inline simdjson_result<value> operator[](std::string_view key) & noexcept; |
644 | simdjson_inline simdjson_result<value> operator[](const char *key) & noexcept; |
645 | simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; |
646 | simdjson_inline simdjson_result<value> find_field_unordered(const char *key) & noexcept; |
647 | |
648 | simdjson_inline simdjson_result<json_type> type() noexcept; |
649 | simdjson_inline simdjson_result<bool> is_scalar() noexcept; |
650 | |
651 | simdjson_inline simdjson_result<const char *> current_location() noexcept; |
652 | simdjson_inline int32_t current_depth() const noexcept; |
653 | simdjson_inline bool is_negative() noexcept; |
654 | simdjson_inline simdjson_result<bool> is_integer() noexcept; |
655 | simdjson_inline simdjson_result<number_type> get_number_type() noexcept; |
656 | simdjson_inline simdjson_result<number> get_number() noexcept; |
657 | simdjson_inline simdjson_result<std::string_view> raw_json_token() noexcept; |
658 | simdjson_inline simdjson_result<value> at_pointer(std::string_view json_pointer) noexcept; |
659 | private: |
660 | document *doc{nullptr}; |
661 | }; |
662 | } // namespace ondemand |
663 | } // namespace SIMDJSON_IMPLEMENTATION |
664 | } // namespace simdjson |
665 | |
666 | namespace simdjson { |
667 | |
668 | template<> |
669 | struct simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document> : public SIMDJSON_IMPLEMENTATION::implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::document> { |
670 | public: |
671 | simdjson_inline simdjson_result(SIMDJSON_IMPLEMENTATION::ondemand::document &&value) noexcept; ///< @private |
672 | simdjson_inline simdjson_result(error_code error) noexcept; ///< @private |
673 | simdjson_inline simdjson_result() noexcept = default; |
674 | simdjson_inline error_code rewind() noexcept; |
675 | |
676 | simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array> get_array() & noexcept; |
677 | simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object> get_object() & noexcept; |
678 | simdjson_inline simdjson_result<uint64_t> get_uint64() noexcept; |
679 | simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept; |
680 | simdjson_inline simdjson_result<int64_t> get_int64() noexcept; |
681 | simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept; |
682 | simdjson_inline simdjson_result<double> get_double() noexcept; |
683 | simdjson_inline simdjson_result<double> get_double_in_string() noexcept; |
684 | simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement = false) noexcept; |
685 | simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept; |
686 | simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string> get_raw_json_string() noexcept; |
687 | simdjson_inline simdjson_result<bool> get_bool() noexcept; |
688 | simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> get_value() noexcept; |
689 | simdjson_inline simdjson_result<bool> is_null() noexcept; |
690 | |
691 | template<typename T> simdjson_inline simdjson_result<T> get() & noexcept; |
692 | template<typename T> simdjson_inline simdjson_result<T> get() && noexcept; |
693 | |
694 | template<typename T> simdjson_inline error_code get(T &out) & noexcept; |
695 | template<typename T> simdjson_inline error_code get(T &out) && noexcept; |
696 | |
697 | #if SIMDJSON_EXCEPTIONS |
698 | simdjson_inline operator SIMDJSON_IMPLEMENTATION::ondemand::array() & noexcept(false); |
699 | simdjson_inline operator SIMDJSON_IMPLEMENTATION::ondemand::object() & noexcept(false); |
700 | simdjson_inline operator uint64_t() noexcept(false); |
701 | simdjson_inline operator int64_t() noexcept(false); |
702 | simdjson_inline operator double() noexcept(false); |
703 | simdjson_inline operator std::string_view() noexcept(false); |
704 | simdjson_inline operator SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string() noexcept(false); |
705 | simdjson_inline operator bool() noexcept(false); |
706 | simdjson_inline operator SIMDJSON_IMPLEMENTATION::ondemand::value() noexcept(false); |
707 | #endif |
708 | simdjson_inline simdjson_result<size_t> count_elements() & noexcept; |
709 | simdjson_inline simdjson_result<size_t> count_fields() & noexcept; |
710 | simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> at(size_t index) & noexcept; |
711 | simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator> begin() & noexcept; |
712 | simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator> end() & noexcept; |
713 | simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field(std::string_view key) & noexcept; |
714 | simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field(const char *key) & noexcept; |
715 | simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> operator[](std::string_view key) & noexcept; |
716 | simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> operator[](const char *key) & noexcept; |
717 | simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field_unordered(std::string_view key) & noexcept; |
718 | simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field_unordered(const char *key) & noexcept; |
719 | simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::json_type> type() noexcept; |
720 | simdjson_inline simdjson_result<bool> is_scalar() noexcept; |
721 | simdjson_inline simdjson_result<const char *> current_location() noexcept; |
722 | simdjson_inline int32_t current_depth() const noexcept; |
723 | simdjson_inline bool is_negative() noexcept; |
724 | simdjson_inline simdjson_result<bool> is_integer() noexcept; |
725 | simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::number_type> get_number_type() noexcept; |
726 | simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::number> get_number() noexcept; |
727 | /** @copydoc simdjson_inline std::string_view document::raw_json_token() const noexcept */ |
728 | simdjson_inline simdjson_result<std::string_view> raw_json_token() noexcept; |
729 | |
730 | simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> at_pointer(std::string_view json_pointer) noexcept; |
731 | }; |
732 | |
733 | |
734 | } // namespace simdjson |
735 | |
736 | |
737 | |
738 | namespace simdjson { |
739 | |
740 | template<> |
741 | struct simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference> : public SIMDJSON_IMPLEMENTATION::implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::document_reference> { |
742 | public: |
743 | simdjson_inline simdjson_result(SIMDJSON_IMPLEMENTATION::ondemand::document_reference value, error_code error) noexcept; |
744 | simdjson_inline simdjson_result() noexcept = default; |
745 | simdjson_inline error_code rewind() noexcept; |
746 | |
747 | simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array> get_array() & noexcept; |
748 | simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object> get_object() & noexcept; |
749 | simdjson_inline simdjson_result<uint64_t> get_uint64() noexcept; |
750 | simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept; |
751 | simdjson_inline simdjson_result<int64_t> get_int64() noexcept; |
752 | simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept; |
753 | simdjson_inline simdjson_result<double> get_double() noexcept; |
754 | simdjson_inline simdjson_result<double> get_double_in_string() noexcept; |
755 | simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement = false) noexcept; |
756 | simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept; |
757 | simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string> get_raw_json_string() noexcept; |
758 | simdjson_inline simdjson_result<bool> get_bool() noexcept; |
759 | simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> get_value() noexcept; |
760 | simdjson_inline simdjson_result<bool> is_null() noexcept; |
761 | |
762 | #if SIMDJSON_EXCEPTIONS |
763 | simdjson_inline operator SIMDJSON_IMPLEMENTATION::ondemand::array() & noexcept(false); |
764 | simdjson_inline operator SIMDJSON_IMPLEMENTATION::ondemand::object() & noexcept(false); |
765 | simdjson_inline operator uint64_t() noexcept(false); |
766 | simdjson_inline operator int64_t() noexcept(false); |
767 | simdjson_inline operator double() noexcept(false); |
768 | simdjson_inline operator std::string_view() noexcept(false); |
769 | simdjson_inline operator SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string() noexcept(false); |
770 | simdjson_inline operator bool() noexcept(false); |
771 | simdjson_inline operator SIMDJSON_IMPLEMENTATION::ondemand::value() noexcept(false); |
772 | #endif |
773 | simdjson_inline simdjson_result<size_t> count_elements() & noexcept; |
774 | simdjson_inline simdjson_result<size_t> count_fields() & noexcept; |
775 | simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> at(size_t index) & noexcept; |
776 | simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator> begin() & noexcept; |
777 | simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator> end() & noexcept; |
778 | simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field(std::string_view key) & noexcept; |
779 | simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field(const char *key) & noexcept; |
780 | simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> operator[](std::string_view key) & noexcept; |
781 | simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> operator[](const char *key) & noexcept; |
782 | simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field_unordered(std::string_view key) & noexcept; |
783 | simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field_unordered(const char *key) & noexcept; |
784 | simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::json_type> type() noexcept; |
785 | simdjson_inline simdjson_result<bool> is_scalar() noexcept; |
786 | simdjson_inline simdjson_result<const char *> current_location() noexcept; |
787 | simdjson_inline simdjson_result<int32_t> current_depth() const noexcept; |
788 | simdjson_inline simdjson_result<bool> is_negative() noexcept; |
789 | simdjson_inline simdjson_result<bool> is_integer() noexcept; |
790 | simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::number_type> get_number_type() noexcept; |
791 | simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::number> get_number() noexcept; |
792 | /** @copydoc simdjson_inline std::string_view document_reference::raw_json_token() const noexcept */ |
793 | simdjson_inline simdjson_result<std::string_view> raw_json_token() noexcept; |
794 | |
795 | simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> at_pointer(std::string_view json_pointer) noexcept; |
796 | }; |
797 | |
798 | |
799 | } // namespace simdjson |
800 | |