From 836e1fc330e14ac8d0448a8e59a0be40c39c0c23 Mon Sep 17 00:00:00 2001 From: John Keiser Date: Sat, 28 Mar 2020 09:38:25 -0700 Subject: [PATCH] Use simdjson_result for all _result classes --- include/simdjson/document.h | 159 +++++++++++----------- include/simdjson/document_stream.h | 2 +- include/simdjson/error.h | 123 +++++++++++++---- include/simdjson/inline/document.h | 156 +++++++++++---------- include/simdjson/inline/document_stream.h | 2 +- include/simdjson/inline/error.h | 102 ++++++++++++++ 6 files changed, 359 insertions(+), 185 deletions(-) diff --git a/include/simdjson/document.h b/include/simdjson/document.h index 1b77bb95..814dc218 100644 --- a/include/simdjson/document.h +++ b/include/simdjson/document.h @@ -59,12 +59,6 @@ public: class parser; 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. */ @@ -129,7 +123,7 @@ namespace internal { /** The index of this element on `doc.tape[]` */ size_t json_index; - friend class simdjson::document::key_value_pair; + friend class document::key_value_pair; template friend class simdjson::minify; }; @@ -230,7 +224,7 @@ public: * @return The array value, or: * - UNEXPECTED_TYPE if the JSON element is not an array */ - inline array_result as_array() const noexcept; + inline simdjson_result as_array() const noexcept; /** * Read this element as a JSON object (key/value pairs). @@ -238,7 +232,7 @@ public: * @return The object value, or: * - UNEXPECTED_TYPE if the JSON element is not an object */ - inline object_result as_object() const noexcept; + inline simdjson_result as_object() const noexcept; #if SIMDJSON_EXCEPTIONS /** @@ -326,7 +320,7 @@ public: * - 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 */ - inline element_result operator[](const std::string_view &json_pointer) const noexcept; + inline simdjson_result operator[](const std::string_view &json_pointer) const noexcept; /** * 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 * - 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 operator[](const char *json_pointer) const noexcept; /** * 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 * - 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 at(const std::string_view &json_pointer) const noexcept; /** * Get the value at the given index. @@ -368,7 +362,7 @@ public: * @return The value at the given index, or: * - 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 at(size_t index) const noexcept; /** * Get the value associated with the given key. @@ -382,7 +376,7 @@ public: * @return The value associated with this field, or: * - 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 at_key(const std::string_view &key) const noexcept; /** * 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: * - 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 at_key_case_insensitive(const std::string_view &key) const noexcept; /** @private for debugging. Prints out the root element. */ inline bool dump_raw_tape(std::ostream &out) const noexcept; @@ -400,9 +394,9 @@ public: private: really_inline element(const document *_doc, size_t _json_index) noexcept; friend class document; - friend class document::element_result; + friend struct simdjson_result; template - friend class minify; + friend class simdjson::minify; }; /** @@ -463,7 +457,7 @@ public: * - 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 */ - inline element_result operator[](const std::string_view &json_pointer) const noexcept; + inline simdjson_result operator[](const std::string_view &json_pointer) const noexcept; /** * 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 * - 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 operator[](const char *json_pointer) const noexcept; /** * 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 * - 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 at(const std::string_view &json_pointer) const noexcept; /** * Get the value at the given index. @@ -503,14 +497,14 @@ public: * @return The value at the given index, or: * - 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 at(size_t index) const noexcept; private: really_inline array(const document *_doc, size_t _json_index) noexcept; - friend class document::element; - friend class document::element_result; + friend class element; + friend struct simdjson_result; template - friend class minify; + friend class simdjson::minify; }; /** @@ -553,7 +547,7 @@ public: inline element value() const noexcept; private: 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 * - 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 operator[](const std::string_view &json_pointer) const noexcept; /** * 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 * - 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 operator[](const char *json_pointer) const noexcept; /** * 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 * - 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 at(const std::string_view &json_pointer) const noexcept; /** * Get the value associated with the given key. @@ -629,7 +623,7 @@ public: * @return The value associated with this field, or: * - 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 at_key(const std::string_view &key) const noexcept; /** * 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: * - 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 at_key_case_insensitive(const std::string_view &key) const noexcept; private: really_inline object(const document *_doc, size_t _json_index) noexcept; - friend class document::element; - friend class document::element_result; + friend class element; + friend struct simdjson_result; template - friend class minify; + friend class simdjson::minify; }; /** @@ -659,15 +653,16 @@ public: private: 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. */ -class document::element_result : public simdjson_result { +template<> +struct simdjson_result : public internal::simdjson_result_base { public: - really_inline element_result() noexcept; - really_inline element_result(element &&value) noexcept; - really_inline element_result(error_code error) noexcept; + really_inline simdjson_result() noexcept; + really_inline simdjson_result(document::element &&value) noexcept; + really_inline simdjson_result(error_code error) noexcept; /** Whether this is a JSON `null` */ inline simdjson_result is_null() const noexcept; @@ -677,15 +672,15 @@ public: inline simdjson_result as_uint64_t() const noexcept; inline simdjson_result as_int64_t() const noexcept; inline simdjson_result as_double() const noexcept; - inline array_result as_array() const noexcept; - inline object_result as_object() const noexcept; + inline simdjson_result as_array() const noexcept; + inline simdjson_result as_object() const noexcept; - inline element_result operator[](const std::string_view &json_pointer) const noexcept; - inline element_result operator[](const char *json_pointer) const noexcept; - inline element_result at(const std::string_view &json_pointer) const noexcept; - inline element_result at(size_t index) const noexcept; - inline element_result 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 operator[](const std::string_view &json_pointer) const noexcept; + inline simdjson_result operator[](const char *json_pointer) const noexcept; + inline simdjson_result at(const std::string_view &json_pointer) const noexcept; + inline simdjson_result at(size_t index) const noexcept; + inline simdjson_result at_key(const std::string_view &key) const noexcept; + inline simdjson_result at_key_case_insensitive(const std::string_view &key) const noexcept; #if SIMDJSON_EXCEPTIONS inline operator bool() const noexcept(false); @@ -694,45 +689,47 @@ public: inline operator uint64_t() const noexcept(false); inline operator int64_t() const noexcept(false); inline operator double() const noexcept(false); - inline operator array() const noexcept(false); - inline operator object() const noexcept(false); + inline operator document::array() const noexcept(false); + inline operator document::object() const noexcept(false); #endif // SIMDJSON_EXCEPTIONS }; /** The result of a JSON conversion that may fail. */ -class document::array_result : public simdjson_result { +template<> +struct simdjson_result : public internal::simdjson_result_base { public: - really_inline array_result() noexcept; - really_inline array_result(array value) noexcept; - really_inline array_result(error_code error) noexcept; + really_inline simdjson_result() noexcept; + really_inline simdjson_result(document::array value) noexcept; + really_inline simdjson_result(error_code error) noexcept; - inline element_result operator[](const std::string_view &json_pointer) const noexcept; - inline element_result operator[](const char *json_pointer) const noexcept; - inline element_result at(const std::string_view &json_pointer) const noexcept; - inline element_result at(size_t index) const noexcept; + inline simdjson_result operator[](const std::string_view &json_pointer) const noexcept; + inline simdjson_result operator[](const char *json_pointer) const noexcept; + inline simdjson_result at(const std::string_view &json_pointer) const noexcept; + inline simdjson_result at(size_t index) const noexcept; #if SIMDJSON_EXCEPTIONS - inline array::iterator begin() const noexcept(false); - inline array::iterator end() const noexcept(false); + inline document::array::iterator begin() const noexcept(false); + inline document::array::iterator end() const noexcept(false); #endif // SIMDJSON_EXCEPTIONS }; /** The result of a JSON conversion that may fail. */ -class document::object_result : public simdjson_result { +template<> +struct simdjson_result : public internal::simdjson_result_base { public: - really_inline object_result() noexcept; - really_inline object_result(object value) noexcept; - really_inline object_result(error_code error) noexcept; + really_inline simdjson_result() noexcept; + really_inline simdjson_result(document::object value) noexcept; + really_inline simdjson_result(error_code error) noexcept; - inline element_result operator[](const std::string_view &json_pointer) const noexcept; - inline element_result operator[](const char *json_pointer) const noexcept; - inline element_result at(const std::string_view &json_pointer) const noexcept; - inline element_result 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 operator[](const std::string_view &json_pointer) const noexcept; + inline simdjson_result operator[](const char *json_pointer) const noexcept; + inline simdjson_result at(const std::string_view &json_pointer) const noexcept; + inline simdjson_result at_key(const std::string_view &key) const noexcept; + inline simdjson_result at_key_case_insensitive(const std::string_view &key) const noexcept; #if SIMDJSON_EXCEPTIONS - inline object::iterator begin() const noexcept(false); - inline object::iterator end() const noexcept(false); + inline document::object::iterator begin() const noexcept(false); + inline document::object::iterator end() const noexcept(false); #endif // SIMDJSON_EXCEPTIONS }; @@ -804,7 +801,7 @@ public: * - CAPACITY if the parser does not have enough capacity and len > max_capacity. * - other json errors if parsing fails. */ - inline element_result load(const std::string &path) noexcept; + inline simdjson_result load(const std::string &path) noexcept; /** * 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. * - 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 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. @@ -935,7 +932,7 @@ public: * - CAPACITY if the parser does not have enough capacity and len > max_capacity. * - 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 parse(const char *buf, size_t len, bool realloc_if_needed = true) noexcept; /** * 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. * - other json errors if parsing fails. */ - really_inline element_result parse(const std::string &s) noexcept; + really_inline simdjson_result parse(const std::string &s) noexcept; /** * 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. * - other json errors if parsing fails. */ - really_inline element_result parse(const padded_string &s) noexcept; + really_inline simdjson_result parse(const padded_string &s) noexcept; // 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 parse(const char *buf) noexcept = delete; /** * 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; // 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 parse_many(const char *buf, size_t batch_size = DEFAULT_BATCH_SIZE) noexcept = delete; /** * The largest document this parser can automatically support. @@ -1448,8 +1445,8 @@ private: // inline simdjson_result read_file(const std::string &path) noexcept; - friend class document::parser::Iterator; - friend class document::stream; + friend class parser::Iterator; + friend class stream; }; // 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 * 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 &value) noexcept(false) { return out << minify(value); } /** * 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 * 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 &value) noexcept(false) { return out << minify(value); } /** * 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 * 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 &value) noexcept(false) { return out << minify(value); } #endif diff --git a/include/simdjson/document_stream.h b/include/simdjson/document_stream.h index ed97e52d..e5281b3d 100644 --- a/include/simdjson/document_stream.h +++ b/include/simdjson/document_stream.h @@ -24,7 +24,7 @@ public: /** * Get the current document (or error). */ - really_inline element_result operator*() noexcept; + really_inline simdjson_result operator*() noexcept; /** * Advance to the next document. */ diff --git a/include/simdjson/error.h b/include/simdjson/error.h index 97099efe..be311287 100644 --- a/include/simdjson/error.h +++ b/include/simdjson/error.h @@ -74,29 +74,60 @@ private: 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. + * + * This is a base class for implementations that want to add functions to the result type for + * chaining. + * + * Override like: + * + * struct simdjson_result : public internal::simdjson_result_base { + * simdjson_result() noexcept : internal::simdjson_result_base() {} + * simdjson_result(error_code error) noexcept : internal::simdjson_result_base(error) {} + * simdjson_result(T &&value) noexcept : internal::simdjson_result_base(std::forward(value)) {} + * simdjson_result(T &&value, error_code error) noexcept : internal::simdjson_result_base(value, error) {} + * // Your extra methods here + * } + * + * Then any method returning simdjson_result will be chainable with your methods. */ template -struct simdjson_result : public std::pair { +struct simdjson_result_base : public std::pair { + + /** + * 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. */ - void tie(T& t, error_code & e) && 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>(*this).first; - e = this->second; - } + really_inline void tie(T &value, error_code &error) && noexcept; /** * The error. */ - error_code error() const { return this->second; } + really_inline error_code error() const noexcept; #if SIMDJSON_EXCEPTIONS @@ -105,52 +136,86 @@ struct simdjson_result : public std::pair { * * @throw simdjson_error if there was an error. */ - T& get() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return this->first; - }; + really_inline T& get() noexcept(false); /** * The value of the function. * * @throw simdjson_error if there was an error. */ - T&& take() && { - if (error()) { throw simdjson_error(error()); } - return std::forward(this->first); - }; + really_inline T&& take() && noexcept(false); /** * Cast to the value (will throw on error). * * @throw simdjson_error if there was an error. */ - operator T&&() && { - return std::forward>(*this).take(); - } + really_inline operator T&&() && noexcept(false); #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 +struct simdjson_result : public internal::simdjson_result_base { /** * Create a new empty result with error = UNINITIALIZED. */ - simdjson_result() noexcept : simdjson_result(UNINITIALIZED) {} - + really_inline simdjson_result() noexcept; /** * Create a new error result. */ - simdjson_result(error_code error) noexcept : std::pair(T{}, error) {} - + really_inline simdjson_result(T &&value) noexcept; /** * Create a new successful result. */ - simdjson_result(T &&value) noexcept : std::pair(std::forward(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). */ - simdjson_result(T &&value, error_code error) noexcept : std::pair(std::forward(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 diff --git a/include/simdjson/inline/document.h b/include/simdjson/inline/document.h index 78b5728a..349453c1 100644 --- a/include/simdjson/inline/document.h +++ b/include/simdjson/inline/document.h @@ -10,178 +10,188 @@ #include "simdjson/internal/jsonformatutils.h" #include #include +#include namespace simdjson { // -// element_result inline implementation +// simdjson_result inline implementation // -really_inline document::element_result::element_result() noexcept : simdjson_result() {} -really_inline document::element_result::element_result(element &&value) noexcept : simdjson_result((element&&)value) {} -really_inline document::element_result::element_result(error_code error) noexcept : simdjson_result(error) {} -inline simdjson_result document::element_result::is_null() const noexcept { +really_inline simdjson_result::simdjson_result() noexcept + : internal::simdjson_result_base() {} +really_inline simdjson_result::simdjson_result(document::element &&value) noexcept + : internal::simdjson_result_base(std::forward(value)) {} +really_inline simdjson_result::simdjson_result(error_code error) noexcept + : internal::simdjson_result_base(error) {} +inline simdjson_result simdjson_result::is_null() const noexcept { if (error()) { return error(); } return first.is_null(); } -inline simdjson_result document::element_result::as_bool() const noexcept { +inline simdjson_result simdjson_result::as_bool() const noexcept { if (error()) { return error(); } return first.as_bool(); } -inline simdjson_result document::element_result::as_c_str() const noexcept { +inline simdjson_result simdjson_result::as_c_str() const noexcept { if (error()) { return error(); } return first.as_c_str(); } -inline simdjson_result document::element_result::as_string() const noexcept { +inline simdjson_result simdjson_result::as_string() const noexcept { if (error()) { return error(); } return first.as_string(); } -inline simdjson_result document::element_result::as_uint64_t() const noexcept { +inline simdjson_result simdjson_result::as_uint64_t() const noexcept { if (error()) { return error(); } return first.as_uint64_t(); } -inline simdjson_result document::element_result::as_int64_t() const noexcept { +inline simdjson_result simdjson_result::as_int64_t() const noexcept { if (error()) { return error(); } return first.as_int64_t(); } -inline simdjson_result document::element_result::as_double() const noexcept { +inline simdjson_result simdjson_result::as_double() const noexcept { if (error()) { return error(); } return first.as_double(); } -inline document::array_result document::element_result::as_array() const noexcept { +inline simdjson_result simdjson_result::as_array() const noexcept { if (error()) { return error(); } return first.as_array(); } -inline document::object_result document::element_result::as_object() const noexcept { +inline simdjson_result simdjson_result::as_object() const noexcept { if (error()) { return error(); } return first.as_object(); } -inline document::element_result document::element_result::operator[](const std::string_view &json_pointer) const noexcept { +inline simdjson_result simdjson_result::operator[](const std::string_view &json_pointer) const noexcept { if (error()) { return *this; } return first[json_pointer]; } -inline document::element_result document::element_result::operator[](const char *json_pointer) const noexcept { +inline simdjson_result simdjson_result::operator[](const char *json_pointer) const noexcept { if (error()) { return *this; } return first[json_pointer]; } -inline document::element_result document::element_result::at(const std::string_view &json_pointer) const noexcept { +inline simdjson_result simdjson_result::at(const std::string_view &json_pointer) const noexcept { if (error()) { return *this; } return first.at(json_pointer); } -inline document::element_result document::element_result::at(size_t index) const noexcept { +inline simdjson_result simdjson_result::at(size_t index) const noexcept { if (error()) { return *this; } return first.at(index); } -inline document::element_result document::element_result::at_key(const std::string_view &key) const noexcept { +inline simdjson_result simdjson_result::at_key(const std::string_view &key) const noexcept { if (error()) { return *this; } 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 simdjson_result::at_key_case_insensitive(const std::string_view &key) const noexcept { if (error()) { return *this; } return first.at_key_case_insensitive(key); } #if SIMDJSON_EXCEPTIONS -inline document::element_result::operator bool() const noexcept(false) { +inline simdjson_result::operator bool() const noexcept(false) { return as_bool(); } -inline document::element_result::operator const char *() const noexcept(false) { +inline simdjson_result::operator const char *() const noexcept(false) { return as_c_str(); } -inline document::element_result::operator std::string_view() const noexcept(false) { +inline simdjson_result::operator std::string_view() const noexcept(false) { return as_string(); } -inline document::element_result::operator uint64_t() const noexcept(false) { +inline simdjson_result::operator uint64_t() const noexcept(false) { return as_uint64_t(); } -inline document::element_result::operator int64_t() const noexcept(false) { +inline simdjson_result::operator int64_t() const noexcept(false) { return as_int64_t(); } -inline document::element_result::operator double() const noexcept(false) { +inline simdjson_result::operator double() const noexcept(false) { return as_double(); } -inline document::element_result::operator document::array() const noexcept(false) { +inline simdjson_result::operator document::array() const noexcept(false) { return as_array(); } -inline document::element_result::operator document::object() const noexcept(false) { +inline simdjson_result::operator document::object() const noexcept(false) { return as_object(); } #endif // -// array_result inline implementation +// simdjson_result inline implementation // -really_inline document::array_result::array_result() noexcept : simdjson_result() {} -really_inline document::array_result::array_result(array value) noexcept : simdjson_result((array&&)value) {} -really_inline document::array_result::array_result(error_code error) noexcept : simdjson_result(error) {} +really_inline simdjson_result::simdjson_result() noexcept + : internal::simdjson_result_base() {} +really_inline simdjson_result::simdjson_result(document::array value) noexcept + : internal::simdjson_result_base(std::forward(value)) {} +really_inline simdjson_result::simdjson_result(error_code error) noexcept + : internal::simdjson_result_base(error) {} #if SIMDJSON_EXCEPTIONS -inline document::array::iterator document::array_result::begin() const noexcept(false) { +inline document::array::iterator simdjson_result::begin() const noexcept(false) { if (error()) { throw simdjson_error(error()); } return first.begin(); } -inline document::array::iterator document::array_result::end() const noexcept(false) { +inline document::array::iterator simdjson_result::end() const noexcept(false) { if (error()) { throw simdjson_error(error()); } return first.end(); } #endif // SIMDJSON_EXCEPTIONS -inline document::element_result document::array_result::operator[](const std::string_view &json_pointer) const noexcept { +inline simdjson_result simdjson_result::operator[](const std::string_view &json_pointer) const noexcept { if (error()) { return error(); } return first.at(json_pointer); } -inline document::element_result document::array_result::operator[](const char *json_pointer) const noexcept { +inline simdjson_result simdjson_result::operator[](const char *json_pointer) const noexcept { if (error()) { return error(); } return first.at(json_pointer); } -inline document::element_result document::array_result::at(const std::string_view &json_pointer) const noexcept { +inline simdjson_result simdjson_result::at(const std::string_view &json_pointer) const noexcept { if (error()) { return error(); } return first.at(json_pointer); } -inline document::element_result document::array_result::at(size_t index) const noexcept { +inline simdjson_result simdjson_result::at(size_t index) const noexcept { if (error()) { return error(); } return first.at(index); } // -// object_result inline implementation +// simdjson_result inline implementation // -really_inline document::object_result::object_result() noexcept : simdjson_result() {} -really_inline document::object_result::object_result(object value) noexcept : simdjson_result((object&&)value) {} -really_inline document::object_result::object_result(error_code error) noexcept : simdjson_result(error) {} +really_inline simdjson_result::simdjson_result() noexcept + : internal::simdjson_result_base() {} +really_inline simdjson_result::simdjson_result(document::object value) noexcept + : internal::simdjson_result_base(std::forward(value)) {} +really_inline simdjson_result::simdjson_result(error_code error) noexcept + : internal::simdjson_result_base(error) {} -inline document::element_result document::object_result::operator[](const std::string_view &json_pointer) const noexcept { +inline simdjson_result simdjson_result::operator[](const std::string_view &json_pointer) const noexcept { if (error()) { return error(); } return first[json_pointer]; } -inline document::element_result document::object_result::operator[](const char *json_pointer) const noexcept { +inline simdjson_result simdjson_result::operator[](const char *json_pointer) const noexcept { if (error()) { return error(); } return first[json_pointer]; } -inline document::element_result document::object_result::at(const std::string_view &json_pointer) const noexcept { +inline simdjson_result simdjson_result::at(const std::string_view &json_pointer) const noexcept { if (error()) { return error(); } return first.at(json_pointer); } -inline document::element_result document::object_result::at_key(const std::string_view &key) const noexcept { +inline simdjson_result simdjson_result::at_key(const std::string_view &key) const noexcept { if (error()) { return error(); } 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 simdjson_result::at_key_case_insensitive(const std::string_view &key) const noexcept { if (error()) { return error(); } return first.at_key_case_insensitive(key); } #if SIMDJSON_EXCEPTIONS -inline document::object::iterator document::object_result::begin() const noexcept(false) { +inline document::object::iterator simdjson_result::begin() const noexcept(false) { if (error()) { throw simdjson_error(error()); } return first.begin(); } -inline document::object::iterator document::object_result::end() const noexcept(false) { +inline document::object::iterator simdjson_result::end() const noexcept(false) { if (error()) { throw simdjson_error(error()); } return first.end(); } @@ -369,7 +379,7 @@ inline simdjson_result document::parser::read_file(const std::string &pa return bytes_read; } -inline document::element_result document::parser::load(const std::string &path) noexcept { +inline simdjson_result document::parser::load(const std::string &path) noexcept { auto [len, code] = read_file(path); 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); } -inline document::element_result document::parser::parse(const uint8_t *buf, size_t len, bool realloc_if_needed) noexcept { +inline simdjson_result document::parser::parse(const uint8_t *buf, size_t len, bool realloc_if_needed) noexcept { error_code code = ensure_capacity(len); if (code) { return code; } @@ -399,18 +409,18 @@ inline document::element_result document::parser::parse(const uint8_t *buf, size } 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, so set the parse state back to invalid valid = false; error = UNINITIALIZED; 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::parser::parse(const char *buf, size_t len, bool realloc_if_needed) noexcept { 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::parser::parse(const std::string &s) noexcept { 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::parser::parse(const padded_string &s) noexcept { 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); } -inline document::element_result document::array::at(const std::string_view &json_pointer) const noexcept { +inline simdjson_result document::array::at(const std::string_view &json_pointer) const noexcept { // - 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. 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; } -inline document::element_result document::array::at(size_t index) const noexcept { +inline simdjson_result document::array::at(size_t index) const noexcept { size_t i=0; for (auto element : *this) { if (i == index) { return element; } @@ -651,18 +661,18 @@ inline document::object::iterator document::object::end() const noexcept { 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::object::operator[](const std::string_view &json_pointer) const noexcept { return at(json_pointer); } -inline document::element_result document::object::operator[](const char *json_pointer) const noexcept { +inline simdjson_result document::object::operator[](const char *json_pointer) const noexcept { return at(json_pointer); } -inline document::element_result document::object::at(const std::string_view &json_pointer) const noexcept { +inline simdjson_result document::object::at(const std::string_view &json_pointer) const noexcept { size_t slash = json_pointer.find('/'); std::string_view key = json_pointer.substr(0, slash); // Grab the child with the given key - document::element_result child; + simdjson_result child; // If there is an escape character in the key, unescape it and then get the child. size_t escape = key.find('~'); @@ -694,7 +704,7 @@ inline document::element_result document::object::at(const std::string_view &jso return child; } -inline document::element_result document::object::at_key(const std::string_view &key) const noexcept { +inline simdjson_result document::object::at_key(const std::string_view &key) const noexcept { iterator end_field = end(); for (iterator field = begin(); field != end_field; ++field) { 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 // https://github.com/simdjson/simdjson/issues/323 // 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::object::at_key_case_insensitive(const std::string_view &key) const noexcept { iterator end_field = end(); for (iterator field = begin(); field != end_field; ++field) { auto field_key = field.key(); @@ -881,7 +891,7 @@ inline simdjson_result document::element::as_double() const noexcept { return INCORRECT_TYPE; } } -inline document::array_result document::element::as_array() const noexcept { +inline simdjson_result document::element::as_array() const noexcept { switch (type()) { case internal::tape_type::START_ARRAY: return array(doc, json_index); @@ -889,7 +899,7 @@ inline document::array_result document::element::as_array() const noexcept { return INCORRECT_TYPE; } } -inline document::object_result document::element::as_object() const noexcept { +inline simdjson_result document::element::as_object() const noexcept { switch (type()) { case internal::tape_type::START_OBJECT: return object(doc, json_index); @@ -897,13 +907,13 @@ inline document::object_result document::element::as_object() const noexcept { return INCORRECT_TYPE; } } -inline document::element_result document::element::operator[](const std::string_view &json_pointer) const noexcept { +inline simdjson_result document::element::operator[](const std::string_view &json_pointer) const noexcept { return at(json_pointer); } -inline document::element_result document::element::operator[](const char *json_pointer) const noexcept { +inline simdjson_result document::element::operator[](const char *json_pointer) const noexcept { return at(json_pointer); } -inline document::element_result document::element::at(const std::string_view &json_pointer) const noexcept { +inline simdjson_result document::element::at(const std::string_view &json_pointer) const noexcept { switch (type()) { case internal::tape_type::START_OBJECT: 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; } } -inline document::element_result document::element::at(size_t index) const noexcept { +inline simdjson_result document::element::at(size_t index) const noexcept { 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::at_key(const std::string_view &key) const noexcept { 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::at_key_case_insensitive(const std::string_view &key) const noexcept { return as_object().at_key_case_insensitive(key); } @@ -1088,17 +1098,17 @@ inline std::ostream& minify::print(std::ostream& out) #if SIMDJSON_EXCEPTIONS template<> -inline std::ostream& minify::print(std::ostream& out) { +inline std::ostream& minify>::print(std::ostream& out) { if (value.error()) { throw simdjson_error(value.error()); } return out << minify(value.first); } template<> -inline std::ostream& minify::print(std::ostream& out) { +inline std::ostream& minify>::print(std::ostream& out) { if (value.error()) { throw simdjson_error(value.error()); } return out << minify(value.first); } template<> -inline std::ostream& minify::print(std::ostream& out) { +inline std::ostream& minify>::print(std::ostream& out) { if (value.error()) { throw simdjson_error(value.error()); } return out << minify(value.first); } diff --git a/include/simdjson/inline/document_stream.h b/include/simdjson/inline/document_stream.h index 83e7f335..912e3819 100644 --- a/include/simdjson/inline/document_stream.h +++ b/include/simdjson/inline/document_stream.h @@ -127,7 +127,7 @@ really_inline document::stream::iterator::iterator(stream& stream, bool _is_end) : _stream{stream}, finished{_is_end} { } -really_inline document::element_result document::stream::iterator::operator*() noexcept { +really_inline simdjson_result document::stream::iterator::operator*() noexcept { error_code error = _stream.error == SUCCESS_AND_HAS_MORE ? SUCCESS : _stream.error; if (error) { return error; } return _stream.parser.doc.root(); diff --git a/include/simdjson/inline/error.h b/include/simdjson/inline/error.h index b07ff48e..8ba4c995 100644 --- a/include/simdjson/inline/error.h +++ b/include/simdjson/inline/error.h @@ -58,6 +58,108 @@ inline std::ostream& operator<<(std::ostream& out, error_code error) noexcept { return out << error_message(error); } +namespace internal { + +// +// internal::simdjson_result_base inline implementation +// + +template +really_inline void simdjson_result_base::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(); + // fails with "error: no viable overloaded '='"" + value = std::forward>(*this).first; + error = this->second; +} + +template +really_inline error_code simdjson_result_base::error() const noexcept { + return this->second; +} + +#if SIMDJSON_EXCEPTIONS + +template +really_inline T& simdjson_result_base::get() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return this->first; +}; + +template +really_inline T&& simdjson_result_base::take() && noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return std::forward(this->first); +}; + +template +really_inline simdjson_result_base::operator T&&() && noexcept(false) { + return std::forward>(*this).take(); +} + +#endif // SIMDJSON_EXCEPTIONS + +template +really_inline simdjson_result_base::simdjson_result_base(T &&value, error_code error) noexcept + : std::pair(std::forward(value), error) {} +template +really_inline simdjson_result_base::simdjson_result_base(error_code error) noexcept + : simdjson_result_base(T{}, error) {} +template +really_inline simdjson_result_base::simdjson_result_base(T &&value) noexcept + : simdjson_result_base(std::forward(value), SUCCESS) {} +template +really_inline simdjson_result_base::simdjson_result_base() noexcept + : simdjson_result_base(T{}, UNINITIALIZED) {} + +} // namespace internal + +/// +/// simdjson_result inline implementation +/// + +template +really_inline void simdjson_result::tie(T &value, error_code &error) && noexcept { + std::forward>(*this).tie(value, error); +} + +template +really_inline error_code simdjson_result::error() const noexcept { + return internal::simdjson_result_base::error(); +} + +#if SIMDJSON_EXCEPTIONS + +template +really_inline T& simdjson_result::get() noexcept(false) { + return internal::simdjson_result_base::get(); +} + +template +really_inline T&& simdjson_result::take() && noexcept(false) { + return std::forward>(*this).take(); +} + +template +really_inline simdjson_result::operator T&&() && noexcept(false) { + return std::forward>(*this).take(); +} + +#endif // SIMDJSON_EXCEPTIONS + +template +really_inline simdjson_result::simdjson_result(T &&value, error_code error) noexcept + : internal::simdjson_result_base(std::forward(value), error) {} +template +really_inline simdjson_result::simdjson_result(error_code error) noexcept + : internal::simdjson_result_base(error) {} +template +really_inline simdjson_result::simdjson_result(T &&value) noexcept + : internal::simdjson_result_base(std::forward(value)) {} +template +really_inline simdjson_result::simdjson_result() noexcept + : internal::simdjson_result_base() {} + } // namespace simdjson #endif // SIMDJSON_INLINE_ERROR_H