#include "simdjson/error.h" namespace simdjson { namespace SIMDJSON_IMPLEMENTATION { namespace ondemand { class array; class document; class field; class object; class raw_json_string; /** * An ephemeral JSON value returned during iteration. */ class value { public: /** * Create a new invalid value. * * Exists so you can declare a variable and later assign to it before use. */ simdjson_really_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. * * @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_really_inline simdjson_result get() noexcept { // Unless the simdjson library 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."); } /** * Get this value as the given type. * * Supported types: object, array, raw_json_string, string_view, uint64_t, int64_t, double, bool * * @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_really_inline error_code get(T &out) noexcept; /** * 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_really_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_really_inline simdjson_result get_object() noexcept; /** * Cast this JSON value to an unsigned integer. * * @returns A signed 64-bit integer. * @returns INCORRECT_TYPE If the JSON value is not a 64-bit unsigned integer. */ simdjson_really_inline simdjson_result get_uint64() 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_really_inline simdjson_result get_int64() 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_really_inline simdjson_result get_double() noexcept; /** * 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. * @returns INCORRECT_TYPE if the JSON value is not a string. */ simdjson_really_inline simdjson_result get_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_really_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_really_inline simdjson_result get_bool() noexcept; /** * Checks if this JSON value is null. * * @returns Whether the value is null. */ simdjson_really_inline bool is_null() noexcept; #if SIMDJSON_EXCEPTIONS /** * 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_really_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_really_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_really_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_really_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_really_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_really_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_really_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_really_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_really_inline simdjson_result begin() & noexcept; /** * Sentinel representing the end of the array. * * Part of the std::iterable interface. */ simdjson_really_inline simdjson_result end() & noexcept; /** * Look up a field by name on an object (order-sensitive). * * 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 }`: * * ```c++ * 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_really_inline simdjson_result find_field(std::string_view key) noexcept; /** @overload simdjson_really_inline simdjson_result find_field(std::string_view key) noexcept; */ simdjson_really_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. * * It is the default, however, 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 wasn't there when they aren't). * * @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_really_inline simdjson_result find_field_unordered(std::string_view key) noexcept; /** @overload simdjson_really_inline simdjson_result find_field_unordered(std::string_view key) noexcept; */ simdjson_really_inline simdjson_result find_field_unordered(const char *key) noexcept; /** @overload simdjson_really_inline simdjson_result find_field_unordered(std::string_view key) noexcept; */ simdjson_really_inline simdjson_result operator[](std::string_view key) noexcept; /** @overload simdjson_really_inline simdjson_result find_field_unordered(std::string_view key) noexcept; */ simdjson_really_inline simdjson_result operator[](const char *key) noexcept; /** * Get the type of this JSON value. * * 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_really_inline simdjson_result type() 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 */ simdjson_really_inline std::string_view raw_json_token() noexcept; protected: /** * Create a value. */ simdjson_really_inline value(const value_iterator &iter) noexcept; /** * Skip this value, allowing iteration to continue. */ simdjson_really_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_really_inline value start(const value_iterator &iter) noexcept; /** * Resume a value. */ static simdjson_really_inline value resume(const value_iterator &iter) noexcept; /** * Get the object, starting or resuming it as necessary */ simdjson_really_inline simdjson_result start_or_resume_object() noexcept; // simdjson_really_inline void log_value(const char *type) const noexcept; // simdjson_really_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 struct simdjson_result; }; } // namespace ondemand } // namespace SIMDJSON_IMPLEMENTATION } // namespace simdjson namespace simdjson { template<> struct simdjson_result : public SIMDJSON_IMPLEMENTATION::implementation_simdjson_result_base { public: simdjson_really_inline simdjson_result(SIMDJSON_IMPLEMENTATION::ondemand::value &&value) noexcept; ///< @private simdjson_really_inline simdjson_result(error_code error) noexcept; ///< @private simdjson_really_inline simdjson_result() noexcept = default; simdjson_really_inline simdjson_result get_array() noexcept; simdjson_really_inline simdjson_result get_object() noexcept; simdjson_really_inline simdjson_result get_uint64() noexcept; simdjson_really_inline simdjson_result get_int64() noexcept; simdjson_really_inline simdjson_result get_double() noexcept; simdjson_really_inline simdjson_result get_string() noexcept; simdjson_really_inline simdjson_result get_raw_json_string() noexcept; simdjson_really_inline simdjson_result get_bool() noexcept; simdjson_really_inline bool is_null() noexcept; template simdjson_really_inline simdjson_result get() noexcept; template simdjson_really_inline error_code get(T &out) noexcept; #if SIMDJSON_EXCEPTIONS simdjson_really_inline operator SIMDJSON_IMPLEMENTATION::ondemand::array() noexcept(false); simdjson_really_inline operator SIMDJSON_IMPLEMENTATION::ondemand::object() noexcept(false); simdjson_really_inline operator uint64_t() noexcept(false); simdjson_really_inline operator int64_t() noexcept(false); simdjson_really_inline operator double() noexcept(false); simdjson_really_inline operator std::string_view() noexcept(false); simdjson_really_inline operator SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string() noexcept(false); simdjson_really_inline operator bool() noexcept(false); #endif simdjson_really_inline simdjson_result begin() & noexcept; simdjson_really_inline simdjson_result end() & noexcept; /** * Look up a field by name on an object (order-sensitive). * * 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 }`: * * ```c++ * 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_really_inline simdjson_result find_field(std::string_view key) noexcept; /** @overload simdjson_really_inline simdjson_result find_field(std::string_view key) noexcept; */ simdjson_really_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. * * It is the default, however, 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 wasn't there when they aren't). * * @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_really_inline simdjson_result find_field_unordered(std::string_view key) noexcept; /** @overload simdjson_really_inline simdjson_result find_field_unordered(std::string_view key) noexcept; */ simdjson_really_inline simdjson_result find_field_unordered(const char *key) noexcept; /** @overload simdjson_really_inline simdjson_result find_field_unordered(std::string_view key) noexcept; */ simdjson_really_inline simdjson_result operator[](std::string_view key) noexcept; /** @overload simdjson_really_inline simdjson_result find_field_unordered(std::string_view key) noexcept; */ simdjson_really_inline simdjson_result operator[](const char *key) noexcept; /** * Get the type of this JSON value. * * 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_really_inline simdjson_result type() noexcept; /** @copydoc simdjson_really_inline std::string_view value::raw_json_token() const noexcept */ simdjson_really_inline simdjson_result raw_json_token() noexcept; }; } // namespace simdjson