#ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_H #ifndef SIMDJSON_CONDITIONAL_INCLUDE #define SIMDJSON_GENERIC_ONDEMAND_VALUE_H #include "simdjson/generic/ondemand/base.h" #include "simdjson/generic/implementation_simdjson_result_base.h" #include "simdjson/generic/ondemand/value_iterator.h" #include "simdjson/generic/ondemand/deserialize.h" #include #endif // SIMDJSON_CONDITIONAL_INCLUDE #include namespace simdjson { namespace SIMDJSON_IMPLEMENTATION { namespace ondemand { /** * An ephemeral JSON value returned during iteration. It is only valid for as long as you do * not access more data in the JSON document. */ class value { public: /** * Create a new invalid value. * * Exists so you can declare a variable and later assign to it before use. */ simdjson_inline value() noexcept = default; /** * Get this value as the given type. * * Supported types: object, array, raw_json_string, string_view, uint64_t, int64_t, double, bool * * You may use get_double(), get_bool(), get_uint64(), get_int64(), * get_object(), get_array(), get_raw_json_string(), or get_string() instead. * When SIMDJSON_SUPPORTS_CONCEPTS is set, custom types are also supported. * * @returns A value of the given type, parsed from the JSON. * @returns INCORRECT_TYPE If the JSON value is not the given type. */ template simdjson_inline simdjson_result get() #if SIMDJSON_SUPPORTS_CONCEPTS noexcept(custom_deserializable ? nothrow_custom_deserializable : true) #else noexcept #endif { static_assert(std::is_default_constructible::value, "The specified type is not default constructible."); T out{}; SIMDJSON_TRY(get(out)); return out; } /** * Get this value as the given type. * * Supported types: object, array, raw_json_string, string_view, uint64_t, int64_t, double, bool * If the macro SIMDJSON_SUPPORTS_CONCEPTS is set, then custom types are also supported. * * @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. * @returns INCORRECT_TYPE If the JSON value is not an object. * @returns SUCCESS If the parse succeeded and the out parameter was set to the value. */ template simdjson_warn_unused simdjson_inline error_code get(T &out) #if SIMDJSON_SUPPORTS_CONCEPTS noexcept(custom_deserializable ? nothrow_custom_deserializable : true) #else noexcept #endif { #if SIMDJSON_SUPPORTS_CONCEPTS if constexpr (custom_deserializable) { return deserialize(*this, out); } else if constexpr (concepts::optional_type) { using value_type = typename std::remove_cvref_t::value_type; // Check if the value is null bool is_null_value; SIMDJSON_TRY( is_null().get(is_null_value) ); if (is_null_value) { out.reset(); // Set to nullopt return SUCCESS; } if (!out) { out.emplace(); } return get(out.value()); } else { static_assert(!sizeof(T), "The get method with type T is not implemented by the simdjson library. " "And you do not seem to have added support for it. Indeed, we have that " "simdjson::custom_deserializable is false and the type T is not a default type " "such as ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " "int64_t, double, or bool."); static_cast(out); // to get rid of unused errors return UNINITIALIZED; } #else // SIMDJSON_SUPPORTS_CONCEPTS // Unless the simdjson library or the user provides an inline implementation, calling this method should // immediately fail. static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. " "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), " " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template." " You may also add support for custom types, see our documentation."); static_cast(out); // to get rid of unused errors return UNINITIALIZED; #endif } /** * Cast this JSON value to an array. * * @returns An object that can be used to iterate the array. * @returns INCORRECT_TYPE If the JSON value is not an array. */ simdjson_inline simdjson_result get_array() noexcept; /** * Cast this JSON value to an object. * * @returns An object that can be used to look up or iterate fields. * @returns INCORRECT_TYPE If the JSON value is not an object. */ simdjson_inline simdjson_result get_object() noexcept; /** * Cast this JSON value to an unsigned integer. * * @returns A unsigned 64-bit integer. * @returns INCORRECT_TYPE If the JSON value is not a 64-bit unsigned integer. */ simdjson_inline simdjson_result get_uint64() noexcept; /** * Cast this JSON value (inside string) to a unsigned integer. * * @returns A unsigned 64-bit integer. * @returns INCORRECT_TYPE If the JSON value is not a 64-bit unsigned integer. */ simdjson_inline simdjson_result get_uint64_in_string() noexcept; /** * Cast this JSON value to a signed integer. * * @returns A signed 64-bit integer. * @returns INCORRECT_TYPE If the JSON value is not a 64-bit integer. */ simdjson_inline simdjson_result get_int64() noexcept; /** * Cast this JSON value (inside string) to a signed integer. * * @returns A signed 64-bit integer. * @returns INCORRECT_TYPE If the JSON value is not a 64-bit integer. */ simdjson_inline simdjson_result get_int64_in_string() noexcept; /** * Cast this JSON value to a double. * * @returns A double. * @returns INCORRECT_TYPE If the JSON value is not a valid floating-point number. */ simdjson_inline simdjson_result get_double() noexcept; /** * Cast this JSON value (inside string) to a double * * @returns A double. * @returns INCORRECT_TYPE If the JSON value is not a valid floating-point number. */ simdjson_inline simdjson_result get_double_in_string() noexcept; /** * Cast this JSON value to a string. * * The string is guaranteed to be valid UTF-8. * * Equivalent to get(). * * Important: a value should be consumed once. Calling get_string() twice on the same value * is an error. * * In some instances, you may want to allow replacement of invalid Unicode sequences. * You may do so by passing the allow_replacement parameter as true. In the following * example, the string "431924697b\udff0L\u0001Y" is not valid Unicode. By passing true * to get_string, we allow the replacement of the invalid Unicode sequences with the Unicode * replacement character (U+FFFD). * * simdjson::ondemand::parser parser; * auto json = R"({"deviceId":"431924697b\udff0L\u0001Y"})"_padded; * simdjson::ondemand::document doc = parser.iterate(json); * auto view = doc["deviceId"].get_string(true); * * @returns An UTF-8 string. The string is stored in the parser when escaping was needed * and will be invalidated the next * time it parses a document or when it is destroyed. If no escaping was needed, * the string_view points directly into the original JSON buffer. * @returns INCORRECT_TYPE if the JSON value is not a string. */ simdjson_inline simdjson_result get_string(bool allow_replacement = false) noexcept; /** * Attempts to fill the provided std::string reference with the parsed value of the current string. * The data is stored into the provided std::string instance. * * The string is guaranteed to be valid UTF-8. * * Important: a value should be consumed once. Calling get_string() twice on the same value * is an error. * * Performance: This method may be slower than get_string() or get_string(bool) because it may need to allocate memory. * We recommend you avoid allocating an std::string unless you need to. * * @returns INCORRECT_TYPE if the JSON value is not a string. Otherwise, we return SUCCESS. */ template simdjson_warn_unused simdjson_inline error_code get_string(string_type& receiver, bool allow_replacement = false) noexcept; /** * Cast this JSON value to a "wobbly" string. * * The string is may not be a valid UTF-8 string. * See https://simonsapin.github.io/wtf-8/ * * Important: a value should be consumed once. Calling get_wobbly_string() twice on the same value * is an error. * * @returns An UTF-8 string. The string is stored in the parser and will be invalidated the next * time it parses a document or when it is destroyed. * @returns INCORRECT_TYPE if the JSON value is not a string. */ simdjson_inline simdjson_result get_wobbly_string() noexcept; /** * Cast this JSON value to a raw_json_string. * * The string is guaranteed to be valid UTF-8, and may have escapes in it (e.g. \\ or \n). * * @returns A pointer to the raw JSON for the given string. * @returns INCORRECT_TYPE if the JSON value is not a string. */ simdjson_inline simdjson_result get_raw_json_string() noexcept; /** * Cast this JSON value to a bool. * * @returns A bool value. * @returns INCORRECT_TYPE if the JSON value is not true or false. */ simdjson_inline simdjson_result get_bool() noexcept; /** * Checks if this JSON value is null. If and only if the value is * null, then it is consumed (we advance). If we find a token that * begins with 'n' but is not 'null', then an error is returned. * * @returns Whether the value is null. * @returns INCORRECT_TYPE If the JSON value begins with 'n' and is not 'null'. */ simdjson_inline simdjson_result is_null() noexcept; #if SIMDJSON_EXCEPTIONS /** * Cast this JSON value to an instance of type T. The programmer is responsible for * providing an implementation of get for the type T, if T is not one of the types * supported by the library (object, array, raw_json_string, string_view, uint64_t, etc.). * * See https://github.com/simdjson/simdjson/blob/master/doc/basics.md#adding-support-for-custom-types * * @returns An instance of type T */ template explicit simdjson_inline operator T() noexcept(false); /** * Cast this JSON value to an array. * * @returns An object that can be used to iterate the array. * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not an array. */ simdjson_inline operator array() noexcept(false); /** * Cast this JSON value to an object. * * @returns An object that can be used to look up or iterate fields. * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not an object. */ simdjson_inline operator object() noexcept(false); /** * Cast this JSON value to an unsigned integer. * * @returns A signed 64-bit integer. * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not a 64-bit unsigned integer. */ simdjson_inline operator uint64_t() noexcept(false); /** * Cast this JSON value to a signed integer. * * @returns A signed 64-bit integer. * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not a 64-bit integer. */ simdjson_inline operator int64_t() noexcept(false); /** * Cast this JSON value to a double. * * @returns A double. * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not a valid floating-point number. */ simdjson_inline operator double() noexcept(false); /** * Cast this JSON value to a string. * * The string is guaranteed to be valid UTF-8. * * Equivalent to get(). * * @returns An UTF-8 string. The string is stored in the parser and will be invalidated the next * time it parses a document or when it is destroyed. * @exception simdjson_error(INCORRECT_TYPE) if the JSON value is not a string. */ simdjson_inline operator std::string_view() noexcept(false); /** * Cast this JSON value to a raw_json_string. * * The string is guaranteed to be valid UTF-8, and may have escapes in it (e.g. \\ or \n). * * @returns A pointer to the raw JSON for the given string. * @exception simdjson_error(INCORRECT_TYPE) if the JSON value is not a string. */ simdjson_inline operator raw_json_string() noexcept(false); /** * Cast this JSON value to a bool. * * @returns A bool value. * @exception simdjson_error(INCORRECT_TYPE) if the JSON value is not true or false. */ simdjson_inline operator bool() noexcept(false); #endif /** * Begin array iteration. * * Part of the std::iterable interface. * * @returns INCORRECT_TYPE If the JSON value is not an array. */ simdjson_inline simdjson_result begin() & noexcept; /** * Sentinel representing the end of the array. * * Part of the std::iterable interface. */ simdjson_inline simdjson_result end() & noexcept; /** * This method scans the array and counts the number of elements. * The count_elements method should always be called before you have begun * iterating through the array: it is expected that you are pointing at * the beginning of the array. * The runtime complexity is linear in the size of the array. After * calling this function, if successful, the array is 'rewinded' at its * beginning as if it had never been accessed. If the JSON is malformed (e.g., * there is a missing comma), then an error is returned and it is no longer * safe to continue. * * Performance hint: You should only call count_elements() as a last * resort as it may require scanning the document twice or more. */ simdjson_inline simdjson_result count_elements() & noexcept; /** * This method scans the object and counts the number of key-value pairs. * The count_fields method should always be called before you have begun * iterating through the object: it is expected that you are pointing at * the beginning of the object. * The runtime complexity is linear in the size of the object. After * calling this function, if successful, the object is 'rewinded' at its * beginning as if it had never been accessed. If the JSON is malformed (e.g., * there is a missing comma), then an error is returned and it is no longer * safe to continue. * * To check that an object is empty, it is more performant to use * the is_empty() method on the object instance. * * Performance hint: You should only call count_fields() as a last * resort as it may require scanning the document twice or more. */ simdjson_inline simdjson_result count_fields() & noexcept; /** * Get the value at the given index in the array. This function has linear-time complexity. * This function should only be called once on an array instance since the array iterator is not reset between each call. * * @return The value at the given index, or: * - INDEX_OUT_OF_BOUNDS if the array index is larger than an array length */ simdjson_inline simdjson_result at(size_t index) noexcept; /** * Look up a field by name on an object (order-sensitive). By order-sensitive, we mean that * fields must be accessed in the order they appear in the JSON text (although you can * skip fields). See find_field_unordered() and operator[] for an order-insensitive version. * * The following code reads z, then y, then x, and thus will not retrieve x or y if fed the * JSON `{ "x": 1, "y": 2, "z": 3 }`: * * ```cpp * simdjson::ondemand::parser parser; * auto obj = parser.parse(R"( { "x": 1, "y": 2, "z": 3 } )"_padded); * double z = obj.find_field("z"); * double y = obj.find_field("y"); * double x = obj.find_field("x"); * ``` * If you have multiple fields with a matching key ({"x": 1, "x": 1}) be mindful * that only one field is returned. * **Raw Keys:** The lookup will be done against the *raw* key, and will not unescape keys. * e.g. `object["a"]` will match `{ "a": 1 }`, but will *not* match `{ "\u0061": 1 }`. * * @param key The key to look up. * @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object. */ simdjson_inline simdjson_result find_field(std::string_view key) noexcept; /** @overload simdjson_inline simdjson_result find_field(std::string_view key) noexcept; */ simdjson_inline simdjson_result find_field(const char *key) noexcept; /** * Look up a field by name on an object, without regard to key order. * * **Performance Notes:** This is a bit less performant than find_field(), though its effect varies * and often appears negligible. It starts out normally, starting out at the last field; but if * the field is not found, it scans from the beginning of the object to see if it missed it. That * missing case has a non-cache-friendly bump and lots of extra scanning, especially if the object * in question is large. The fact that the extra code is there also bumps the executable size. * * We default operator[] on find_field_unordered() for convenience. * It is the default because it would be highly surprising (and hard to debug) if the * default behavior failed to look up a field just because it was in the wrong order--and many * APIs assume this. Therefore, you must be explicit if you want to treat objects as out of order. * * If you have multiple fields with a matching key ({"x": 1, "x": 1}) be mindful * that only one field is returned. * * Use find_field() if you are sure fields will be in order (or are willing to treat it as if the * field as not there when they are not in order). * * @param key The key to look up. * @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object. */ simdjson_inline simdjson_result find_field_unordered(std::string_view key) noexcept; /** @overload simdjson_inline simdjson_result find_field_unordered(std::string_view key) noexcept; */ simdjson_inline simdjson_result find_field_unordered(const char *key) noexcept; /** @overload simdjson_inline simdjson_result find_field_unordered(std::string_view key) noexcept; */ simdjson_inline simdjson_result operator[](std::string_view key) noexcept; /** @overload simdjson_inline simdjson_result find_field_unordered(std::string_view key) noexcept; */ simdjson_inline simdjson_result operator[](const char *key) noexcept; simdjson_result operator[](int) noexcept = delete; /** * Get the type of this JSON value. It does not validate or consume the value. * E.g., you must still call "is_null()" to check that a value is null even if * "type()" returns json_type::null. * * NOTE: If you're only expecting a value to be one type (a typical case), it's generally * better to just call .get_double, .get_string, etc. and check for INCORRECT_TYPE (or just * let it throw an exception). * * @return The type of JSON value (json_type::array, json_type::object, json_type::string, * json_type::number, json_type::boolean, or json_type::null). * @error TAPE_ERROR when the JSON value is a bad token like "}" "," or "alse". */ simdjson_inline simdjson_result type() noexcept; /** * Checks whether the value is a scalar (string, number, null, Boolean). * Returns false when there it is an array or object. * * @returns true if the type is string, number, null, Boolean * @error TAPE_ERROR when the JSON value is a bad token like "}" "," or "alse". */ simdjson_inline simdjson_result is_scalar() noexcept; /** * Checks whether the value is a string. * * @returns true if the type is string * @error TAPE_ERROR when the JSON value is a bad token like "}" "," or "alse". */ simdjson_inline simdjson_result is_string() noexcept; /** * Checks whether the value is a negative number. * * @returns true if the number if negative. */ simdjson_inline bool is_negative() noexcept; /** * Checks whether the value is an integer number. Note that * this requires to partially parse the number string. If * the value is determined to be an integer, it may still * not parse properly as an integer in subsequent steps * (e.g., it might overflow). * * Performance note: if you call this function systematically * before parsing a number, you may have fallen for a performance * anti-pattern. * * @returns true if the number if negative. */ simdjson_inline simdjson_result is_integer() noexcept; /** * Determine the number type (integer or floating-point number) as quickly * as possible. This function does not fully validate the input. It is * useful when you only need to classify the numbers, without parsing them. * * If you are planning to retrieve the value or you need full validation, * consider using the get_number() method instead: it will fully parse * and validate the input, and give you access to the type: * get_number().get_number_type(). * * get_number_type() is number_type::unsigned_integer if we have * an integer greater or equal to 9223372036854775808. * get_number_type() is number_type::signed_integer if we have an * integer that is less than 9223372036854775808. * get_number_type() is number_type::big_integer for integers that do not fit in 64 bits, * in which case the digit_count is set to the length of the big integer string. * Otherwise, get_number_type() has value number_type::floating_point_number. * * This function requires processing the number string, but it is expected * to be faster than get_number().get_number_type() because it is does not * parse the number value. * * @returns the type of the number */ simdjson_inline simdjson_result get_number_type() noexcept; /** * Attempt to parse an ondemand::number. An ondemand::number may * contain an integer value or a floating-point value, the simdjson * library will autodetect the type. Thus it is a dynamically typed * number. Before accessing the value, you must determine the detected * type. * * number.get_number_type() is number_type::signed_integer if we have * an integer in [-9223372036854775808,9223372036854775808) * You can recover the value by calling number.get_int64() and you * have that number.is_int64() is true. * * number.get_number_type() is number_type::unsigned_integer if we have * an integer in [9223372036854775808,18446744073709551616) * You can recover the value by calling number.get_uint64() and you * have that number.is_uint64() is true. * * For integers that do not fit in 64 bits, the function returns BIGINT_ERROR error code. * * Otherwise, number.get_number_type() has value number_type::floating_point_number * and we have a binary64 number. * You can recover the value by calling number.get_double() and you * have that number.is_double() is true. * * You must check the type before accessing the value: it is an error * to call "get_int64()" when number.get_number_type() is not * number_type::signed_integer and when number.is_int64() is false. * * Performance note: this is designed with performance in mind. When * calling 'get_number()', you scan the number string only once, determining * efficiently the type and storing it in an efficient manner. */ simdjson_warn_unused simdjson_inline simdjson_result get_number() noexcept; /** * Get the raw JSON for this token. * * The string_view will always point into the input buffer. * * The string_view will start at the beginning of the token, and include the entire token * *as well as all spaces until the next token (or EOF).* This means, for example, that a * string token always begins with a " and is always terminated by the final ", possibly * followed by a number of spaces. * * The string_view is *not* null-terminated. However, if this is a scalar (string, number, * boolean, or null), the character after the end of the string_view is guaranteed to be * a non-space token. * * Tokens include: * - { * - [ * - "a string (possibly with UTF-8 or backslashed characters like \\\")". * - -1.2e-100 * - true * - false * - null * * See also value::raw_json(). */ simdjson_inline std::string_view raw_json_token() noexcept; /** * Get a string_view pointing at this value in the JSON document. * If this element is an array or an object, it consumes the array or the object * and returns a string_view instance corresponding to the * array as represented in JSON. It points inside the original document. * If this element is a scalar (string, number, Boolean, null), it returns what * raw_json_token() would return. */ simdjson_inline simdjson_result raw_json() noexcept; /** * Returns the current location in the document if in bounds. */ simdjson_inline simdjson_result current_location() noexcept; /** * Returns the current depth in the document if in bounds. * * E.g., * 0 = finished with document * 1 = document root value (could be [ or {, not yet known) * 2 = , or } inside root array/object * 3 = key or value inside root array/object. */ simdjson_inline int32_t current_depth() const noexcept; /** * Get the value associated with the given JSON pointer. We use the RFC 6901 * https://tools.ietf.org/html/rfc6901 standard. * * ondemand::parser parser; * auto json = R"({ "foo": { "a": [ 10, 20, 30 ] }})"_padded; * auto doc = parser.iterate(json); * doc.at_pointer("/foo/a/1") == 20 * * It is allowed for a key to be the empty string: * * ondemand::parser parser; * auto json = R"({ "": { "a": [ 10, 20, 30 ] }})"_padded; * auto doc = parser.iterate(json); * doc.at_pointer("//a/1") == 20 * * Note that at_pointer() called on the document automatically calls the document's rewind * method between each call. It invalidates all previously accessed arrays, objects and values * that have not been consumed. * * Calling at_pointer() on non-document instances (e.g., arrays and objects) is not * standardized (by RFC 6901). We provide some experimental support for JSON pointers * on non-document instances. Yet it is not the case when calling at_pointer on an array * or an object instance: there is no rewind and no invalidation. * * You may only call at_pointer on an array after it has been created, but before it has * been first accessed. When calling at_pointer on an array, the pointer is advanced to * the location indicated by the JSON pointer (in case of success). It is no longer possible * to call at_pointer on the same array. * * You may call at_pointer more than once on an object, but each time the pointer is advanced * to be within the value matched by the key indicated by the JSON pointer query. Thus any preceding * key (as well as the current key) can no longer be used with following JSON pointer calls. * * Also note that at_pointer() relies on find_field() which implies that we do not unescape keys when matching * * @return The value associated with the given JSON pointer, or: * - NO_SUCH_FIELD if a field does not exist in an object * - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length * - INCORRECT_TYPE if a non-integer is used to access an array * - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed */ simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; /** * Get the value associated with the given JSONPath expression. We only support * JSONPath queries that trivially convertible to JSON Pointer queries: key * names and array indices. * * @return The value associated with the given JSONPath expression, or: * - INVALID_JSON_POINTER if the JSONPath to JSON Pointer conversion fails * - NO_SUCH_FIELD if a field does not exist in an object * - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length * - INCORRECT_TYPE if a non-integer is used to access an array */ simdjson_inline simdjson_result at_path(std::string_view at_path) noexcept; /** * Get all values matching the given JSONPath expression with wildcard support. * Supports wildcard character (*) for arrays or ".*" for objects. * * @param json_path JSONPath expression with wildcards * @return Vector of values matching the wildcard pattern */ simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; protected: /** * Create a value. */ simdjson_inline value(const value_iterator &iter) noexcept; /** * Skip this value, allowing iteration to continue. */ simdjson_inline void skip() noexcept; /** * Start a value at the current position. * * (It should already be started; this is just a self-documentation method.) */ static simdjson_inline value start(const value_iterator &iter) noexcept; /** * Resume a value. */ static simdjson_inline value resume(const value_iterator &iter) noexcept; /** * Get the object, starting or resuming it as necessary */ simdjson_inline simdjson_result start_or_resume_object() noexcept; // simdjson_inline void log_value(const char *type) const noexcept; // simdjson_inline void log_error(const char *message) const noexcept; value_iterator iter{}; friend class document; friend class array_iterator; friend class field; friend class object; friend struct simdjson_result; friend struct simdjson_result; friend class field; }; } // namespace ondemand } // namespace SIMDJSON_IMPLEMENTATION } // namespace simdjson namespace simdjson { template<> struct simdjson_result : public SIMDJSON_IMPLEMENTATION::implementation_simdjson_result_base { public: simdjson_inline simdjson_result(SIMDJSON_IMPLEMENTATION::ondemand::value &&value) noexcept; ///< @private simdjson_inline simdjson_result(error_code error) noexcept; ///< @private simdjson_inline simdjson_result() noexcept = default; simdjson_inline simdjson_result get_array() noexcept; simdjson_inline simdjson_result get_object() noexcept; simdjson_inline simdjson_result get_uint64() noexcept; simdjson_inline simdjson_result get_uint64_in_string() noexcept; simdjson_inline simdjson_result get_int64() noexcept; simdjson_inline simdjson_result get_int64_in_string() noexcept; simdjson_inline simdjson_result get_double() noexcept; simdjson_inline simdjson_result get_double_in_string() noexcept; simdjson_inline simdjson_result get_string(bool allow_replacement = false) noexcept; template simdjson_warn_unused simdjson_inline error_code get_string(string_type& receiver, bool allow_replacement = false) noexcept; simdjson_inline simdjson_result get_wobbly_string() noexcept; simdjson_inline simdjson_result get_raw_json_string() noexcept; simdjson_inline simdjson_result get_bool() noexcept; simdjson_inline simdjson_result is_null() noexcept; template simdjson_inline simdjson_result get() noexcept; template simdjson_inline error_code get(T &out) noexcept; #if SIMDJSON_EXCEPTIONS template explicit simdjson_inline operator T() noexcept(false); simdjson_inline operator SIMDJSON_IMPLEMENTATION::ondemand::array() noexcept(false); simdjson_inline operator SIMDJSON_IMPLEMENTATION::ondemand::object() noexcept(false); simdjson_inline operator uint64_t() noexcept(false); simdjson_inline operator int64_t() noexcept(false); simdjson_inline operator double() noexcept(false); simdjson_inline operator std::string_view() noexcept(false); simdjson_inline operator SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string() noexcept(false); simdjson_inline operator bool() noexcept(false); #endif simdjson_inline simdjson_result count_elements() & noexcept; simdjson_inline simdjson_result count_fields() & noexcept; simdjson_inline simdjson_result at(size_t index) noexcept; simdjson_inline simdjson_result begin() & noexcept; simdjson_inline simdjson_result end() & noexcept; /** * Look up a field by name on an object (order-sensitive). By order-sensitive, we mean that * fields must be accessed in the order they appear in the JSON text (although you can * skip fields). See find_field_unordered() and operator[] for an order-insensitive version. * * The following code reads z, then y, then x, and thus will not retrieve x or y if fed the * JSON `{ "x": 1, "y": 2, "z": 3 }`: * * ```cpp * simdjson::ondemand::parser parser; * auto obj = parser.parse(R"( { "x": 1, "y": 2, "z": 3 } )"_padded); * double z = obj.find_field("z"); * double y = obj.find_field("y"); * double x = obj.find_field("x"); * ``` * * **Raw Keys:** The lookup will be done against the *raw* key, and will not unescape keys. * e.g. `object["a"]` will match `{ "a": 1 }`, but will *not* match `{ "\u0061": 1 }`. * * @param key The key to look up. * @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object. */ simdjson_inline simdjson_result find_field(std::string_view key) noexcept; /** @overload simdjson_inline simdjson_result find_field(std::string_view key) noexcept; */ simdjson_inline simdjson_result find_field(const char *key) noexcept; /** * Look up a field by name on an object, without regard to key order. * * **Performance Notes:** This is a bit less performant than find_field(), though its effect varies * and often appears negligible. It starts out normally, starting out at the last field; but if * the field is not found, it scans from the beginning of the object to see if it missed it. That * missing case has a non-cache-friendly bump and lots of extra scanning, especially if the object * in question is large. The fact that the extra code is there also bumps the executable size. * * We default operator[] on find_field_unordered() for convenience. * It is the default because it would be highly surprising (and hard to debug) if the * default behavior failed to look up a field just because it was in the wrong order--and many * APIs assume this. Therefore, you must be explicit if you want to treat objects as out of order. * * Use find_field() if you are sure fields will be in order (or are willing to treat it as if the * field as not there when they are not in order). * * @param key The key to look up. * @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object. */ simdjson_inline simdjson_result find_field_unordered(std::string_view key) noexcept; /** @overload simdjson_inline simdjson_result find_field_unordered(std::string_view key) noexcept; */ simdjson_inline simdjson_result find_field_unordered(const char *key) noexcept; /** @overload simdjson_inline simdjson_result find_field_unordered(std::string_view key) noexcept; */ simdjson_inline simdjson_result operator[](std::string_view key) noexcept; /** @overload simdjson_inline simdjson_result find_field_unordered(std::string_view key) noexcept; */ simdjson_inline simdjson_result operator[](const char *key) noexcept; simdjson_result operator[](int) noexcept = delete; /** * Get the type of this JSON value. It does not validate or consume the value. * E.g., you must still call "is_null()" to check that a value is null even if * "type()" returns json_type::null. * * Given a valid JSON document, the answer can be one of * simdjson::ondemand::json_type::object, * simdjson::ondemand::json_type::array, * simdjson::ondemand::json_type::string, * simdjson::ondemand::json_type::number, * simdjson::ondemand::json_type::boolean, * simdjson::ondemand::json_type::null. * * Starting with simdjson 4.0, this function will return simdjson::ondemand::json_type::unknown * given a bad token. * This allows you to identify a case such as {"key": NaN} and identify the NaN value. * The simdjson::ondemand::json_type::unknown value should only happen with non-valid JSON. * * NOTE: If you're only expecting a value to be one type (a typical case), it's generally * better to just call .get_double, .get_string, etc. and check for INCORRECT_TYPE (or just * let it throw an exception). */ simdjson_inline simdjson_result type() noexcept; simdjson_inline simdjson_result is_scalar() noexcept; simdjson_inline simdjson_result is_string() noexcept; simdjson_inline simdjson_result is_negative() noexcept; simdjson_inline simdjson_result is_integer() noexcept; simdjson_inline simdjson_result get_number_type() noexcept; simdjson_inline simdjson_result get_number() noexcept; /** @copydoc simdjson_inline std::string_view value::raw_json_token() const noexcept */ simdjson_inline simdjson_result raw_json_token() noexcept; simdjson_inline simdjson_result raw_json() noexcept; /** @copydoc simdjson_inline simdjson_result current_location() noexcept */ simdjson_inline simdjson_result current_location() noexcept; /** @copydoc simdjson_inline int32_t current_depth() const noexcept */ simdjson_inline simdjson_result current_depth() const noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; }; } // namespace simdjson #endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_H