Merge pull request #640 from simdjson/jkeiser/simdjson-result

Use simdjson_result for all _result classes
This commit is contained in:
John Keiser 2020-03-28 13:36:54 -07:00 committed by GitHub
commit de001da35b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 359 additions and 185 deletions

View File

@ -59,12 +59,6 @@ public:
class parser; class parser;
class stream; class stream;
class element_result;
class element_result;
class array_result;
class object_result;
class stream_result;
/** /**
* Get the root element of this document as a JSON array. * Get the root element of this document as a JSON array.
*/ */
@ -129,7 +123,7 @@ namespace internal {
/** The index of this element on `doc.tape[]` */ /** The index of this element on `doc.tape[]` */
size_t json_index; size_t json_index;
friend class simdjson::document::key_value_pair; friend class document::key_value_pair;
template<typename T> template<typename T>
friend class simdjson::minify; friend class simdjson::minify;
}; };
@ -230,7 +224,7 @@ public:
* @return The array value, or: * @return The array value, or:
* - UNEXPECTED_TYPE if the JSON element is not an array * - UNEXPECTED_TYPE if the JSON element is not an array
*/ */
inline array_result as_array() const noexcept; inline simdjson_result<array> as_array() const noexcept;
/** /**
* Read this element as a JSON object (key/value pairs). * Read this element as a JSON object (key/value pairs).
@ -238,7 +232,7 @@ public:
* @return The object value, or: * @return The object value, or:
* - UNEXPECTED_TYPE if the JSON element is not an object * - UNEXPECTED_TYPE if the JSON element is not an object
*/ */
inline object_result as_object() const noexcept; inline simdjson_result<object> as_object() const noexcept;
#if SIMDJSON_EXCEPTIONS #if SIMDJSON_EXCEPTIONS
/** /**
@ -326,7 +320,7 @@ public:
* - INCORRECT_TYPE if a non-integer is used to access an array * - 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 * - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
*/ */
inline element_result operator[](const std::string_view &json_pointer) const noexcept; inline simdjson_result<element> operator[](const std::string_view &json_pointer) const noexcept;
/** /**
* Get the value associated with the given JSON pointer. * Get the value associated with the given JSON pointer.
@ -343,7 +337,7 @@ public:
* - INCORRECT_TYPE if a non-integer is used to access an array * - 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 * - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
*/ */
inline element_result operator[](const char *json_pointer) const noexcept; inline simdjson_result<element> operator[](const char *json_pointer) const noexcept;
/** /**
* Get the value associated with the given JSON pointer. * Get the value associated with the given JSON pointer.
@ -360,7 +354,7 @@ public:
* - INCORRECT_TYPE if a non-integer is used to access an array * - 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 * - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
*/ */
inline element_result at(const std::string_view &json_pointer) const noexcept; inline simdjson_result<element> at(const std::string_view &json_pointer) const noexcept;
/** /**
* Get the value at the given index. * Get the value at the given index.
@ -368,7 +362,7 @@ public:
* @return The value at the given index, or: * @return The value at the given index, or:
* - INDEX_OUT_OF_BOUNDS if the array index is larger than an array length * - INDEX_OUT_OF_BOUNDS if the array index is larger than an array length
*/ */
inline element_result at(size_t index) const noexcept; inline simdjson_result<element> at(size_t index) const noexcept;
/** /**
* Get the value associated with the given key. * Get the value associated with the given key.
@ -382,7 +376,7 @@ public:
* @return The value associated with this field, or: * @return The value associated with this field, or:
* - NO_SUCH_FIELD if the field does not exist in the object * - NO_SUCH_FIELD if the field does not exist in the object
*/ */
inline element_result at_key(const std::string_view &key) const noexcept; inline simdjson_result<element> at_key(const std::string_view &key) const noexcept;
/** /**
* Get the value associated with the given key in a case-insensitive manner. * Get the value associated with the given key in a case-insensitive manner.
@ -392,7 +386,7 @@ public:
* @return The value associated with this field, or: * @return The value associated with this field, or:
* - NO_SUCH_FIELD if the field does not exist in the object * - NO_SUCH_FIELD if the field does not exist in the object
*/ */
inline element_result at_key_case_insensitive(const std::string_view &key) const noexcept; inline simdjson_result<element> at_key_case_insensitive(const std::string_view &key) const noexcept;
/** @private for debugging. Prints out the root element. */ /** @private for debugging. Prints out the root element. */
inline bool dump_raw_tape(std::ostream &out) const noexcept; inline bool dump_raw_tape(std::ostream &out) const noexcept;
@ -400,9 +394,9 @@ public:
private: private:
really_inline element(const document *_doc, size_t _json_index) noexcept; really_inline element(const document *_doc, size_t _json_index) noexcept;
friend class document; friend class document;
friend class document::element_result; friend struct simdjson_result<document::element>;
template<typename T> template<typename T>
friend class minify; friend class simdjson::minify;
}; };
/** /**
@ -463,7 +457,7 @@ public:
* - INCORRECT_TYPE if a non-integer is used to access an array * - 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 * - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
*/ */
inline element_result operator[](const std::string_view &json_pointer) const noexcept; inline simdjson_result<element> operator[](const std::string_view &json_pointer) const noexcept;
/** /**
* Get the value associated with the given JSON pointer. * Get the value associated with the given JSON pointer.
@ -479,7 +473,7 @@ public:
* - INCORRECT_TYPE if a non-integer is used to access an array * - 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 * - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
*/ */
inline element_result operator[](const char *json_pointer) const noexcept; inline simdjson_result<element> operator[](const char *json_pointer) const noexcept;
/** /**
* Get the value associated with the given JSON pointer. * Get the value associated with the given JSON pointer.
@ -495,7 +489,7 @@ public:
* - INCORRECT_TYPE if a non-integer is used to access an array * - 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 * - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
*/ */
inline element_result at(const std::string_view &json_pointer) const noexcept; inline simdjson_result<element> at(const std::string_view &json_pointer) const noexcept;
/** /**
* Get the value at the given index. * Get the value at the given index.
@ -503,14 +497,14 @@ public:
* @return The value at the given index, or: * @return The value at the given index, or:
* - INDEX_OUT_OF_BOUNDS if the array index is larger than an array length * - INDEX_OUT_OF_BOUNDS if the array index is larger than an array length
*/ */
inline element_result at(size_t index) const noexcept; inline simdjson_result<element> at(size_t index) const noexcept;
private: private:
really_inline array(const document *_doc, size_t _json_index) noexcept; really_inline array(const document *_doc, size_t _json_index) noexcept;
friend class document::element; friend class element;
friend class document::element_result; friend struct simdjson_result<element>;
template<typename T> template<typename T>
friend class minify; friend class simdjson::minify;
}; };
/** /**
@ -553,7 +547,7 @@ public:
inline element value() const noexcept; inline element value() const noexcept;
private: private:
really_inline iterator(const document *_doc, size_t _json_index) noexcept; really_inline iterator(const document *_doc, size_t _json_index) noexcept;
friend class document::object; friend class object;
}; };
/** /**
@ -583,7 +577,7 @@ public:
* - INCORRECT_TYPE if a non-integer is used to access an array * - 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 * - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
*/ */
inline element_result operator[](const std::string_view &json_pointer) const noexcept; inline simdjson_result<element> operator[](const std::string_view &json_pointer) const noexcept;
/** /**
* Get the value associated with the given JSON pointer. * Get the value associated with the given JSON pointer.
@ -599,7 +593,7 @@ public:
* - INCORRECT_TYPE if a non-integer is used to access an array * - 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 * - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
*/ */
inline element_result operator[](const char *json_pointer) const noexcept; inline simdjson_result<element> operator[](const char *json_pointer) const noexcept;
/** /**
* Get the value associated with the given JSON pointer. * Get the value associated with the given JSON pointer.
@ -615,7 +609,7 @@ public:
* - INCORRECT_TYPE if a non-integer is used to access an array * - 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 * - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
*/ */
inline element_result at(const std::string_view &json_pointer) const noexcept; inline simdjson_result<element> at(const std::string_view &json_pointer) const noexcept;
/** /**
* Get the value associated with the given key. * Get the value associated with the given key.
@ -629,7 +623,7 @@ public:
* @return The value associated with this field, or: * @return The value associated with this field, or:
* - NO_SUCH_FIELD if the field does not exist in the object * - NO_SUCH_FIELD if the field does not exist in the object
*/ */
inline element_result at_key(const std::string_view &key) const noexcept; inline simdjson_result<element> at_key(const std::string_view &key) const noexcept;
/** /**
* Get the value associated with the given key in a case-insensitive manner. * Get the value associated with the given key in a case-insensitive manner.
@ -639,14 +633,14 @@ public:
* @return The value associated with this field, or: * @return The value associated with this field, or:
* - NO_SUCH_FIELD if the field does not exist in the object * - NO_SUCH_FIELD if the field does not exist in the object
*/ */
inline element_result at_key_case_insensitive(const std::string_view &key) const noexcept; inline simdjson_result<element> at_key_case_insensitive(const std::string_view &key) const noexcept;
private: private:
really_inline object(const document *_doc, size_t _json_index) noexcept; really_inline object(const document *_doc, size_t _json_index) noexcept;
friend class document::element; friend class element;
friend class document::element_result; friend struct simdjson_result<element>;
template<typename T> template<typename T>
friend class minify; friend class simdjson::minify;
}; };
/** /**
@ -659,15 +653,16 @@ public:
private: private:
really_inline key_value_pair(const std::string_view &_key, document::element _value) noexcept; really_inline key_value_pair(const std::string_view &_key, document::element _value) noexcept;
friend class document::object; friend class object;
}; };
/** The result of a JSON navigation that may fail. */ /** The result of a JSON navigation that may fail. */
class document::element_result : public simdjson_result<document::element> { template<>
struct simdjson_result<document::element> : public internal::simdjson_result_base<document::element> {
public: public:
really_inline element_result() noexcept; really_inline simdjson_result() noexcept;
really_inline element_result(element &&value) noexcept; really_inline simdjson_result(document::element &&value) noexcept;
really_inline element_result(error_code error) noexcept; really_inline simdjson_result(error_code error) noexcept;
/** Whether this is a JSON `null` */ /** Whether this is a JSON `null` */
inline simdjson_result<bool> is_null() const noexcept; inline simdjson_result<bool> is_null() const noexcept;
@ -677,15 +672,15 @@ public:
inline simdjson_result<uint64_t> as_uint64_t() const noexcept; inline simdjson_result<uint64_t> as_uint64_t() const noexcept;
inline simdjson_result<int64_t> as_int64_t() const noexcept; inline simdjson_result<int64_t> as_int64_t() const noexcept;
inline simdjson_result<double> as_double() const noexcept; inline simdjson_result<double> as_double() const noexcept;
inline array_result as_array() const noexcept; inline simdjson_result<document::array> as_array() const noexcept;
inline object_result as_object() const noexcept; inline simdjson_result<document::object> as_object() const noexcept;
inline element_result operator[](const std::string_view &json_pointer) const noexcept; inline simdjson_result<document::element> operator[](const std::string_view &json_pointer) const noexcept;
inline element_result operator[](const char *json_pointer) const noexcept; inline simdjson_result<document::element> operator[](const char *json_pointer) const noexcept;
inline element_result at(const std::string_view &json_pointer) const noexcept; inline simdjson_result<document::element> at(const std::string_view &json_pointer) const noexcept;
inline element_result at(size_t index) const noexcept; inline simdjson_result<document::element> at(size_t index) const noexcept;
inline element_result at_key(const std::string_view &key) const noexcept; inline simdjson_result<document::element> at_key(const std::string_view &key) const noexcept;
inline element_result at_key_case_insensitive(const std::string_view &key) const noexcept; inline simdjson_result<document::element> at_key_case_insensitive(const std::string_view &key) const noexcept;
#if SIMDJSON_EXCEPTIONS #if SIMDJSON_EXCEPTIONS
inline operator bool() const noexcept(false); inline operator bool() const noexcept(false);
@ -694,45 +689,47 @@ public:
inline operator uint64_t() const noexcept(false); inline operator uint64_t() const noexcept(false);
inline operator int64_t() const noexcept(false); inline operator int64_t() const noexcept(false);
inline operator double() const noexcept(false); inline operator double() const noexcept(false);
inline operator array() const noexcept(false); inline operator document::array() const noexcept(false);
inline operator object() const noexcept(false); inline operator document::object() const noexcept(false);
#endif // SIMDJSON_EXCEPTIONS #endif // SIMDJSON_EXCEPTIONS
}; };
/** The result of a JSON conversion that may fail. */ /** The result of a JSON conversion that may fail. */
class document::array_result : public simdjson_result<document::array> { template<>
struct simdjson_result<document::array> : public internal::simdjson_result_base<document::array> {
public: public:
really_inline array_result() noexcept; really_inline simdjson_result() noexcept;
really_inline array_result(array value) noexcept; really_inline simdjson_result(document::array value) noexcept;
really_inline array_result(error_code error) noexcept; really_inline simdjson_result(error_code error) noexcept;
inline element_result operator[](const std::string_view &json_pointer) const noexcept; inline simdjson_result<document::element> operator[](const std::string_view &json_pointer) const noexcept;
inline element_result operator[](const char *json_pointer) const noexcept; inline simdjson_result<document::element> operator[](const char *json_pointer) const noexcept;
inline element_result at(const std::string_view &json_pointer) const noexcept; inline simdjson_result<document::element> at(const std::string_view &json_pointer) const noexcept;
inline element_result at(size_t index) const noexcept; inline simdjson_result<document::element> at(size_t index) const noexcept;
#if SIMDJSON_EXCEPTIONS #if SIMDJSON_EXCEPTIONS
inline array::iterator begin() const noexcept(false); inline document::array::iterator begin() const noexcept(false);
inline array::iterator end() const noexcept(false); inline document::array::iterator end() const noexcept(false);
#endif // SIMDJSON_EXCEPTIONS #endif // SIMDJSON_EXCEPTIONS
}; };
/** The result of a JSON conversion that may fail. */ /** The result of a JSON conversion that may fail. */
class document::object_result : public simdjson_result<document::object> { template<>
struct simdjson_result<document::object> : public internal::simdjson_result_base<document::object> {
public: public:
really_inline object_result() noexcept; really_inline simdjson_result() noexcept;
really_inline object_result(object value) noexcept; really_inline simdjson_result(document::object value) noexcept;
really_inline object_result(error_code error) noexcept; really_inline simdjson_result(error_code error) noexcept;
inline element_result operator[](const std::string_view &json_pointer) const noexcept; inline simdjson_result<document::element> operator[](const std::string_view &json_pointer) const noexcept;
inline element_result operator[](const char *json_pointer) const noexcept; inline simdjson_result<document::element> operator[](const char *json_pointer) const noexcept;
inline element_result at(const std::string_view &json_pointer) const noexcept; inline simdjson_result<document::element> at(const std::string_view &json_pointer) const noexcept;
inline element_result at_key(const std::string_view &key) const noexcept; inline simdjson_result<document::element> at_key(const std::string_view &key) const noexcept;
inline element_result at_key_case_insensitive(const std::string_view &key) const noexcept; inline simdjson_result<document::element> at_key_case_insensitive(const std::string_view &key) const noexcept;
#if SIMDJSON_EXCEPTIONS #if SIMDJSON_EXCEPTIONS
inline object::iterator begin() const noexcept(false); inline document::object::iterator begin() const noexcept(false);
inline object::iterator end() const noexcept(false); inline document::object::iterator end() const noexcept(false);
#endif // SIMDJSON_EXCEPTIONS #endif // SIMDJSON_EXCEPTIONS
}; };
@ -804,7 +801,7 @@ public:
* - CAPACITY if the parser does not have enough capacity and len > max_capacity. * - CAPACITY if the parser does not have enough capacity and len > max_capacity.
* - other json errors if parsing fails. * - other json errors if parsing fails.
*/ */
inline element_result load(const std::string &path) noexcept; inline simdjson_result<element> load(const std::string &path) noexcept;
/** /**
* Load a file containing many JSON documents. * Load a file containing many JSON documents.
@ -898,7 +895,7 @@ public:
* - CAPACITY if the parser does not have enough capacity and len > max_capacity. * - CAPACITY if the parser does not have enough capacity and len > max_capacity.
* - other json errors if parsing fails. * - other json errors if parsing fails.
*/ */
inline element_result parse(const uint8_t *buf, size_t len, bool realloc_if_needed = true) noexcept; inline simdjson_result<element> parse(const uint8_t *buf, size_t len, bool realloc_if_needed = true) noexcept;
/** /**
* Parse a JSON document and return a temporary reference to it. * Parse a JSON document and return a temporary reference to it.
@ -935,7 +932,7 @@ public:
* - CAPACITY if the parser does not have enough capacity and len > max_capacity. * - CAPACITY if the parser does not have enough capacity and len > max_capacity.
* - other json errors if parsing fails. * - other json errors if parsing fails.
*/ */
really_inline element_result parse(const char *buf, size_t len, bool realloc_if_needed = true) noexcept; really_inline simdjson_result<element> parse(const char *buf, size_t len, bool realloc_if_needed = true) noexcept;
/** /**
* Parse a JSON document and return a temporary reference to it. * Parse a JSON document and return a temporary reference to it.
@ -970,7 +967,7 @@ public:
* - CAPACITY if the parser does not have enough capacity and len > max_capacity. * - CAPACITY if the parser does not have enough capacity and len > max_capacity.
* - other json errors if parsing fails. * - other json errors if parsing fails.
*/ */
really_inline element_result parse(const std::string &s) noexcept; really_inline simdjson_result<element> parse(const std::string &s) noexcept;
/** /**
* Parse a JSON document and return a temporary reference to it. * Parse a JSON document and return a temporary reference to it.
@ -995,10 +992,10 @@ public:
* - CAPACITY if the parser does not have enough capacity and len > max_capacity. * - CAPACITY if the parser does not have enough capacity and len > max_capacity.
* - other json errors if parsing fails. * - other json errors if parsing fails.
*/ */
really_inline element_result parse(const padded_string &s) noexcept; really_inline simdjson_result<element> parse(const padded_string &s) noexcept;
// We do not want to allow implicit conversion from C string to std::string. // We do not want to allow implicit conversion from C string to std::string.
really_inline element_result parse(const char *buf) noexcept = delete; really_inline simdjson_result<element> parse(const char *buf) noexcept = delete;
/** /**
* Parse a buffer containing many JSON documents. * Parse a buffer containing many JSON documents.
@ -1242,7 +1239,7 @@ public:
inline stream parse_many(const padded_string &s, size_t batch_size = DEFAULT_BATCH_SIZE) noexcept; inline stream parse_many(const padded_string &s, size_t batch_size = DEFAULT_BATCH_SIZE) noexcept;
// We do not want to allow implicit conversion from C string to std::string. // We do not want to allow implicit conversion from C string to std::string.
really_inline element_result parse_many(const char *buf, size_t batch_size = DEFAULT_BATCH_SIZE) noexcept = delete; really_inline simdjson_result<element> parse_many(const char *buf, size_t batch_size = DEFAULT_BATCH_SIZE) noexcept = delete;
/** /**
* The largest document this parser can automatically support. * The largest document this parser can automatically support.
@ -1448,8 +1445,8 @@ private:
// //
inline simdjson_result<size_t> read_file(const std::string &path) noexcept; inline simdjson_result<size_t> read_file(const std::string &path) noexcept;
friend class document::parser::Iterator; friend class parser::Iterator;
friend class document::stream; friend class stream;
}; // class parser }; // class parser
/** /**
@ -1547,7 +1544,7 @@ inline std::ostream& operator<<(std::ostream& out, const document::key_value_pai
* underlying output stream, that error will be propagated (simdjson_error will not be * underlying output stream, that error will be propagated (simdjson_error will not be
* thrown). * thrown).
*/ */
inline std::ostream& operator<<(std::ostream& out, const document::element_result &value) noexcept(false) { return out << minify(value); } inline std::ostream& operator<<(std::ostream& out, const simdjson_result<document::element> &value) noexcept(false) { return out << minify(value); }
/** /**
* Print JSON to an output stream. * Print JSON to an output stream.
* *
@ -1559,7 +1556,7 @@ inline std::ostream& operator<<(std::ostream& out, const document::element_resul
* underlying output stream, that error will be propagated (simdjson_error will not be * underlying output stream, that error will be propagated (simdjson_error will not be
* thrown). * thrown).
*/ */
inline std::ostream& operator<<(std::ostream& out, const document::array_result &value) noexcept(false) { return out << minify(value); } inline std::ostream& operator<<(std::ostream& out, const simdjson_result<document::array> &value) noexcept(false) { return out << minify(value); }
/** /**
* Print JSON to an output stream. * Print JSON to an output stream.
* *
@ -1571,7 +1568,7 @@ inline std::ostream& operator<<(std::ostream& out, const document::array_result
* underlying output stream, that error will be propagated (simdjson_error will not be * underlying output stream, that error will be propagated (simdjson_error will not be
* thrown). * thrown).
*/ */
inline std::ostream& operator<<(std::ostream& out, const document::object_result &value) noexcept(false) { return out << minify(value); } inline std::ostream& operator<<(std::ostream& out, const simdjson_result<document::object> &value) noexcept(false) { return out << minify(value); }
#endif #endif

View File

@ -24,7 +24,7 @@ public:
/** /**
* Get the current document (or error). * Get the current document (or error).
*/ */
really_inline element_result operator*() noexcept; really_inline simdjson_result<element> operator*() noexcept;
/** /**
* Advance to the next document. * Advance to the next document.
*/ */

View File

@ -74,29 +74,60 @@ private:
error_code _error; error_code _error;
}; };
namespace internal {
/** /**
* The result of a simd operation that could fail. * The result of a simdjson operation that could fail.
* *
* Gives the option of reading error codes, or throwing an exception by casting to the desired result. * Gives the option of reading error codes, or throwing an exception by casting to the desired result.
*
* This is a base class for implementations that want to add functions to the result type for
* chaining.
*
* Override like:
*
* struct simdjson_result<T> : public internal::simdjson_result_base<T> {
* simdjson_result() noexcept : internal::simdjson_result_base<T>() {}
* simdjson_result(error_code error) noexcept : internal::simdjson_result_base<T>(error) {}
* simdjson_result(T &&value) noexcept : internal::simdjson_result_base<T>(std::forward(value)) {}
* simdjson_result(T &&value, error_code error) noexcept : internal::simdjson_result_base<T>(value, error) {}
* // Your extra methods here
* }
*
* Then any method returning simdjson_result<T> will be chainable with your methods.
*/ */
template<typename T> template<typename T>
struct simdjson_result : public std::pair<T, error_code> { struct simdjson_result_base : public std::pair<T, error_code> {
/**
* Create a new empty result with error = UNINITIALIZED.
*/
really_inline simdjson_result_base() noexcept;
/**
* Create a new error result.
*/
really_inline simdjson_result_base(error_code error) noexcept;
/**
* Create a new successful result.
*/
really_inline simdjson_result_base(T &&value) noexcept;
/**
* Create a new result with both things (use if you don't want to branch when creating the result).
*/
really_inline simdjson_result_base(T &&value, error_code error) noexcept;
/** /**
* Move the value and the error to the provided variables. * Move the value and the error to the provided variables.
*/ */
void tie(T& t, error_code & e) && noexcept { really_inline void tie(T &value, error_code &error) && noexcept;
// on the clang compiler that comes with current macOS (Apple clang version 11.0.0),
// tie(width, error) = size["w"].as_uint64_t();
// fails with "error: no viable overloaded '='""
t = std::forward<simdjson_result<T>>(*this).first;
e = this->second;
}
/** /**
* The error. * The error.
*/ */
error_code error() const { return this->second; } really_inline error_code error() const noexcept;
#if SIMDJSON_EXCEPTIONS #if SIMDJSON_EXCEPTIONS
@ -105,52 +136,86 @@ struct simdjson_result : public std::pair<T, error_code> {
* *
* @throw simdjson_error if there was an error. * @throw simdjson_error if there was an error.
*/ */
T& get() noexcept(false) { really_inline T& get() noexcept(false);
if (error()) { throw simdjson_error(error()); }
return this->first;
};
/** /**
* The value of the function. * The value of the function.
* *
* @throw simdjson_error if there was an error. * @throw simdjson_error if there was an error.
*/ */
T&& take() && { really_inline T&& take() && noexcept(false);
if (error()) { throw simdjson_error(error()); }
return std::forward<T>(this->first);
};
/** /**
* Cast to the value (will throw on error). * Cast to the value (will throw on error).
* *
* @throw simdjson_error if there was an error. * @throw simdjson_error if there was an error.
*/ */
operator T&&() && { really_inline operator T&&() && noexcept(false);
return std::forward<simdjson_result<T>>(*this).take();
}
#endif // SIMDJSON_EXCEPTIONS #endif // SIMDJSON_EXCEPTIONS
}; // struct simdjson_result_base
} // namespace internal
/**
* The result of a simdjson operation that could fail.
*
* Gives the option of reading error codes, or throwing an exception by casting to the desired result.
*/
template<typename T>
struct simdjson_result : public internal::simdjson_result_base<T> {
/** /**
* Create a new empty result with error = UNINITIALIZED. * Create a new empty result with error = UNINITIALIZED.
*/ */
simdjson_result() noexcept : simdjson_result(UNINITIALIZED) {} really_inline simdjson_result() noexcept;
/** /**
* Create a new error result. * Create a new error result.
*/ */
simdjson_result(error_code error) noexcept : std::pair<T, error_code>(T{}, error) {} really_inline simdjson_result(T &&value) noexcept;
/** /**
* Create a new successful result. * Create a new successful result.
*/ */
simdjson_result(T &&value) noexcept : std::pair<T, error_code>(std::forward<T>(value), SUCCESS) {} really_inline simdjson_result(error_code error_code) noexcept;
/** /**
* Create a new result with both things (use if you don't want to branch when creating the result). * Create a new result with both things (use if you don't want to branch when creating the result).
*/ */
simdjson_result(T &&value, error_code error) noexcept : std::pair<T, error_code>(std::forward<T>(value), error) {} really_inline simdjson_result(T &&value, error_code error) noexcept;
};
/**
* Move the value and the error to the provided variables.
*/
really_inline void tie(T& t, error_code & e) && noexcept;
/**
* The error.
*/
really_inline error_code error() const noexcept;
#if SIMDJSON_EXCEPTIONS
/**
* The value of the function.
*
* @throw simdjson_error if there was an error.
*/
really_inline T& get() noexcept(false);
/**
* The value of the function.
*
* @throw simdjson_error if there was an error.
*/
really_inline T&& take() && noexcept(false);
/**
* Cast to the value (will throw on error).
*
* @throw simdjson_error if there was an error.
*/
really_inline operator T&&() && noexcept(false);
#endif // SIMDJSON_EXCEPTIONS
}; // struct simdjson_result
/** /**
* @deprecated This is an alias and will be removed, use error_code instead * @deprecated This is an alias and will be removed, use error_code instead

View File

@ -10,178 +10,188 @@
#include "simdjson/internal/jsonformatutils.h" #include "simdjson/internal/jsonformatutils.h"
#include <iostream> #include <iostream>
#include <climits> #include <climits>
#include <cctype>
namespace simdjson { namespace simdjson {
// //
// element_result inline implementation // simdjson_result<document::element> inline implementation
// //
really_inline document::element_result::element_result() noexcept : simdjson_result<element>() {} really_inline simdjson_result<document::element>::simdjson_result() noexcept
really_inline document::element_result::element_result(element &&value) noexcept : simdjson_result<element>((element&&)value) {} : internal::simdjson_result_base<document::element>() {}
really_inline document::element_result::element_result(error_code error) noexcept : simdjson_result<element>(error) {} really_inline simdjson_result<document::element>::simdjson_result(document::element &&value) noexcept
inline simdjson_result<bool> document::element_result::is_null() const noexcept { : internal::simdjson_result_base<document::element>(std::forward<document::element>(value)) {}
really_inline simdjson_result<document::element>::simdjson_result(error_code error) noexcept
: internal::simdjson_result_base<document::element>(error) {}
inline simdjson_result<bool> simdjson_result<document::element>::is_null() const noexcept {
if (error()) { return error(); } if (error()) { return error(); }
return first.is_null(); return first.is_null();
} }
inline simdjson_result<bool> document::element_result::as_bool() const noexcept { inline simdjson_result<bool> simdjson_result<document::element>::as_bool() const noexcept {
if (error()) { return error(); } if (error()) { return error(); }
return first.as_bool(); return first.as_bool();
} }
inline simdjson_result<const char*> document::element_result::as_c_str() const noexcept { inline simdjson_result<const char*> simdjson_result<document::element>::as_c_str() const noexcept {
if (error()) { return error(); } if (error()) { return error(); }
return first.as_c_str(); return first.as_c_str();
} }
inline simdjson_result<std::string_view> document::element_result::as_string() const noexcept { inline simdjson_result<std::string_view> simdjson_result<document::element>::as_string() const noexcept {
if (error()) { return error(); } if (error()) { return error(); }
return first.as_string(); return first.as_string();
} }
inline simdjson_result<uint64_t> document::element_result::as_uint64_t() const noexcept { inline simdjson_result<uint64_t> simdjson_result<document::element>::as_uint64_t() const noexcept {
if (error()) { return error(); } if (error()) { return error(); }
return first.as_uint64_t(); return first.as_uint64_t();
} }
inline simdjson_result<int64_t> document::element_result::as_int64_t() const noexcept { inline simdjson_result<int64_t> simdjson_result<document::element>::as_int64_t() const noexcept {
if (error()) { return error(); } if (error()) { return error(); }
return first.as_int64_t(); return first.as_int64_t();
} }
inline simdjson_result<double> document::element_result::as_double() const noexcept { inline simdjson_result<double> simdjson_result<document::element>::as_double() const noexcept {
if (error()) { return error(); } if (error()) { return error(); }
return first.as_double(); return first.as_double();
} }
inline document::array_result document::element_result::as_array() const noexcept { inline simdjson_result<document::array> simdjson_result<document::element>::as_array() const noexcept {
if (error()) { return error(); } if (error()) { return error(); }
return first.as_array(); return first.as_array();
} }
inline document::object_result document::element_result::as_object() const noexcept { inline simdjson_result<document::object> simdjson_result<document::element>::as_object() const noexcept {
if (error()) { return error(); } if (error()) { return error(); }
return first.as_object(); return first.as_object();
} }
inline document::element_result document::element_result::operator[](const std::string_view &json_pointer) const noexcept { inline simdjson_result<document::element> simdjson_result<document::element>::operator[](const std::string_view &json_pointer) const noexcept {
if (error()) { return *this; } if (error()) { return *this; }
return first[json_pointer]; return first[json_pointer];
} }
inline document::element_result document::element_result::operator[](const char *json_pointer) const noexcept { inline simdjson_result<document::element> simdjson_result<document::element>::operator[](const char *json_pointer) const noexcept {
if (error()) { return *this; } if (error()) { return *this; }
return first[json_pointer]; return first[json_pointer];
} }
inline document::element_result document::element_result::at(const std::string_view &json_pointer) const noexcept { inline simdjson_result<document::element> simdjson_result<document::element>::at(const std::string_view &json_pointer) const noexcept {
if (error()) { return *this; } if (error()) { return *this; }
return first.at(json_pointer); return first.at(json_pointer);
} }
inline document::element_result document::element_result::at(size_t index) const noexcept { inline simdjson_result<document::element> simdjson_result<document::element>::at(size_t index) const noexcept {
if (error()) { return *this; } if (error()) { return *this; }
return first.at(index); return first.at(index);
} }
inline document::element_result document::element_result::at_key(const std::string_view &key) const noexcept { inline simdjson_result<document::element> simdjson_result<document::element>::at_key(const std::string_view &key) const noexcept {
if (error()) { return *this; } if (error()) { return *this; }
return first.at_key(key); return first.at_key(key);
} }
inline document::element_result document::element_result::at_key_case_insensitive(const std::string_view &key) const noexcept { inline simdjson_result<document::element> simdjson_result<document::element>::at_key_case_insensitive(const std::string_view &key) const noexcept {
if (error()) { return *this; } if (error()) { return *this; }
return first.at_key_case_insensitive(key); return first.at_key_case_insensitive(key);
} }
#if SIMDJSON_EXCEPTIONS #if SIMDJSON_EXCEPTIONS
inline document::element_result::operator bool() const noexcept(false) { inline simdjson_result<document::element>::operator bool() const noexcept(false) {
return as_bool(); return as_bool();
} }
inline document::element_result::operator const char *() const noexcept(false) { inline simdjson_result<document::element>::operator const char *() const noexcept(false) {
return as_c_str(); return as_c_str();
} }
inline document::element_result::operator std::string_view() const noexcept(false) { inline simdjson_result<document::element>::operator std::string_view() const noexcept(false) {
return as_string(); return as_string();
} }
inline document::element_result::operator uint64_t() const noexcept(false) { inline simdjson_result<document::element>::operator uint64_t() const noexcept(false) {
return as_uint64_t(); return as_uint64_t();
} }
inline document::element_result::operator int64_t() const noexcept(false) { inline simdjson_result<document::element>::operator int64_t() const noexcept(false) {
return as_int64_t(); return as_int64_t();
} }
inline document::element_result::operator double() const noexcept(false) { inline simdjson_result<document::element>::operator double() const noexcept(false) {
return as_double(); return as_double();
} }
inline document::element_result::operator document::array() const noexcept(false) { inline simdjson_result<document::element>::operator document::array() const noexcept(false) {
return as_array(); return as_array();
} }
inline document::element_result::operator document::object() const noexcept(false) { inline simdjson_result<document::element>::operator document::object() const noexcept(false) {
return as_object(); return as_object();
} }
#endif #endif
// //
// array_result inline implementation // simdjson_result<document::array> inline implementation
// //
really_inline document::array_result::array_result() noexcept : simdjson_result<array>() {} really_inline simdjson_result<document::array>::simdjson_result() noexcept
really_inline document::array_result::array_result(array value) noexcept : simdjson_result<array>((array&&)value) {} : internal::simdjson_result_base<document::array>() {}
really_inline document::array_result::array_result(error_code error) noexcept : simdjson_result<array>(error) {} really_inline simdjson_result<document::array>::simdjson_result(document::array value) noexcept
: internal::simdjson_result_base<document::array>(std::forward<document::array>(value)) {}
really_inline simdjson_result<document::array>::simdjson_result(error_code error) noexcept
: internal::simdjson_result_base<document::array>(error) {}
#if SIMDJSON_EXCEPTIONS #if SIMDJSON_EXCEPTIONS
inline document::array::iterator document::array_result::begin() const noexcept(false) { inline document::array::iterator simdjson_result<document::array>::begin() const noexcept(false) {
if (error()) { throw simdjson_error(error()); } if (error()) { throw simdjson_error(error()); }
return first.begin(); return first.begin();
} }
inline document::array::iterator document::array_result::end() const noexcept(false) { inline document::array::iterator simdjson_result<document::array>::end() const noexcept(false) {
if (error()) { throw simdjson_error(error()); } if (error()) { throw simdjson_error(error()); }
return first.end(); return first.end();
} }
#endif // SIMDJSON_EXCEPTIONS #endif // SIMDJSON_EXCEPTIONS
inline document::element_result document::array_result::operator[](const std::string_view &json_pointer) const noexcept { inline simdjson_result<document::element> simdjson_result<document::array>::operator[](const std::string_view &json_pointer) const noexcept {
if (error()) { return error(); } if (error()) { return error(); }
return first.at(json_pointer); return first.at(json_pointer);
} }
inline document::element_result document::array_result::operator[](const char *json_pointer) const noexcept { inline simdjson_result<document::element> simdjson_result<document::array>::operator[](const char *json_pointer) const noexcept {
if (error()) { return error(); } if (error()) { return error(); }
return first.at(json_pointer); return first.at(json_pointer);
} }
inline document::element_result document::array_result::at(const std::string_view &json_pointer) const noexcept { inline simdjson_result<document::element> simdjson_result<document::array>::at(const std::string_view &json_pointer) const noexcept {
if (error()) { return error(); } if (error()) { return error(); }
return first.at(json_pointer); return first.at(json_pointer);
} }
inline document::element_result document::array_result::at(size_t index) const noexcept { inline simdjson_result<document::element> simdjson_result<document::array>::at(size_t index) const noexcept {
if (error()) { return error(); } if (error()) { return error(); }
return first.at(index); return first.at(index);
} }
// //
// object_result inline implementation // simdjson_result<document::object> inline implementation
// //
really_inline document::object_result::object_result() noexcept : simdjson_result<object>() {} really_inline simdjson_result<document::object>::simdjson_result() noexcept
really_inline document::object_result::object_result(object value) noexcept : simdjson_result<object>((object&&)value) {} : internal::simdjson_result_base<document::object>() {}
really_inline document::object_result::object_result(error_code error) noexcept : simdjson_result<object>(error) {} really_inline simdjson_result<document::object>::simdjson_result(document::object value) noexcept
: internal::simdjson_result_base<document::object>(std::forward<document::object>(value)) {}
really_inline simdjson_result<document::object>::simdjson_result(error_code error) noexcept
: internal::simdjson_result_base<document::object>(error) {}
inline document::element_result document::object_result::operator[](const std::string_view &json_pointer) const noexcept { inline simdjson_result<document::element> simdjson_result<document::object>::operator[](const std::string_view &json_pointer) const noexcept {
if (error()) { return error(); } if (error()) { return error(); }
return first[json_pointer]; return first[json_pointer];
} }
inline document::element_result document::object_result::operator[](const char *json_pointer) const noexcept { inline simdjson_result<document::element> simdjson_result<document::object>::operator[](const char *json_pointer) const noexcept {
if (error()) { return error(); } if (error()) { return error(); }
return first[json_pointer]; return first[json_pointer];
} }
inline document::element_result document::object_result::at(const std::string_view &json_pointer) const noexcept { inline simdjson_result<document::element> simdjson_result<document::object>::at(const std::string_view &json_pointer) const noexcept {
if (error()) { return error(); } if (error()) { return error(); }
return first.at(json_pointer); return first.at(json_pointer);
} }
inline document::element_result document::object_result::at_key(const std::string_view &key) const noexcept { inline simdjson_result<document::element> simdjson_result<document::object>::at_key(const std::string_view &key) const noexcept {
if (error()) { return error(); } if (error()) { return error(); }
return first.at_key(key); return first.at_key(key);
} }
inline document::element_result document::object_result::at_key_case_insensitive(const std::string_view &key) const noexcept { inline simdjson_result<document::element> simdjson_result<document::object>::at_key_case_insensitive(const std::string_view &key) const noexcept {
if (error()) { return error(); } if (error()) { return error(); }
return first.at_key_case_insensitive(key); return first.at_key_case_insensitive(key);
} }
#if SIMDJSON_EXCEPTIONS #if SIMDJSON_EXCEPTIONS
inline document::object::iterator document::object_result::begin() const noexcept(false) { inline document::object::iterator simdjson_result<document::object>::begin() const noexcept(false) {
if (error()) { throw simdjson_error(error()); } if (error()) { throw simdjson_error(error()); }
return first.begin(); return first.begin();
} }
inline document::object::iterator document::object_result::end() const noexcept(false) { inline document::object::iterator simdjson_result<document::object>::end() const noexcept(false) {
if (error()) { throw simdjson_error(error()); } if (error()) { throw simdjson_error(error()); }
return first.end(); return first.end();
} }
@ -369,7 +379,7 @@ inline simdjson_result<size_t> document::parser::read_file(const std::string &pa
return bytes_read; return bytes_read;
} }
inline document::element_result document::parser::load(const std::string &path) noexcept { inline simdjson_result<document::element> document::parser::load(const std::string &path) noexcept {
auto [len, code] = read_file(path); auto [len, code] = read_file(path);
if (code) { return code; } if (code) { return code; }
@ -381,7 +391,7 @@ inline document::stream document::parser::load_many(const std::string &path, siz
return stream(*this, (const uint8_t*)loaded_bytes.get(), len, batch_size, code); return stream(*this, (const uint8_t*)loaded_bytes.get(), len, batch_size, code);
} }
inline document::element_result document::parser::parse(const uint8_t *buf, size_t len, bool realloc_if_needed) noexcept { inline simdjson_result<document::element> document::parser::parse(const uint8_t *buf, size_t len, bool realloc_if_needed) noexcept {
error_code code = ensure_capacity(len); error_code code = ensure_capacity(len);
if (code) { return code; } if (code) { return code; }
@ -399,18 +409,18 @@ inline document::element_result document::parser::parse(const uint8_t *buf, size
} }
if (code) { return code; } if (code) { return code; }
// We're indicating validity via the element_result, so set the parse state back to invalid // We're indicating validity via the simdjson_result<element>, so set the parse state back to invalid
valid = false; valid = false;
error = UNINITIALIZED; error = UNINITIALIZED;
return doc.root(); return doc.root();
} }
really_inline document::element_result document::parser::parse(const char *buf, size_t len, bool realloc_if_needed) noexcept { really_inline simdjson_result<document::element> document::parser::parse(const char *buf, size_t len, bool realloc_if_needed) noexcept {
return parse((const uint8_t *)buf, len, realloc_if_needed); return parse((const uint8_t *)buf, len, realloc_if_needed);
} }
really_inline document::element_result document::parser::parse(const std::string &s) noexcept { really_inline simdjson_result<document::element> document::parser::parse(const std::string &s) noexcept {
return parse(s.data(), s.length(), s.capacity() - s.length() < SIMDJSON_PADDING); return parse(s.data(), s.length(), s.capacity() - s.length() < SIMDJSON_PADDING);
} }
really_inline document::element_result document::parser::parse(const padded_string &s) noexcept { really_inline simdjson_result<document::element> document::parser::parse(const padded_string &s) noexcept {
return parse(s.data(), s.length(), false); return parse(s.data(), s.length(), false);
} }
@ -587,7 +597,7 @@ inline document::array::iterator document::array::end() const noexcept {
return iterator(doc, after_element() - 1); return iterator(doc, after_element() - 1);
} }
inline document::element_result document::array::at(const std::string_view &json_pointer) const noexcept { inline simdjson_result<document::element> document::array::at(const std::string_view &json_pointer) const noexcept {
// - means "the append position" or "the element after the end of the array" // - means "the append position" or "the element after the end of the array"
// We don't support this, because we're returning a real element, not a position. // We don't support this, because we're returning a real element, not a position.
if (json_pointer == "-") { return INDEX_OUT_OF_BOUNDS; } if (json_pointer == "-") { return INDEX_OUT_OF_BOUNDS; }
@ -616,7 +626,7 @@ inline document::element_result document::array::at(const std::string_view &json
} }
return child; return child;
} }
inline document::element_result document::array::at(size_t index) const noexcept { inline simdjson_result<document::element> document::array::at(size_t index) const noexcept {
size_t i=0; size_t i=0;
for (auto element : *this) { for (auto element : *this) {
if (i == index) { return element; } if (i == index) { return element; }
@ -651,18 +661,18 @@ inline document::object::iterator document::object::end() const noexcept {
return iterator(doc, after_element() - 1); return iterator(doc, after_element() - 1);
} }
inline document::element_result document::object::operator[](const std::string_view &json_pointer) const noexcept { inline simdjson_result<document::element> document::object::operator[](const std::string_view &json_pointer) const noexcept {
return at(json_pointer); return at(json_pointer);
} }
inline document::element_result document::object::operator[](const char *json_pointer) const noexcept { inline simdjson_result<document::element> document::object::operator[](const char *json_pointer) const noexcept {
return at(json_pointer); return at(json_pointer);
} }
inline document::element_result document::object::at(const std::string_view &json_pointer) const noexcept { inline simdjson_result<document::element> document::object::at(const std::string_view &json_pointer) const noexcept {
size_t slash = json_pointer.find('/'); size_t slash = json_pointer.find('/');
std::string_view key = json_pointer.substr(0, slash); std::string_view key = json_pointer.substr(0, slash);
// Grab the child with the given key // Grab the child with the given key
document::element_result child; simdjson_result<document::element> child;
// If there is an escape character in the key, unescape it and then get the child. // If there is an escape character in the key, unescape it and then get the child.
size_t escape = key.find('~'); size_t escape = key.find('~');
@ -694,7 +704,7 @@ inline document::element_result document::object::at(const std::string_view &jso
return child; return child;
} }
inline document::element_result document::object::at_key(const std::string_view &key) const noexcept { inline simdjson_result<document::element> document::object::at_key(const std::string_view &key) const noexcept {
iterator end_field = end(); iterator end_field = end();
for (iterator field = begin(); field != end_field; ++field) { for (iterator field = begin(); field != end_field; ++field) {
if (key == field.key()) { if (key == field.key()) {
@ -706,7 +716,7 @@ inline document::element_result document::object::at_key(const std::string_view
// In case you wonder why we need this, please see // In case you wonder why we need this, please see
// https://github.com/simdjson/simdjson/issues/323 // https://github.com/simdjson/simdjson/issues/323
// People do seek keys in a case-insensitive manner. // People do seek keys in a case-insensitive manner.
inline document::element_result document::object::at_key_case_insensitive(const std::string_view &key) const noexcept { inline simdjson_result<document::element> document::object::at_key_case_insensitive(const std::string_view &key) const noexcept {
iterator end_field = end(); iterator end_field = end();
for (iterator field = begin(); field != end_field; ++field) { for (iterator field = begin(); field != end_field; ++field) {
auto field_key = field.key(); auto field_key = field.key();
@ -881,7 +891,7 @@ inline simdjson_result<double> document::element::as_double() const noexcept {
return INCORRECT_TYPE; return INCORRECT_TYPE;
} }
} }
inline document::array_result document::element::as_array() const noexcept { inline simdjson_result<document::array> document::element::as_array() const noexcept {
switch (type()) { switch (type()) {
case internal::tape_type::START_ARRAY: case internal::tape_type::START_ARRAY:
return array(doc, json_index); return array(doc, json_index);
@ -889,7 +899,7 @@ inline document::array_result document::element::as_array() const noexcept {
return INCORRECT_TYPE; return INCORRECT_TYPE;
} }
} }
inline document::object_result document::element::as_object() const noexcept { inline simdjson_result<document::object> document::element::as_object() const noexcept {
switch (type()) { switch (type()) {
case internal::tape_type::START_OBJECT: case internal::tape_type::START_OBJECT:
return object(doc, json_index); return object(doc, json_index);
@ -897,13 +907,13 @@ inline document::object_result document::element::as_object() const noexcept {
return INCORRECT_TYPE; return INCORRECT_TYPE;
} }
} }
inline document::element_result document::element::operator[](const std::string_view &json_pointer) const noexcept { inline simdjson_result<document::element> document::element::operator[](const std::string_view &json_pointer) const noexcept {
return at(json_pointer); return at(json_pointer);
} }
inline document::element_result document::element::operator[](const char *json_pointer) const noexcept { inline simdjson_result<document::element> document::element::operator[](const char *json_pointer) const noexcept {
return at(json_pointer); return at(json_pointer);
} }
inline document::element_result document::element::at(const std::string_view &json_pointer) const noexcept { inline simdjson_result<document::element> document::element::at(const std::string_view &json_pointer) const noexcept {
switch (type()) { switch (type()) {
case internal::tape_type::START_OBJECT: case internal::tape_type::START_OBJECT:
return object(doc, json_index).at(json_pointer); return object(doc, json_index).at(json_pointer);
@ -913,13 +923,13 @@ inline document::element_result document::element::at(const std::string_view &js
return INCORRECT_TYPE; return INCORRECT_TYPE;
} }
} }
inline document::element_result document::element::at(size_t index) const noexcept { inline simdjson_result<document::element> document::element::at(size_t index) const noexcept {
return as_array().at(index); return as_array().at(index);
} }
inline document::element_result document::element::at_key(const std::string_view &key) const noexcept { inline simdjson_result<document::element> document::element::at_key(const std::string_view &key) const noexcept {
return as_object().at_key(key); return as_object().at_key(key);
} }
inline document::element_result document::element::at_key_case_insensitive(const std::string_view &key) const noexcept { inline simdjson_result<document::element> document::element::at_key_case_insensitive(const std::string_view &key) const noexcept {
return as_object().at_key_case_insensitive(key); return as_object().at_key_case_insensitive(key);
} }
@ -1088,17 +1098,17 @@ inline std::ostream& minify<document::key_value_pair>::print(std::ostream& out)
#if SIMDJSON_EXCEPTIONS #if SIMDJSON_EXCEPTIONS
template<> template<>
inline std::ostream& minify<document::element_result>::print(std::ostream& out) { inline std::ostream& minify<simdjson_result<document::element>>::print(std::ostream& out) {
if (value.error()) { throw simdjson_error(value.error()); } if (value.error()) { throw simdjson_error(value.error()); }
return out << minify<document::element>(value.first); return out << minify<document::element>(value.first);
} }
template<> template<>
inline std::ostream& minify<document::array_result>::print(std::ostream& out) { inline std::ostream& minify<simdjson_result<document::array>>::print(std::ostream& out) {
if (value.error()) { throw simdjson_error(value.error()); } if (value.error()) { throw simdjson_error(value.error()); }
return out << minify<document::array>(value.first); return out << minify<document::array>(value.first);
} }
template<> template<>
inline std::ostream& minify<document::object_result>::print(std::ostream& out) { inline std::ostream& minify<simdjson_result<document::object>>::print(std::ostream& out) {
if (value.error()) { throw simdjson_error(value.error()); } if (value.error()) { throw simdjson_error(value.error()); }
return out << minify<document::object>(value.first); return out << minify<document::object>(value.first);
} }

View File

@ -127,7 +127,7 @@ really_inline document::stream::iterator::iterator(stream& stream, bool _is_end)
: _stream{stream}, finished{_is_end} { : _stream{stream}, finished{_is_end} {
} }
really_inline document::element_result document::stream::iterator::operator*() noexcept { really_inline simdjson_result<document::element> document::stream::iterator::operator*() noexcept {
error_code error = _stream.error == SUCCESS_AND_HAS_MORE ? SUCCESS : _stream.error; error_code error = _stream.error == SUCCESS_AND_HAS_MORE ? SUCCESS : _stream.error;
if (error) { return error; } if (error) { return error; }
return _stream.parser.doc.root(); return _stream.parser.doc.root();

View File

@ -58,6 +58,108 @@ inline std::ostream& operator<<(std::ostream& out, error_code error) noexcept {
return out << error_message(error); return out << error_message(error);
} }
namespace internal {
//
// internal::simdjson_result_base<T> inline implementation
//
template<typename T>
really_inline void simdjson_result_base<T>::tie(T &value, error_code &error) && noexcept {
// on the clang compiler that comes with current macOS (Apple clang version 11.0.0),
// tie(width, error) = size["w"].get<uint64_t>();
// fails with "error: no viable overloaded '='""
value = std::forward<simdjson_result_base<T>>(*this).first;
error = this->second;
}
template<typename T>
really_inline error_code simdjson_result_base<T>::error() const noexcept {
return this->second;
}
#if SIMDJSON_EXCEPTIONS
template<typename T>
really_inline T& simdjson_result_base<T>::get() noexcept(false) {
if (error()) { throw simdjson_error(error()); }
return this->first;
};
template<typename T>
really_inline T&& simdjson_result_base<T>::take() && noexcept(false) {
if (error()) { throw simdjson_error(error()); }
return std::forward<T>(this->first);
};
template<typename T>
really_inline simdjson_result_base<T>::operator T&&() && noexcept(false) {
return std::forward<simdjson_result_base<T>>(*this).take();
}
#endif // SIMDJSON_EXCEPTIONS
template<typename T>
really_inline simdjson_result_base<T>::simdjson_result_base(T &&value, error_code error) noexcept
: std::pair<T, error_code>(std::forward<T>(value), error) {}
template<typename T>
really_inline simdjson_result_base<T>::simdjson_result_base(error_code error) noexcept
: simdjson_result_base(T{}, error) {}
template<typename T>
really_inline simdjson_result_base<T>::simdjson_result_base(T &&value) noexcept
: simdjson_result_base(std::forward<T>(value), SUCCESS) {}
template<typename T>
really_inline simdjson_result_base<T>::simdjson_result_base() noexcept
: simdjson_result_base(T{}, UNINITIALIZED) {}
} // namespace internal
///
/// simdjson_result<T> inline implementation
///
template<typename T>
really_inline void simdjson_result<T>::tie(T &value, error_code &error) && noexcept {
std::forward<internal::simdjson_result_base<T>>(*this).tie(value, error);
}
template<typename T>
really_inline error_code simdjson_result<T>::error() const noexcept {
return internal::simdjson_result_base<T>::error();
}
#if SIMDJSON_EXCEPTIONS
template<typename T>
really_inline T& simdjson_result<T>::get() noexcept(false) {
return internal::simdjson_result_base<T>::get();
}
template<typename T>
really_inline T&& simdjson_result<T>::take() && noexcept(false) {
return std::forward<internal::simdjson_result_base<T>>(*this).take();
}
template<typename T>
really_inline simdjson_result<T>::operator T&&() && noexcept(false) {
return std::forward<internal::simdjson_result_base<T>>(*this).take();
}
#endif // SIMDJSON_EXCEPTIONS
template<typename T>
really_inline simdjson_result<T>::simdjson_result(T &&value, error_code error) noexcept
: internal::simdjson_result_base<T>(std::forward<T>(value), error) {}
template<typename T>
really_inline simdjson_result<T>::simdjson_result(error_code error) noexcept
: internal::simdjson_result_base<T>(error) {}
template<typename T>
really_inline simdjson_result<T>::simdjson_result(T &&value) noexcept
: internal::simdjson_result_base<T>(std::forward<T>(value)) {}
template<typename T>
really_inline simdjson_result<T>::simdjson_result() noexcept
: internal::simdjson_result_base<T>() {}
} // namespace simdjson } // namespace simdjson
#endif // SIMDJSON_INLINE_ERROR_H #endif // SIMDJSON_INLINE_ERROR_H