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