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 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<typename T>
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<array> 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<object> 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<element> 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<element> 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<element> 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<element> 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<element> 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<element> 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<document::element>;
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
* - 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.
@ -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<element> 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<element> 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<element> 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<element>;
template<typename T>
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<element> 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<element> 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<element> 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<element> 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<element> 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<element>;
template<typename T>
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<document::element> {
template<>
struct simdjson_result<document::element> : public internal::simdjson_result_base<document::element> {
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<bool> is_null() const noexcept;
@ -677,15 +672,15 @@ public:
inline simdjson_result<uint64_t> as_uint64_t() const noexcept;
inline simdjson_result<int64_t> as_int64_t() const noexcept;
inline simdjson_result<double> as_double() const noexcept;
inline array_result as_array() const noexcept;
inline object_result as_object() const noexcept;
inline simdjson_result<document::array> as_array() const noexcept;
inline simdjson_result<document::object> 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<document::element> operator[](const std::string_view &json_pointer) const noexcept;
inline simdjson_result<document::element> operator[](const char *json_pointer) const noexcept;
inline simdjson_result<document::element> at(const std::string_view &json_pointer) const noexcept;
inline simdjson_result<document::element> at(size_t index) const noexcept;
inline simdjson_result<document::element> at_key(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
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<document::array> {
template<>
struct simdjson_result<document::array> : public internal::simdjson_result_base<document::array> {
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<document::element> operator[](const std::string_view &json_pointer) const noexcept;
inline simdjson_result<document::element> operator[](const char *json_pointer) const noexcept;
inline simdjson_result<document::element> at(const std::string_view &json_pointer) const noexcept;
inline simdjson_result<document::element> 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<document::object> {
template<>
struct simdjson_result<document::object> : public internal::simdjson_result_base<document::object> {
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<document::element> operator[](const std::string_view &json_pointer) const noexcept;
inline simdjson_result<document::element> operator[](const char *json_pointer) const noexcept;
inline simdjson_result<document::element> at(const std::string_view &json_pointer) const noexcept;
inline simdjson_result<document::element> at_key(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
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<element> 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<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.
@ -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<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.
@ -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<element> 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<element> 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<element> 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<element> 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<size_t> 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<document::element> &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<document::array> &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<document::object> &value) noexcept(false) { return out << minify(value); }
#endif

View File

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

View File

@ -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<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>
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.
*/
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<simdjson_result<T>>(*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<T, error_code> {
*
* @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<T>(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<simdjson_result<T>>(*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<typename T>
struct simdjson_result : public internal::simdjson_result_base<T> {
/**
* 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_code>(T{}, error) {}
really_inline simdjson_result(T &&value) noexcept;
/**
* 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).
*/
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

View File

@ -10,178 +10,188 @@
#include "simdjson/internal/jsonformatutils.h"
#include <iostream>
#include <climits>
#include <cctype>
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 document::element_result::element_result(element &&value) noexcept : simdjson_result<element>((element&&)value) {}
really_inline document::element_result::element_result(error_code error) noexcept : simdjson_result<element>(error) {}
inline simdjson_result<bool> document::element_result::is_null() const noexcept {
really_inline simdjson_result<document::element>::simdjson_result() noexcept
: internal::simdjson_result_base<document::element>() {}
really_inline simdjson_result<document::element>::simdjson_result(document::element &&value) 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(); }
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(); }
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(); }
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(); }
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(); }
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(); }
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(); }
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(); }
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(); }
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; }
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; }
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; }
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; }
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; }
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; }
return first.at_key_case_insensitive(key);
}
#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();
}
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();
}
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();
}
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();
}
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();
}
inline document::element_result::operator double() const noexcept(false) {
inline simdjson_result<document::element>::operator double() const noexcept(false) {
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();
}
inline document::element_result::operator document::object() const noexcept(false) {
inline simdjson_result<document::element>::operator document::object() const noexcept(false) {
return as_object();
}
#endif
//
// array_result inline implementation
// simdjson_result<document::array> inline implementation
//
really_inline document::array_result::array_result() noexcept : simdjson_result<array>() {}
really_inline document::array_result::array_result(array value) noexcept : simdjson_result<array>((array&&)value) {}
really_inline document::array_result::array_result(error_code error) noexcept : simdjson_result<array>(error) {}
really_inline simdjson_result<document::array>::simdjson_result() noexcept
: internal::simdjson_result_base<document::array>() {}
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
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()); }
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()); }
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<document::element> simdjson_result<document::array>::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<document::element> simdjson_result<document::array>::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<document::element> simdjson_result<document::array>::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<document::element> simdjson_result<document::array>::at(size_t index) const noexcept {
if (error()) { return error(); }
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 document::object_result::object_result(object value) noexcept : simdjson_result<object>((object&&)value) {}
really_inline document::object_result::object_result(error_code error) noexcept : simdjson_result<object>(error) {}
really_inline simdjson_result<document::object>::simdjson_result() noexcept
: internal::simdjson_result_base<document::object>() {}
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(); }
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(); }
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(); }
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(); }
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(); }
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<document::object>::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<document::object>::end() const noexcept(false) {
if (error()) { throw simdjson_error(error()); }
return first.end();
}
@ -369,7 +379,7 @@ inline simdjson_result<size_t> 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::element> 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::element> 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<element>, 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::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);
}
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);
}
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);
}
@ -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::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"
// 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::element> 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::element> 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::element> 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::element> 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<document::element> 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::element> 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::element> 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<double> document::element::as_double() const noexcept {
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()) {
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::object> 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> 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> 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> 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> 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> 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> 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<document::key_value_pair>::print(std::ostream& out)
#if SIMDJSON_EXCEPTIONS
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()); }
return out << minify<document::element>(value.first);
}
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()); }
return out << minify<document::array>(value.first);
}
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()); }
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} {
}
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;
if (error) { return error; }
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);
}
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
#endif // SIMDJSON_INLINE_ERROR_H