Add tests for SIMDJSON_EXCEPTIONS=0, add `tie()` support

This commit is contained in:
John Keiser 2020-03-13 17:43:24 -07:00
parent 03c828c7ad
commit 1a5d8f1957
24 changed files with 1039 additions and 811 deletions

View File

@ -178,6 +178,28 @@ steps:
- make -j
- ctest --output-on-failure
---
kind: pipeline
name: amd64_clang_cmake_no_exceptions
platform:
os: linux
arch: amd64
steps:
- name: Build and Test
image: ubuntu:18.04
environment:
CC: clang
CXX: clang++
CMAKE_FLAGS: -DSIMDJSON_BUILD_STATIC=OFF
commands:
- apt-get update -qq
- apt-get install -y clang make cmake
- $CC --version
- mkdir build && cd build
- cmake $CMAKE_FLAGS ..
- make -j
- ctest --output-on-failure
kind: pipeline
name: amd64_clang_cmake_static

View File

@ -12,6 +12,8 @@ using namespace std;
const padded_string EMPTY_ARRAY("[]", 2);
#if SIMDJSON_EXCEPTIONS
static void twitter_count(State& state) {
// Prints the number of results in twitter.json
document doc = document::load(JSON_TEST_PATH);
@ -22,17 +24,6 @@ static void twitter_count(State& state) {
}
BENCHMARK(twitter_count);
static void error_code_twitter_count(State& state) noexcept {
// Prints the number of results in twitter.json
document doc = document::load(JSON_TEST_PATH);
for (auto _ : state) {
auto [value, error] = doc["search_metadata"]["count"];
if (error) { return; }
if (uint64_t(value) != 100) { return; }
}
}
BENCHMARK(error_code_twitter_count);
static void iterator_twitter_count(State& state) {
// Prints the number of results in twitter.json
document doc = document::load(JSON_TEST_PATH);
@ -65,6 +56,39 @@ static void twitter_default_profile(State& state) {
}
BENCHMARK(twitter_default_profile);
static void twitter_image_sizes(State& state) {
// Count unique image sizes
document doc = document::load(JSON_TEST_PATH);
for (auto _ : state) {
set<tuple<uint64_t, uint64_t>> image_sizes;
for (document::object tweet : doc["statuses"].as_array()) {
auto [media, not_found] = tweet["entities"]["media"];
if (!not_found) {
for (document::object image : media.as_array()) {
for (auto [key, size] : image["sizes"].as_object()) {
image_sizes.insert({ size["w"], size["h"] });
}
}
}
}
if (image_sizes.size() != 15) { return; };
}
}
BENCHMARK(twitter_image_sizes);
#endif // SIMDJSON_EXCEPTIONS
static void error_code_twitter_count(State& state) noexcept {
// Prints the number of results in twitter.json
document doc = document::load(JSON_TEST_PATH);
for (auto _ : state) {
auto [value, error] = doc["search_metadata"]["count"].as_uint64_t();
if (error) { return; }
if (value != 100) { return; }
}
}
BENCHMARK(error_code_twitter_count);
static void error_code_twitter_default_profile(State& state) noexcept {
// Count unique users with a default profile.
document doc = document::load(JSON_TEST_PATH);
@ -127,26 +151,6 @@ static void iterator_twitter_default_profile(State& state) {
}
BENCHMARK(iterator_twitter_default_profile);
static void twitter_image_sizes(State& state) {
// Count unique image sizes
document doc = document::load(JSON_TEST_PATH);
for (auto _ : state) {
set<tuple<uint64_t, uint64_t>> image_sizes;
for (document::object tweet : doc["statuses"].as_array()) {
auto [media, not_found] = tweet["entities"]["media"];
if (!not_found) {
for (document::object image : media.as_array()) {
for (auto [key, size] : image["sizes"].as_object()) {
image_sizes.insert({ size["w"], size["h"] });
}
}
}
}
if (image_sizes.size() != 15) { return; };
}
}
BENCHMARK(twitter_image_sizes);
static void error_code_twitter_image_sizes(State& state) noexcept {
// Count unique image sizes
document doc = document::load(JSON_TEST_PATH);

View File

@ -304,8 +304,8 @@ struct benchmarker {
// Run it once to get hot buffers
if(hotbuffers) {
auto result = parser.parse((const uint8_t *)json.data(), json.size());
if (result.error) {
exit_error(string("Failed to parse ") + filename + string(":") + error_message(result.error));
if (result.error()) {
exit_error(string("Failed to parse ") + filename + string(":") + error_message(result.error()));
}
}

View File

@ -67,7 +67,7 @@ simdjson_compute_stats(const simdjson::padded_string &p) {
__attribute__((noinline)) bool
simdjson_just_parse(const simdjson::padded_string &p) {
return simdjson::document::parse(p).error != simdjson::SUCCESS;
return simdjson::document::parse(p).error() != simdjson::SUCCESS;
}
void sajson_traverse(std::vector<int64_t> &answer, const sajson::value &node) {

View File

@ -82,7 +82,7 @@ int main (int argc, char *argv[]){
auto start = std::chrono::steady_clock::now();
count = 0;
for (auto result : parser.parse_many(p, 4000000)) {
error = result.error;
error = result.error();
count++;
}
auto end = std::chrono::steady_clock::now();
@ -121,7 +121,7 @@ int main (int argc, char *argv[]){
auto start = std::chrono::steady_clock::now();
// TODO this includes allocation of the parser; is that intentional?
for (auto result : parser.parse_many(p, 4000000)) {
error = result.error;
error = result.error();
}
auto end = std::chrono::steady_clock::now();

View File

@ -47,7 +47,10 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
try {
auto pj = simdjson::build_parsed_json(Data, Size);
simdjson::ParsedJson::Iterator pjh(pj);
if (!pj.is_valid()) {
throw 1;
}
simdjson::ParsedJson::Iterator pjh(pj.doc);
if (pjh.is_ok()) {
compute_dump(pjh);
}

View File

@ -10,11 +10,13 @@
#include "simdjson/simdjson.h"
#include "simdjson/padded_string.h"
namespace simdjson {
namespace simdjson::internal {
constexpr const uint64_t JSON_VALUE_MASK = 0x00FFFFFFFFFFFFFF;
enum class tape_type;
class tape_ref;
} // namespace simdjson::internal
namespace internal {
constexpr const uint64_t JSON_VALUE_MASK = 0x00FFFFFFFFFFFFFF;
}
namespace simdjson {
template<size_t max_depth> class document_iterator;
@ -59,10 +61,11 @@ public:
class parser;
class stream;
template<typename T=element>
class element_result;
class doc_move_result;
class doc_result;
class doc_ref_result;
class element_result;
class array_result;
class object_result;
class stream_result;
// Nested classes. See definitions later in file.
@ -75,11 +78,11 @@ public:
/**
* Get the root element of this document as a JSON array.
*/
element_result<array> as_array() const noexcept;
array_result as_array() const noexcept;
/**
* Get the root element of this document as a JSON object.
*/
element_result<object> as_object() const noexcept;
object_result as_object() const noexcept;
/**
* Get the root element of this document.
*/
@ -114,7 +117,7 @@ public:
* - NO_SUCH_FIELD if the field does not exist in the object
* - UNEXPECTED_TYPE if the document is not an object
*/
element_result<element> operator[](const std::string_view &s) const noexcept;
element_result operator[](const std::string_view &s) const noexcept;
/**
* Get the value associated with the given key.
*
@ -127,7 +130,7 @@ public:
* - NO_SUCH_FIELD if the field does not exist in the object
* - UNEXPECTED_TYPE if the document is not an object
*/
element_result<element> operator[](const char *s) const noexcept;
element_result operator[](const char *s) const noexcept;
/**
* Dump the raw tape for debugging.
@ -154,7 +157,7 @@ public:
* - CAPACITY if the parser does not have enough capacity and len > max_capacity.
* - other json errors if parsing fails.
*/
inline static doc_result load(const std::string& path) noexcept;
inline static doc_move_result load(const std::string& path) noexcept;
/**
* Parse a JSON document and return a reference to it.
@ -170,7 +173,7 @@ public:
* @param realloc_if_needed Whether to reallocate and enlarge the JSON buffer to add padding.
* @return the document, or an error if the JSON is invalid.
*/
inline static doc_result parse(const uint8_t *buf, size_t len, bool realloc_if_needed = true) noexcept;
inline static doc_move_result parse(const uint8_t *buf, size_t len, bool realloc_if_needed = true) noexcept;
/**
* Parse a JSON document.
@ -186,7 +189,7 @@ public:
* @param realloc_if_needed Whether to reallocate and enlarge the JSON buffer to add padding.
* @return the document, or an error if the JSON is invalid.
*/
really_inline static doc_result parse(const char *buf, size_t len, bool realloc_if_needed = true) noexcept;
really_inline static doc_move_result parse(const char *buf, size_t len, bool realloc_if_needed = true) noexcept;
/**
* Parse a JSON document.
@ -199,7 +202,7 @@ public:
* a new string will be created with the extra padding.
* @return the document, or an error if the JSON is invalid.
*/
really_inline static doc_result parse(const std::string &s) noexcept;
really_inline static doc_move_result parse(const std::string &s) noexcept;
/**
* Parse a JSON document.
@ -207,28 +210,29 @@ public:
* @param s The JSON to parse.
* @return the document, or an error if the JSON is invalid.
*/
really_inline static doc_result parse(const padded_string &s) noexcept;
really_inline static doc_move_result parse(const padded_string &s) noexcept;
// We do not want to allow implicit conversion from C string to std::string.
doc_ref_result parse(const char *buf, bool realloc_if_needed = true) noexcept = delete;
doc_result parse(const char *buf, bool realloc_if_needed = true) noexcept = delete;
std::unique_ptr<uint64_t[]> tape;
std::unique_ptr<uint8_t[]> string_buf;// should be at least byte_capacity
private:
class tape_ref;
enum class tape_type;
inline error_code set_capacity(size_t len) noexcept;
template<typename T>
friend class minify;
}; // class document
template<typename T>
class minify;
/**
* A parsed, *owned* document, or an error if the parse failed.
*
* document &doc = document::parse(json);
*
* Returns an owned `document`. When the doc_result (or the document retrieved from it) goes out of
* Returns an owned `document`. When the doc_move_result (or the document retrieved from it) goes out of
* scope, the document's memory is deallocated.
*
* ## Error Codes vs. Exceptions
@ -245,26 +249,24 @@ private:
* document doc = document::parse(json);
*
*/
class document::doc_result {
class document::doc_move_result : public simdjson_move_result<document> {
public:
/**
* The parsed document. This is *invalid* if there is an error.
*/
document doc;
/**
* The error code, or SUCCESS (0) if there is no error.
*/
error_code error;
#if SIMDJSON_EXCEPTIONS
/**
* Return the document, or throw an exception if it is invalid.
* Read this document as a JSON objec.
*
* @return the document.
* @exception simdjson_error if the document is invalid or there was an error parsing it.
* @return The object value, or:
* - UNEXPECTED_TYPE if the JSON document is not an object
*/
operator document() noexcept(false);
#endif // SIMDJSON_EXCEPTIONS
inline object_result as_object() const noexcept;
/**
* Read this document as a JSON array.
*
* @return The array value, or:
* - UNEXPECTED_TYPE if the JSON document is not an array
*/
inline array_result as_array() const noexcept;
/**
* Get the value associated with the given key.
@ -278,7 +280,7 @@ public:
* - NO_SUCH_FIELD if the field does not exist in the object
* - UNEXPECTED_TYPE if the document is not an object
*/
inline element_result<element> operator[](const std::string_view &key) const noexcept;
inline element_result operator[](const std::string_view &key) const noexcept;
/**
* Get the value associated with the given key.
*
@ -291,16 +293,14 @@ public:
* - NO_SUCH_FIELD if the field does not exist in the object
* - UNEXPECTED_TYPE if the document is not an object
*/
inline element_result<element> operator[](const char *key) const noexcept;
inline element_result operator[](const char *key) const noexcept;
~doc_result() noexcept=default;
private:
doc_result(document &&_doc, error_code _error) noexcept;
doc_result(document &&_doc) noexcept;
doc_result(error_code _error) noexcept;
~doc_move_result() noexcept=default;
doc_move_result(document &&doc, error_code error) noexcept;
doc_move_result(document &&doc) noexcept;
doc_move_result(error_code error) noexcept;
friend class document;
}; // class document::doc_result
}; // class document::doc_move_result
/**
* A parsed document reference, or an error if the parse failed.
@ -333,26 +333,23 @@ private:
* document &doc = document::parse(json);
*
*/
class document::doc_ref_result {
class document::doc_result : public simdjson_result<document&> {
public:
/**
* The parsed document. This is *invalid* if there is an error.
*/
document &doc;
/**
* The error code, or SUCCESS (0) if there is no error.
*/
error_code error;
#if SIMDJSON_EXCEPTIONS
/**
* A reference to the document, or throw an exception if it is invalid.
* Read this document as a JSON objec.
*
* @return the document.
* @exception simdjson_error if the document is invalid or there was an error parsing it.
* @return The object value, or:
* - UNEXPECTED_TYPE if the JSON document is not an object
*/
operator document&() noexcept(false);
#endif // SIMDJSON_EXCEPTIONS
inline object_result as_object() const noexcept;
/**
* Read this document as a JSON array.
*
* @return The array value, or:
* - UNEXPECTED_TYPE if the JSON document is not an array
*/
inline array_result as_array() const noexcept;
/**
* Get the value associated with the given key.
@ -366,7 +363,7 @@ public:
* - NO_SUCH_FIELD if the field does not exist in the object
* - UNEXPECTED_TYPE if the document is not an object
*/
inline element_result<element> operator[](const std::string_view &key) const noexcept;
inline element_result operator[](const std::string_view &key) const noexcept;
/**
* Get the value associated with the given key.
@ -380,58 +377,58 @@ public:
* - NO_SUCH_FIELD if the field does not exist in the object
* - UNEXPECTED_TYPE if the document is not an object
*/
inline element_result<element> operator[](const char *key) const noexcept;
inline element_result operator[](const char *key) const noexcept;
~doc_ref_result()=default;
private:
doc_ref_result(document &_doc, error_code _error) noexcept;
~doc_result()=default;
doc_result(document &doc, error_code error) noexcept;
friend class document::parser;
friend class document::stream;
}; // class document::doc_ref_result
}; // class document::doc_result
/**
* The possible types in the tape. Internal only.
namespace internal {
/**
* The possible types in the tape. Internal only.
*/
enum class tape_type {
ROOT = 'r',
START_ARRAY = '[',
START_OBJECT = '{',
END_ARRAY = ']',
END_OBJECT = '}',
STRING = '"',
INT64 = 'l',
UINT64 = 'u',
DOUBLE = 'd',
TRUE_VALUE = 't',
FALSE_VALUE = 'f',
NULL_VALUE = 'n'
};
/**
* A reference to an element on the tape. Internal only.
*/
enum class document::tape_type {
ROOT = 'r',
START_ARRAY = '[',
START_OBJECT = '{',
END_ARRAY = ']',
END_OBJECT = '}',
STRING = '"',
INT64 = 'l',
UINT64 = 'u',
DOUBLE = 'd',
TRUE_VALUE = 't',
FALSE_VALUE = 'f',
NULL_VALUE = 'n'
};
class tape_ref {
protected:
really_inline tape_ref() noexcept;
really_inline tape_ref(const document *_doc, size_t _json_index) noexcept;
inline size_t after_element() const noexcept;
really_inline tape_type type() const noexcept;
really_inline uint64_t tape_value() const noexcept;
template<typename T>
really_inline T next_tape_value() const noexcept;
inline std::string_view get_string_view() const noexcept;
/**
* A reference to an element on the tape. Internal only.
*/
class document::tape_ref {
protected:
really_inline tape_ref() noexcept;
really_inline tape_ref(const document *_doc, size_t _json_index) noexcept;
inline size_t after_element() const noexcept;
really_inline tape_type type() const noexcept;
really_inline uint64_t tape_value() const noexcept;
template<typename T>
really_inline T next_tape_value() const noexcept;
inline std::string_view get_string_view() const noexcept;
/** The document this element references. */
const document *doc;
/** The document this element references. */
const document *doc;
/** The index of this element on `doc.tape[]` */
size_t json_index;
/** The index of this element on `doc.tape[]` */
size_t json_index;
friend class document::key_value_pair;
template<typename T>
friend class minify;
};
friend class simdjson::document::key_value_pair;
template<typename T>
friend class simdjson::minify;
};
} // namespace simdjson::internal
/**
* A JSON element.
@ -439,8 +436,11 @@ protected:
* References an element in a JSON document, representing a JSON null, boolean, string, number,
* array or object.
*/
class document::element : protected document::tape_ref {
class document::element : protected internal::tape_ref {
public:
/** Create a new, invalid element. */
really_inline element() noexcept;
/** Whether this element is a json `null`. */
really_inline bool is_null() const noexcept;
/** Whether this is a JSON `true` or `false` */
@ -462,7 +462,7 @@ public:
* @return The boolean value, or:
* - UNEXPECTED_TYPE error if the JSON element is not a boolean
*/
inline element_result<bool> as_bool() const noexcept;
inline simdjson_result<bool> as_bool() const noexcept;
/**
* Read this element as a null-terminated string.
@ -473,7 +473,7 @@ public:
* @return A `string_view` into the string, or:
* - UNEXPECTED_TYPE error if the JSON element is not a string
*/
inline element_result<const char *> as_c_str() const noexcept;
inline simdjson_result<const char *> as_c_str() const noexcept;
/**
* Read this element as a C++ string_view (string with length).
@ -484,7 +484,7 @@ public:
* @return A `string_view` into the string, or:
* - UNEXPECTED_TYPE error if the JSON element is not a string
*/
inline element_result<std::string_view> as_string() const noexcept;
inline simdjson_result<std::string_view> as_string() const noexcept;
/**
* Read this element as an unsigned integer.
@ -493,7 +493,7 @@ public:
* - UNEXPECTED_TYPE if the JSON element is not an integer
* - NUMBER_OUT_OF_RANGE if the integer doesn't fit in 64 bits or is negative
*/
inline element_result<uint64_t> as_uint64_t() const noexcept;
inline simdjson_result<uint64_t> as_uint64_t() const noexcept;
/**
* Read this element as a signed integer.
@ -502,7 +502,7 @@ public:
* - UNEXPECTED_TYPE if the JSON element is not an integer
* - NUMBER_OUT_OF_RANGE if the integer doesn't fit in 64 bits
*/
inline element_result<int64_t> as_int64_t() const noexcept;
inline simdjson_result<int64_t> as_int64_t() const noexcept;
/**
* Read this element as a floating point value.
@ -510,7 +510,7 @@ public:
* @return The double value, or:
* - UNEXPECTED_TYPE if the JSON element is not a number
*/
inline element_result<double> as_double() const noexcept;
inline simdjson_result<double> as_double() const noexcept;
/**
* Read this element as a JSON array.
@ -518,7 +518,7 @@ public:
* @return The array value, or:
* - UNEXPECTED_TYPE if the JSON element is not an array
*/
inline element_result<document::array> as_array() const noexcept;
inline array_result as_array() const noexcept;
/**
* Read this element as a JSON object (key/value pairs).
@ -526,7 +526,7 @@ public:
* @return The object value, or:
* - UNEXPECTED_TYPE if the JSON element is not an object
*/
inline element_result<document::object> as_object() const noexcept;
inline object_result as_object() const noexcept;
#if SIMDJSON_EXCEPTIONS
/**
@ -611,7 +611,7 @@ public:
* - NO_SUCH_FIELD if the field does not exist in the object
* - UNEXPECTED_TYPE if the document is not an object
*/
inline element_result<element> operator[](const std::string_view &s) const noexcept;
inline element_result operator[](const std::string_view &s) const noexcept;
/**
* Get the value associated with the given key.
@ -625,13 +625,11 @@ public:
* - NO_SUCH_FIELD if the field does not exist in the object
* - UNEXPECTED_TYPE if the document is not an object
*/
inline element_result<element> operator[](const char *s) const noexcept;
inline element_result operator[](const char *s) const noexcept;
private:
really_inline element() noexcept;
really_inline element(const document *_doc, size_t _json_index) noexcept;
friend class document;
template<typename T>
friend class document::element_result;
template<typename T>
friend class minify;
@ -640,8 +638,11 @@ private:
/**
* Represents a JSON array.
*/
class document::array : protected document::tape_ref {
class document::array : protected internal::tape_ref {
public:
/** Create a new, invalid array */
really_inline array() noexcept;
class iterator : tape_ref {
public:
/**
@ -679,10 +680,8 @@ public:
inline iterator end() const noexcept;
private:
really_inline array() noexcept;
really_inline array(const document *_doc, size_t _json_index) noexcept;
friend class document::element;
template<typename T>
friend class document::element_result;
template<typename T>
friend class minify;
@ -691,9 +690,12 @@ private:
/**
* Represents a JSON object.
*/
class document::object : protected document::tape_ref {
class document::object : protected internal::tape_ref {
public:
class iterator : protected document::tape_ref {
/** Create a new, invalid object */
really_inline object() noexcept;
class iterator : protected internal::tape_ref {
public:
/**
* Get the actual key/value pair
@ -752,7 +754,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<element> operator[](const std::string_view &s) const noexcept;
inline element_result operator[](const std::string_view &s) const noexcept;
/**
* Get the value associated with the given key.
@ -765,13 +767,11 @@ public:
* @return The value associated with this field, or:
* - NO_SUCH_FIELD if the field does not exist in the object
*/
inline element_result<element> operator[](const char *s) const noexcept;
inline element_result operator[](const char *s) const noexcept;
private:
really_inline object() noexcept;
really_inline object(const document *_doc, size_t _json_index) noexcept;
friend class document::element;
template<typename T>
friend class document::element_result;
template<typename T>
friend class minify;
@ -791,63 +791,27 @@ private:
};
/**
* The result of a JSON navigation or conversion, or an error (if the navigation or conversion
* failed). Allows the user to pick whether to use exceptions or not.
*
* Use like this to avoid exceptions:
*
* auto [str, error] = document::parse(json).root().as_string();
* if (error) { exit(1); }
* cout << str;
*
* Use like this if you'd prefer to use exceptions:
*
* string str = document::parse(json).root();
* cout << str;
*
*/
template<typename T>
class document::element_result {
/** The result of a JSON navigation that may fail. */
class document::element_result : public simdjson_result<document::element> {
public:
/** The value */
T value;
/** The error code (or 0 if there is no error) */
error_code error;
#if SIMDJSON_EXCEPTIONS
inline operator T() const noexcept(false);
#endif // SIMDJSON_EXCEPTIONS
private:
really_inline element_result(T value) noexcept;
really_inline element_result(error_code _error) noexcept;
friend class document;
friend class element;
};
// Add exception-throwing navigation / conversion methods to element_result<element>
template<>
class document::element_result<document::element> {
public:
/** The value */
element value;
/** The error code (or 0 if there is no error) */
error_code error;
really_inline element_result(element value) noexcept;
really_inline element_result(error_code error) noexcept;
/** Whether this is a JSON `null` */
inline element_result<bool> is_null() const noexcept;
inline element_result<bool> as_bool() const noexcept;
inline element_result<std::string_view> as_string() const noexcept;
inline element_result<const char *> as_c_str() const noexcept;
inline element_result<uint64_t> as_uint64_t() const noexcept;
inline element_result<int64_t> as_int64_t() const noexcept;
inline element_result<double> as_double() const noexcept;
inline element_result<array> as_array() const noexcept;
inline element_result<object> as_object() const noexcept;
inline simdjson_result<bool> is_null() const noexcept;
inline simdjson_result<bool> as_bool() const noexcept;
inline simdjson_result<std::string_view> as_string() const noexcept;
inline simdjson_result<const char *> as_c_str() const noexcept;
inline simdjson_result<uint64_t> as_uint64_t() const noexcept;
inline simdjson_result<int64_t> as_int64_t() const noexcept;
inline simdjson_result<double> as_double() const noexcept;
inline array_result as_array() const noexcept;
inline object_result as_object() const noexcept;
inline element_result operator[](const std::string_view &s) const noexcept;
inline element_result operator[](const char *s) const noexcept;
#if SIMDJSON_EXCEPTIONS
inline operator element() const noexcept(false);
inline operator bool() const noexcept(false);
inline explicit operator const char*() const noexcept(false);
inline operator std::string_view() const noexcept(false);
@ -857,64 +821,33 @@ public:
inline operator array() const noexcept(false);
inline operator object() const noexcept(false);
#endif // SIMDJSON_EXCEPTIONS
inline element_result<element> operator[](const std::string_view &s) const noexcept;
inline element_result<element> operator[](const char *s) const noexcept;
private:
really_inline element_result(element value) noexcept;
really_inline element_result(error_code _error) noexcept;
friend class document;
friend class element;
};
// Add exception-throwing navigation methods to element_result<array>
template<>
class document::element_result<document::array> {
/** The result of a JSON conversion that may fail. */
class document::array_result : public simdjson_result<document::array> {
public:
/** The value */
array value;
/** The error code (or 0 if there is no error) */
error_code error;
really_inline array_result(array value) noexcept;
really_inline array_result(error_code error) noexcept;
#if SIMDJSON_EXCEPTIONS
inline operator array() const noexcept(false);
inline array::iterator begin() const noexcept(false);
inline array::iterator end() const noexcept(false);
#endif // SIMDJSON_EXCEPTIONS
private:
really_inline element_result(array value) noexcept;
really_inline element_result(error_code _error) noexcept;
friend class document;
friend class element;
};
// Add exception-throwing navigation methods to element_result<object>
template<>
class document::element_result<document::object> {
/** The result of a JSON conversion that may fail. */
class document::object_result : public simdjson_result<document::object> {
public:
/** The value */
object value;
/** The error code (or 0 if there is no error) */
error_code error;
really_inline object_result(object value) noexcept;
really_inline object_result(error_code error) noexcept;
inline element_result operator[](const std::string_view &s) const noexcept;
inline element_result operator[](const char *s) const noexcept;
#if SIMDJSON_EXCEPTIONS
inline operator object() const noexcept(false);
inline object::iterator begin() const noexcept(false);
inline object::iterator end() const noexcept(false);
#endif // SIMDJSON_EXCEPTIONS
inline element_result<element> operator[](const std::string_view &s) const noexcept;
inline element_result<element> operator[](const char *s) const noexcept;
private:
really_inline element_result(object value) noexcept;
really_inline element_result(error_code _error) noexcept;
friend class document;
friend class element;
};
/**
@ -985,7 +918,7 @@ public:
* - CAPACITY if the parser does not have enough capacity and len > max_capacity.
* - other json errors if parsing fails.
*/
inline doc_ref_result load(const std::string& path) noexcept;
inline doc_result load(const std::string& path) noexcept;
/**
* Load a file containing many JSON documents.
@ -1079,7 +1012,7 @@ public:
* - CAPACITY if the parser does not have enough capacity and len > max_capacity.
* - other json errors if parsing fails.
*/
inline doc_ref_result parse(const uint8_t *buf, size_t len, bool realloc_if_needed = true) noexcept;
inline doc_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.
@ -1116,7 +1049,7 @@ public:
* - CAPACITY if the parser does not have enough capacity and len > max_capacity.
* - other json errors if parsing fails.
*/
really_inline doc_ref_result parse(const char *buf, size_t len, bool realloc_if_needed = true) noexcept;
really_inline doc_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.
@ -1151,7 +1084,7 @@ public:
* - CAPACITY if the parser does not have enough capacity and len > max_capacity.
* - other json errors if parsing fails.
*/
really_inline doc_ref_result parse(const std::string &s) noexcept;
really_inline doc_result parse(const std::string &s) noexcept;
/**
* Parse a JSON document and return a temporary reference to it.
@ -1176,10 +1109,10 @@ public:
* - CAPACITY if the parser does not have enough capacity and len > max_capacity.
* - other json errors if parsing fails.
*/
really_inline doc_ref_result parse(const padded_string &s) noexcept;
really_inline doc_result parse(const padded_string &s) noexcept;
// We do not want to allow implicit conversion from C string to std::string.
really_inline doc_ref_result parse(const char *buf) noexcept = delete;
really_inline doc_result parse(const char *buf) noexcept = delete;
/**
* Parse a buffer containing many JSON documents.
@ -1423,7 +1356,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 doc_ref_result parse_many(const char *buf, size_t batch_size = DEFAULT_BATCH_SIZE) noexcept = delete;
really_inline doc_result parse_many(const char *buf, size_t batch_size = DEFAULT_BATCH_SIZE) noexcept = delete;
/**
* The largest document this parser can automatically support.
@ -1603,7 +1536,7 @@ private:
//
//
inline void write_tape(uint64_t val, tape_type t) noexcept;
inline void write_tape(uint64_t val, internal::tape_type t) noexcept;
inline void annotate_previous_loc(uint32_t saved_loc, uint64_t val) noexcept;
// Ensure we have enough capacity to handle at least desired_capacity bytes,
@ -1709,6 +1642,18 @@ inline std::ostream& operator<<(std::ostream& out, const document::object &value
* @throw if there is an error with the underlying output stream. simdjson itself will not throw.
*/
inline std::ostream& operator<<(std::ostream& out, const document::key_value_pair &value) { return out << minify(value); }
/**
* Print JSON to an output stream.
*
* By default, the value will be printed minified.
*
* @param out The output stream.
* @param value The value to print.
* @throw simdjson_error if the result being printed has an error. If there is an error with the
* underlying output stream, that error will be propagated (simdjson_error will not be
* thrown).
*/
inline std::ostream& operator<<(std::ostream& out, const document::doc_move_result &value) noexcept(false) { return out << minify(value); }
/**
* Print JSON to an output stream.
*
@ -1732,7 +1677,7 @@ inline std::ostream& operator<<(std::ostream& out, const document::doc_result &v
* underlying output stream, that error will be propagated (simdjson_error will not be
* thrown).
*/
inline std::ostream& operator<<(std::ostream& out, const document::doc_ref_result &value) noexcept(false) { return out << minify(value); }
inline std::ostream& operator<<(std::ostream& out, const document::element_result &value) noexcept(false) { return out << minify(value); }
/**
* Print JSON to an output stream.
*
@ -1744,7 +1689,7 @@ inline std::ostream& operator<<(std::ostream& out, const document::doc_ref_resul
* 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<document::element> &value) noexcept(false) { return out << minify(value); }
inline std::ostream& operator<<(std::ostream& out, const document::array_result &value) noexcept(false) { return out << minify(value); }
/**
* Print JSON to an output stream.
*
@ -1756,19 +1701,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::element_result<document::array> &value) noexcept(false) { return out << minify(value); }
/**
* Print JSON to an output stream.
*
* By default, the value will be printed minified.
*
* @param out The output stream.
* @param value The value to print.
* @throw simdjson_error if the result being printed has an error. If there is an error with the
* 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<document::object> &value) noexcept(false) { return out << minify(value); }
inline std::ostream& operator<<(std::ostream& out, const document::object_result &value) noexcept(false) { return out << minify(value); }
} // namespace simdjson

View File

@ -15,7 +15,9 @@ namespace simdjson {
template <size_t max_depth> class document_iterator {
public:
document_iterator(const document::parser &parser);
#if SIMDJSON_EXCEPTIONS
document_iterator(const document::parser &parser) noexcept(false);
#endif
document_iterator(const document &doc) noexcept;
document_iterator(const document_iterator &o) noexcept;
document_iterator &operator=(const document_iterator &o) noexcept;

View File

@ -26,7 +26,7 @@ public:
/**
* Get the current document (or error).
*/
really_inline doc_ref_result operator*() noexcept;
really_inline doc_result operator*() noexcept;
/**
* Advance to the next document.
*/

View File

@ -2,6 +2,7 @@
#define SIMDJSON_ERROR_H
#include <string>
#include <utility>
namespace simdjson {
@ -61,6 +62,7 @@ struct simdjson_error : public std::exception {
simdjson_error(error_code error) noexcept : _error{error} { }
/** The error message */
const char *what() const noexcept { return error_message(error()); }
/** The error code */
error_code error() const noexcept { return _error; }
private:
/** The error code that was used */
@ -73,34 +75,90 @@ private:
* Gives the option of reading error codes, or throwing an exception by casting to the desired result.
*/
template<typename T>
struct simdjson_result {
struct simdjson_result : public std::pair<T, error_code> {
/**
* The value of the function.
*
* Undefined if error is true.
* @throw simdjson_error if there was an error.
*/
T value;
T get() noexcept(false) {
if (error()) { throw simdjson_error(error()); }
return this->first;
};
/**
* The error.
*/
error_code error;
error_code error() const { return this->second; }
/**
* Cast to the value (will throw on error).
*
* @throw simdjson_error if there was an error.
*/
operator T() noexcept(false) {
if (error) { throw simdjson_error(error); }
return std::move(value);
}
operator T() noexcept(false) { return get(); }
/**
* Create a new error result.
*/
simdjson_result(error_code _error) noexcept : value{}, error{_error} {}
simdjson_result(error_code _error) noexcept : std::pair<T, error_code>({}, _error) {}
/**
* Create a new successful result.
*/
simdjson_result(T _value) noexcept : value{std::move(_value)}, error{SUCCESS} {}
simdjson_result(T _value) noexcept : std::pair<T, error_code>(_value, SUCCESS) {}
/**
* 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>(value, error) {}
};
/**
* The result of a simd operation that could fail.
*
* This class is for values that must be *moved*, like padded_string and document.
*
* Gives the option of reading error codes, or throwing an exception by casting to the desired result.
*/
template<typename T>
struct simdjson_move_result : std::pair<T, error_code> {
/**
* The error.
*/
error_code error() const { return this->second; }
/**
* The value of the function.
*
* @throw simdjson_error if there was an error.
*/
T move() noexcept(false) {
if (error()) { throw simdjson_error(error()); }
return std::move(this->first);
};
/**
* Cast to the value (will throw on error).
*
* @throw simdjson_error if there was an error.
*/
operator T() noexcept(false) { return move(); }
/**
* Create a new error result.
*/
simdjson_move_result(error_code error) noexcept : std::pair<T, error_code>(T(), error) {}
/**
* Create a new successful result.
*/
simdjson_move_result(T value) noexcept : std::pair<T, error_code>(std::move(value), SUCCESS) {}
/**
* Create a new result with both things (use if you don't want to branch when creating the result).
*/
simdjson_move_result(T value, error_code error) noexcept : std::pair<T, error_code>(std::move(value), error) {}
};
/**

View File

@ -13,227 +13,184 @@
namespace simdjson {
//
// document::element_result<T> inline implementation
// element_result inline implementation
//
template<typename T>
inline document::element_result<T>::element_result(T _value) noexcept : value(_value), error{SUCCESS} {}
template<typename T>
inline document::element_result<T>::element_result(error_code _error) noexcept : value(), error{_error} {}
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<element>(error) {}
inline simdjson_result<bool> document::element_result::is_null() const noexcept {
if (error()) { return error(); }
return first.is_null();
}
inline simdjson_result<bool> document::element_result::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 {
if (error()) { return error(); }
return first.as_c_str();
}
inline simdjson_result<std::string_view> document::element_result::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 {
if (error()) { return error(); }
return first.as_uint64_t();
}
inline simdjson_result<int64_t> document::element_result::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 {
if (error()) { return error(); }
return first.as_double();
}
inline document::array_result document::element_result::as_array() const noexcept {
if (error()) { return error(); }
return first.as_array();
}
inline document::object_result document::element_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 &key) const noexcept {
if (error()) { return *this; }
return first[key];
}
inline document::element_result document::element_result::operator[](const char *key) const noexcept {
if (error()) { return *this; }
return first[key];
}
#if SIMDJSON_EXCEPTIONS
template<>
inline document::element_result<std::string_view>::operator std::string_view() const noexcept(false) {
if (error) { throw simdjson_error(error); }
return value;
}
template<>
inline document::element_result<const char *>::operator const char *() const noexcept(false) {
if (error) { throw simdjson_error(error); }
return value;
}
template<>
inline document::element_result<bool>::operator bool() const noexcept(false) {
if (error) { throw simdjson_error(error); }
return value;
}
template<>
inline document::element_result<uint64_t>::operator uint64_t() const noexcept(false) {
if (error) { throw simdjson_error(error); }
return value;
}
template<>
inline document::element_result<int64_t>::operator int64_t() const noexcept(false) {
if (error) { throw simdjson_error(error); }
return value;
}
template<>
inline document::element_result<double>::operator double() const noexcept(false) {
if (error) { throw simdjson_error(error); }
return value;
}
#endif // SIMDJSON_EXCEPTIONS
//
// document::element_result<document::array> inline implementation
//
inline document::element_result<document::array>::element_result(document::array _value) noexcept : value(_value), error{SUCCESS} {}
inline document::element_result<document::array>::element_result(error_code _error) noexcept : value(), error{_error} {}
#if SIMDJSON_EXCEPTIONS
inline document::element_result<document::array>::operator document::array() const noexcept(false) {
if (error) { throw simdjson_error(error); }
return value;
}
inline document::array::iterator document::element_result<document::array>::begin() const noexcept(false) {
if (error) { throw simdjson_error(error); }
return value.begin();
}
inline document::array::iterator document::element_result<document::array>::end() const noexcept(false) {
if (error) { throw simdjson_error(error); }
return value.end();
}
#endif // SIMDJSON_EXCEPTIONS
//
// document::element_result<document::object> inline implementation
//
inline document::element_result<document::object>::element_result(document::object _value) noexcept : value(_value), error{SUCCESS} {}
inline document::element_result<document::object>::element_result(error_code _error) noexcept : value(), error{_error} {}
#if SIMDJSON_EXCEPTIONS
inline document::element_result<document::object>::operator document::object() const noexcept(false) {
if (error) { throw simdjson_error(error); }
return value;
}
inline document::element_result<document::element> document::element_result<document::object>::operator[](const std::string_view &key) const noexcept {
if (error) { return error; }
return value[key];
}
inline document::element_result<document::element> document::element_result<document::object>::operator[](const char *key) const noexcept {
if (error) { return error; }
return value[key];
}
inline document::object::iterator document::element_result<document::object>::begin() const noexcept(false) {
if (error) { throw simdjson_error(error); }
return value.begin();
}
inline document::object::iterator document::element_result<document::object>::end() const noexcept(false) {
if (error) { throw simdjson_error(error); }
return value.end();
}
#endif // SIMDJSON_EXCEPTIONS
//
// document::element_result<document::element> inline implementation
//
inline document::element_result<document::element>::element_result(document::element _value) noexcept : value(_value), error{SUCCESS} {}
inline document::element_result<document::element>::element_result(error_code _error) noexcept : value(), error{_error} {}
inline document::element_result<bool> document::element_result<document::element>::is_null() const noexcept {
if (error) { return error; }
return value.is_null();
}
inline document::element_result<bool> document::element_result<document::element>::as_bool() const noexcept {
if (error) { return error; }
return value.as_bool();
}
inline document::element_result<const char*> document::element_result<document::element>::as_c_str() const noexcept {
if (error) { return error; }
return value.as_c_str();
}
inline document::element_result<std::string_view> document::element_result<document::element>::as_string() const noexcept {
if (error) { return error; }
return value.as_string();
}
inline document::element_result<uint64_t> document::element_result<document::element>::as_uint64_t() const noexcept {
if (error) { return error; }
return value.as_uint64_t();
}
inline document::element_result<int64_t> document::element_result<document::element>::as_int64_t() const noexcept {
if (error) { return error; }
return value.as_int64_t();
}
inline document::element_result<double> document::element_result<document::element>::as_double() const noexcept {
if (error) { return error; }
return value.as_double();
}
inline document::element_result<document::array> document::element_result<document::element>::as_array() const noexcept {
if (error) { return error; }
return value.as_array();
}
inline document::element_result<document::object> document::element_result<document::element>::as_object() const noexcept {
if (error) { return error; }
return value.as_object();
}
inline document::element_result<document::element>::operator document::element() const noexcept(false) {
if (error) { throw simdjson_error(error); }
return value;
}
inline document::element_result<document::element>::operator bool() const noexcept(false) {
inline document::element_result::operator bool() const noexcept(false) {
return as_bool();
}
inline document::element_result<document::element>::operator const char *() const noexcept(false) {
inline document::element_result::operator const char *() const noexcept(false) {
return as_c_str();
}
inline document::element_result<document::element>::operator std::string_view() const noexcept(false) {
inline document::element_result::operator std::string_view() const noexcept(false) {
return as_string();
}
inline document::element_result<document::element>::operator uint64_t() const noexcept(false) {
inline document::element_result::operator uint64_t() const noexcept(false) {
return as_uint64_t();
}
inline document::element_result<document::element>::operator int64_t() const noexcept(false) {
inline document::element_result::operator int64_t() const noexcept(false) {
return as_int64_t();
}
inline document::element_result<document::element>::operator double() const noexcept(false) {
inline document::element_result::operator double() const noexcept(false) {
return as_double();
}
inline document::element_result<document::element>::operator document::array() const noexcept(false) {
inline document::element_result::operator document::array() const noexcept(false) {
return as_array();
}
inline document::element_result<document::element>::operator document::object() const noexcept(false) {
inline document::element_result::operator document::object() const noexcept(false) {
return as_object();
}
inline document::element_result<document::element> document::element_result<document::element>::operator[](const std::string_view &key) const noexcept {
if (error) { return *this; }
return value[key];
#endif
//
// array_result inline implementation
//
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<array>(error) {}
#if SIMDJSON_EXCEPTIONS
inline document::array::iterator document::array_result::begin() const noexcept(false) {
if (error()) { throw simdjson_error(error()); }
return first.begin();
}
inline document::element_result<document::element> document::element_result<document::element>::operator[](const char *key) const noexcept {
if (error) { return *this; }
return value[key];
inline document::array::iterator document::array_result::end() const noexcept(false) {
if (error()) { throw simdjson_error(error()); }
return first.end();
}
#endif // SIMDJSON_EXCEPTIONS
//
// object_result inline implementation
//
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<object>(error) {}
inline document::element_result document::object_result::operator[](const std::string_view &key) const noexcept {
if (error()) { return error(); }
return first[key];
}
inline document::element_result document::object_result::operator[](const char *key) const noexcept {
if (error()) { return error(); }
return first[key];
}
#if SIMDJSON_EXCEPTIONS
inline document::object::iterator document::object_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) {
if (error()) { throw simdjson_error(error()); }
return first.end();
}
#endif // SIMDJSON_EXCEPTIONS
//
// document inline implementation
//
inline document::element document::root() const noexcept {
return document::element(this, 1);
return element(this, 1);
}
inline document::element_result<document::array> document::as_array() const noexcept {
inline document::array_result document::as_array() const noexcept {
return root().as_array();
}
inline document::element_result<document::object> document::as_object() const noexcept {
inline document::object_result document::as_object() const noexcept {
return root().as_object();
}
inline document::operator document::element() const noexcept {
inline document::operator element() const noexcept {
return root();
}
#if SIMDJSON_EXCEPTIONS
inline document::operator document::array() const noexcept(false) {
return root();
}
inline document::operator document::object() const noexcept(false) {
return root();
}
inline document::element_result<document::element> document::operator[](const std::string_view &key) const noexcept {
#endif
inline document::element_result document::operator[](const std::string_view &key) const noexcept {
return root()[key];
}
inline document::element_result<document::element> document::operator[](const char *key) const noexcept {
inline document::element_result document::operator[](const char *key) const noexcept {
return root()[key];
}
inline document::doc_result document::load(const std::string &path) noexcept {
inline document::doc_move_result document::load(const std::string &path) noexcept {
document::parser parser;
auto [doc, error] = parser.load(path);
return document::doc_result((document &&)doc, error);
return doc_move_result((document &&)doc, error);
}
inline document::doc_result document::parse(const uint8_t *buf, size_t len, bool realloc_if_needed) noexcept {
inline document::doc_move_result document::parse(const uint8_t *buf, size_t len, bool realloc_if_needed) noexcept {
document::parser parser;
auto [doc, error] = parser.parse(buf, len, realloc_if_needed);
return document::doc_result((document &&)doc, error);
return doc_move_result((document &&)doc, error);
}
really_inline document::doc_result document::parse(const char *buf, size_t len, bool realloc_if_needed) noexcept {
really_inline document::doc_move_result document::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::doc_result document::parse(const std::string &s) noexcept {
really_inline document::doc_move_result document::parse(const std::string &s) noexcept {
return parse(s.data(), s.length(), s.capacity() - s.length() < SIMDJSON_PADDING);
}
really_inline document::doc_result document::parse(const padded_string &s) noexcept {
really_inline document::doc_move_result document::parse(const padded_string &s) noexcept {
return parse(s.data(), s.length(), false);
}
@ -353,50 +310,52 @@ inline bool document::dump_raw_tape(std::ostream &os) const noexcept {
}
//
// document::doc_ref_result inline implementation
// doc_result inline implementation
//
inline document::doc_ref_result::doc_ref_result(document &_doc, error_code _error) noexcept : doc(_doc), error(_error) { }
inline document::doc_result::doc_result(document &doc, error_code error) noexcept : simdjson_result<document&>(doc, error) { }
#if SIMDJSON_EXCEPTIONS
inline document::doc_ref_result::operator document&() noexcept(false) {
if (error) { throw simdjson_error(error); }
return doc;
inline document::array_result document::doc_result::as_array() const noexcept {
if (error()) { return error(); }
return first.root().as_array();
}
inline document::element_result<document::element> document::doc_ref_result::operator[](const std::string_view &key) const noexcept {
if (error) { return error; }
return doc[key];
}
inline document::element_result<document::element> document::doc_ref_result::operator[](const char *key) const noexcept {
if (error) { return error; }
return doc[key];
inline document::object_result document::doc_result::as_object() const noexcept {
if (error()) { return error(); }
return first.root().as_object();
}
#endif // SIMDJSON_EXCEPTIONS
inline document::element_result document::doc_result::operator[](const std::string_view &key) const noexcept {
if (error()) { return error(); }
return first[key];
}
inline document::element_result document::doc_result::operator[](const char *key) const noexcept {
if (error()) { return error(); }
return first[key];
}
//
// document::doc_result inline implementation
// doc_move_result inline implementation
//
inline document::doc_result::doc_result(document &&_doc, error_code _error) noexcept : doc(std::move(_doc)), error(_error) { }
inline document::doc_result::doc_result(document &&_doc) noexcept : doc(std::move(_doc)), error(SUCCESS) { }
inline document::doc_result::doc_result(error_code _error) noexcept : doc(), error(_error) { }
inline document::doc_move_result::doc_move_result(document &&doc, error_code error) noexcept : simdjson_move_result<document>(std::move(doc), error) { }
inline document::doc_move_result::doc_move_result(document &&doc) noexcept : simdjson_move_result<document>(std::move(doc)) { }
inline document::doc_move_result::doc_move_result(error_code error) noexcept : simdjson_move_result<document>(error) { }
#if SIMDJSON_EXCEPTIONS
inline document::doc_result::operator document() noexcept(false) {
if (error) { throw simdjson_error(error); }
return std::move(doc);
inline document::array_result document::doc_move_result::as_array() const noexcept {
if (error()) { return error(); }
return first.root().as_array();
}
inline document::element_result<document::element> document::doc_result::operator[](const std::string_view &key) const noexcept {
if (error) { return error; }
return doc[key];
}
inline document::element_result<document::element> document::doc_result::operator[](const char *key) const noexcept {
if (error) { return error; }
return doc[key];
inline document::object_result document::doc_move_result::as_object() const noexcept {
if (error()) { return error(); }
return first.root().as_object();
}
#endif // SIMDJSON_EXCEPTIONS
inline document::element_result document::doc_move_result::operator[](const std::string_view &key) const noexcept {
if (error()) { return error(); }
return first[key];
}
inline document::element_result document::doc_move_result::operator[](const char *key) const noexcept {
if (error()) { return error(); }
return first[key];
}
//
// document::parser inline implementation
@ -428,9 +387,9 @@ inline const document &document::parser::get_document() const noexcept(false) {
#endif // SIMDJSON_EXCEPTIONS
inline document::doc_ref_result document::parser::load(const std::string &path) noexcept {
inline document::doc_result document::parser::load(const std::string &path) noexcept {
auto [json, _error] = padded_string::load(path);
if (_error) { return doc_ref_result(doc, _error); }
if (_error) { return doc_result(doc, _error); }
return parse(json);
}
@ -439,35 +398,35 @@ inline document::stream document::parser::load_many(const std::string &path, siz
return stream(*this, reinterpret_cast<const uint8_t*>(json.data()), json.length(), batch_size, _error);
}
inline document::doc_ref_result document::parser::parse(const uint8_t *buf, size_t len, bool realloc_if_needed) noexcept {
inline document::doc_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 document::doc_ref_result(doc, code); }
if (code) { return doc_result(doc, code); }
if (realloc_if_needed) {
const uint8_t *tmp_buf = buf;
buf = (uint8_t *)internal::allocate_padded_buffer(len);
if (buf == nullptr)
return document::doc_ref_result(doc, MEMALLOC);
return doc_result(doc, MEMALLOC);
memcpy((void *)buf, tmp_buf, len);
}
code = simdjson::active_implementation->parse(buf, len, *this);
// We're indicating validity via the doc_ref_result, so set the parse state back to invalid
// We're indicating validity via the doc_result, so set the parse state back to invalid
valid = false;
error = UNINITIALIZED;
if (realloc_if_needed) {
aligned_free((void *)buf); // must free before we exit
}
return document::doc_ref_result(doc, code);
return doc_result(doc, code);
}
really_inline document::doc_ref_result document::parser::parse(const char *buf, size_t len, bool realloc_if_needed) noexcept {
really_inline document::doc_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::doc_ref_result document::parser::parse(const std::string &s) noexcept {
really_inline document::doc_result document::parser::parse(const std::string &s) noexcept {
return parse(s.data(), s.length(), s.capacity() - s.length() < SIMDJSON_PADDING);
}
really_inline document::doc_ref_result document::parser::parse(const padded_string &s) noexcept {
really_inline document::doc_result document::parser::parse(const padded_string &s) noexcept {
return parse(s.data(), s.length(), false);
}
@ -593,12 +552,12 @@ inline error_code document::parser::ensure_capacity(size_t desired_capacity) noe
}
//
// document::tape_ref inline implementation
// tape_ref inline implementation
//
really_inline document::tape_ref::tape_ref() noexcept : doc{nullptr}, json_index{0} {}
really_inline document::tape_ref::tape_ref(const document *_doc, size_t _json_index) noexcept : doc{_doc}, json_index{_json_index} {}
really_inline internal::tape_ref::tape_ref() noexcept : doc{nullptr}, json_index{0} {}
really_inline internal::tape_ref::tape_ref(const document *_doc, size_t _json_index) noexcept : doc{_doc}, json_index{_json_index} {}
inline size_t document::tape_ref::after_element() const noexcept {
inline size_t internal::tape_ref::after_element() const noexcept {
switch (type()) {
case tape_type::START_ARRAY:
case tape_type::START_OBJECT:
@ -611,18 +570,18 @@ inline size_t document::tape_ref::after_element() const noexcept {
return json_index + 1;
}
}
really_inline document::tape_type document::tape_ref::type() const noexcept {
really_inline internal::tape_type internal::tape_ref::type() const noexcept {
return static_cast<tape_type>(doc->tape[json_index] >> 56);
}
really_inline uint64_t document::tape_ref::tape_value() const noexcept {
really_inline uint64_t internal::tape_ref::tape_value() const noexcept {
return doc->tape[json_index] & internal::JSON_VALUE_MASK;
}
template<typename T>
really_inline T document::tape_ref::next_tape_value() const noexcept {
really_inline T internal::tape_ref::next_tape_value() const noexcept {
static_assert(sizeof(T) == sizeof(uint64_t));
return *reinterpret_cast<const T*>(&doc->tape[json_index + 1]);
}
inline std::string_view document::tape_ref::get_string_view() const noexcept {
inline std::string_view internal::tape_ref::get_string_view() const noexcept {
size_t string_buf_index = tape_value();
uint32_t len;
memcpy(&len, &doc->string_buf[string_buf_index], sizeof(len));
@ -633,10 +592,10 @@ inline std::string_view document::tape_ref::get_string_view() const noexcept {
}
//
// document::array inline implementation
// array inline implementation
//
really_inline document::array::array() noexcept : tape_ref() {}
really_inline document::array::array(const document *_doc, size_t _json_index) noexcept : tape_ref(_doc, _json_index) {}
really_inline document::array::array() noexcept : internal::tape_ref() {}
really_inline document::array::array(const document *_doc, size_t _json_index) noexcept : internal::tape_ref(_doc, _json_index) {}
inline document::array::iterator document::array::begin() const noexcept {
return iterator(doc, json_index + 1);
}
@ -648,7 +607,7 @@ inline document::array::iterator document::array::end() const noexcept {
//
// document::array::iterator inline implementation
//
really_inline document::array::iterator::iterator(const document *_doc, size_t _json_index) noexcept : tape_ref(_doc, _json_index) { }
really_inline document::array::iterator::iterator(const document *_doc, size_t _json_index) noexcept : internal::tape_ref(_doc, _json_index) { }
inline document::element document::array::iterator::operator*() const noexcept {
return element(doc, json_index);
}
@ -660,17 +619,17 @@ inline void document::array::iterator::operator++() noexcept {
}
//
// document::object inline implementation
// object inline implementation
//
really_inline document::object::object() noexcept : tape_ref() {}
really_inline document::object::object(const document *_doc, size_t _json_index) noexcept : tape_ref(_doc, _json_index) { };
really_inline document::object::object() noexcept : internal::tape_ref() {}
really_inline document::object::object(const document *_doc, size_t _json_index) noexcept : internal::tape_ref(_doc, _json_index) { };
inline document::object::iterator document::object::begin() const noexcept {
return iterator(doc, json_index + 1);
}
inline document::object::iterator document::object::end() const noexcept {
return iterator(doc, after_element() - 1);
}
inline document::element_result<document::element> document::object::operator[](const std::string_view &key) const noexcept {
inline document::element_result document::object::operator[](const std::string_view &key) const noexcept {
iterator end_field = end();
for (iterator field = begin(); field != end_field; ++field) {
if (key == field.key()) {
@ -679,7 +638,7 @@ inline document::element_result<document::element> document::object::operator[](
}
return NO_SUCH_FIELD;
}
inline document::element_result<document::element> document::object::operator[](const char *key) const noexcept {
inline document::element_result document::object::operator[](const char *key) const noexcept {
iterator end_field = end();
for (iterator field = begin(); field != end_field; ++field) {
if (!strcmp(key, field.key_c_str())) {
@ -692,7 +651,7 @@ inline document::element_result<document::element> document::object::operator[](
//
// document::object::iterator inline implementation
//
really_inline document::object::iterator::iterator(const document *_doc, size_t _json_index) noexcept : tape_ref(_doc, _json_index) { }
really_inline document::object::iterator::iterator(const document *_doc, size_t _json_index) noexcept : internal::tape_ref(_doc, _json_index) { }
inline const document::key_value_pair document::object::iterator::operator*() const noexcept {
return key_value_pair(key(), value());
}
@ -722,35 +681,39 @@ inline document::element document::object::iterator::value() const noexcept {
//
// document::key_value_pair inline implementation
//
inline document::key_value_pair::key_value_pair(std::string_view _key, document::element _value) noexcept :
inline document::key_value_pair::key_value_pair(std::string_view _key, element _value) noexcept :
key(_key), value(_value) {}
//
// document::element inline implementation
// element inline implementation
//
really_inline document::element::element() noexcept : tape_ref() {}
really_inline document::element::element(const document *_doc, size_t _json_index) noexcept : tape_ref(_doc, _json_index) { }
really_inline document::element::element() noexcept : internal::tape_ref() {}
really_inline document::element::element(const document *_doc, size_t _json_index) noexcept : internal::tape_ref(_doc, _json_index) { }
really_inline bool document::element::is_null() const noexcept {
return type() == tape_type::NULL_VALUE;
return type() == internal::tape_type::NULL_VALUE;
}
really_inline bool document::element::is_bool() const noexcept {
return type() == tape_type::TRUE_VALUE || type() == tape_type::FALSE_VALUE;
return type() == internal::tape_type::TRUE_VALUE || type() == internal::tape_type::FALSE_VALUE;
}
really_inline bool document::element::is_number() const noexcept {
return type() == tape_type::UINT64 || type() == tape_type::INT64 || type() == tape_type::DOUBLE;
return type() == internal::tape_type::UINT64 || type() == internal::tape_type::INT64 || type() == internal::tape_type::DOUBLE;
}
really_inline bool document::element::is_integer() const noexcept {
return type() == tape_type::UINT64 || type() == tape_type::INT64;
return type() == internal::tape_type::UINT64 || type() == internal::tape_type::INT64;
}
really_inline bool document::element::is_string() const noexcept {
return type() == tape_type::STRING;
return type() == internal::tape_type::STRING;
}
really_inline bool document::element::is_array() const noexcept {
return type() == tape_type::START_ARRAY;
return type() == internal::tape_type::START_ARRAY;
}
really_inline bool document::element::is_object() const noexcept {
return type() == tape_type::START_OBJECT;
return type() == internal::tape_type::START_OBJECT;
}
#if SIMDJSON_EXCEPTIONS
inline document::element::operator bool() const noexcept(false) { return as_bool(); }
inline document::element::operator const char*() const noexcept(false) { return as_c_str(); }
inline document::element::operator std::string_view() const noexcept(false) { return as_string(); }
@ -759,19 +722,22 @@ inline document::element::operator int64_t() const noexcept(false) { return as_i
inline document::element::operator double() const noexcept(false) { return as_double(); }
inline document::element::operator document::array() const noexcept(false) { return as_array(); }
inline document::element::operator document::object() const noexcept(false) { return as_object(); }
inline document::element_result<bool> document::element::as_bool() const noexcept {
#endif
inline simdjson_result<bool> document::element::as_bool() const noexcept {
switch (type()) {
case tape_type::TRUE_VALUE:
case internal::tape_type::TRUE_VALUE:
return true;
case tape_type::FALSE_VALUE:
case internal::tape_type::FALSE_VALUE:
return false;
default:
return INCORRECT_TYPE;
}
}
inline document::element_result<const char *> document::element::as_c_str() const noexcept {
inline simdjson_result<const char *> document::element::as_c_str() const noexcept {
switch (type()) {
case tape_type::STRING: {
case internal::tape_type::STRING: {
size_t string_buf_index = tape_value();
return reinterpret_cast<const char *>(&doc->string_buf[string_buf_index + sizeof(uint32_t)]);
}
@ -779,19 +745,19 @@ inline document::element_result<const char *> document::element::as_c_str() cons
return INCORRECT_TYPE;
}
}
inline document::element_result<std::string_view> document::element::as_string() const noexcept {
inline simdjson_result<std::string_view> document::element::as_string() const noexcept {
switch (type()) {
case tape_type::STRING:
case internal::tape_type::STRING:
return get_string_view();
default:
return INCORRECT_TYPE;
}
}
inline document::element_result<uint64_t> document::element::as_uint64_t() const noexcept {
inline simdjson_result<uint64_t> document::element::as_uint64_t() const noexcept {
switch (type()) {
case tape_type::UINT64:
case internal::tape_type::UINT64:
return next_tape_value<uint64_t>();
case tape_type::INT64: {
case internal::tape_type::INT64: {
int64_t result = next_tape_value<int64_t>();
if (result < 0) {
return NUMBER_OUT_OF_RANGE;
@ -802,9 +768,9 @@ inline document::element_result<uint64_t> document::element::as_uint64_t() const
return INCORRECT_TYPE;
}
}
inline document::element_result<int64_t> document::element::as_int64_t() const noexcept {
inline simdjson_result<int64_t> document::element::as_int64_t() const noexcept {
switch (type()) {
case tape_type::UINT64: {
case internal::tape_type::UINT64: {
uint64_t result = next_tape_value<uint64_t>();
// Wrapping max in parens to handle Windows issue: https://stackoverflow.com/questions/11544073/how-do-i-deal-with-the-max-macro-in-windows-h-colliding-with-max-in-std
if (result > (std::numeric_limits<uint64_t>::max)()) {
@ -812,17 +778,17 @@ inline document::element_result<int64_t> document::element::as_int64_t() const n
}
return static_cast<int64_t>(result);
}
case tape_type::INT64:
case internal::tape_type::INT64:
return next_tape_value<int64_t>();
default:
return INCORRECT_TYPE;
}
}
inline document::element_result<double> document::element::as_double() const noexcept {
inline simdjson_result<double> document::element::as_double() const noexcept {
switch (type()) {
case tape_type::UINT64:
case internal::tape_type::UINT64:
return next_tape_value<uint64_t>();
case tape_type::INT64: {
case internal::tape_type::INT64: {
return next_tape_value<int64_t>();
int64_t result = tape_value();
if (result < 0) {
@ -830,34 +796,34 @@ inline document::element_result<double> document::element::as_double() const noe
}
return result;
}
case tape_type::DOUBLE:
case internal::tape_type::DOUBLE:
return next_tape_value<double>();
default:
return INCORRECT_TYPE;
}
}
inline document::element_result<document::array> document::element::as_array() const noexcept {
inline document::array_result document::element::as_array() const noexcept {
switch (type()) {
case tape_type::START_ARRAY:
case internal::tape_type::START_ARRAY:
return array(doc, json_index);
default:
return INCORRECT_TYPE;
}
}
inline document::element_result<document::object> document::element::as_object() const noexcept {
inline document::object_result document::element::as_object() const noexcept {
switch (type()) {
case tape_type::START_OBJECT:
case internal::tape_type::START_OBJECT:
return object(doc, json_index);
default:
return INCORRECT_TYPE;
}
}
inline document::element_result<document::element> document::element::operator[](const std::string_view &key) const noexcept {
inline document::element_result document::element::operator[](const std::string_view &key) const noexcept {
auto [obj, error] = as_object();
if (error) { return error; }
return obj[key];
}
inline document::element_result<document::element> document::element::operator[](const char *key) const noexcept {
inline document::element_result document::element::operator[](const char *key) const noexcept {
auto [obj, error] = as_object();
if (error) { return error; }
return obj[key];
@ -873,15 +839,14 @@ inline std::ostream& minify<document>::print(std::ostream& out) {
}
template<>
inline std::ostream& minify<document::element>::print(std::ostream& out) {
using tape_type=document::tape_type;
using tape_type=internal::tape_type;
size_t depth = 0;
constexpr size_t MAX_DEPTH = 16;
bool is_object[MAX_DEPTH];
is_object[0] = false;
bool after_value = false;
document::tape_ref iter(value.doc, value.json_index);
internal::tape_ref iter(value.doc, value.json_index);
do {
// print commas after each value
if (after_value) {
@ -1026,30 +991,30 @@ inline std::ostream& minify<document::key_value_pair>::print(std::ostream& out)
return out << '"' << internal::escape_json_string(value.key) << "\":" << value.value;
}
template<>
inline std::ostream& minify<document::doc_move_result>::print(std::ostream& out) {
if (value.error()) { throw simdjson_error(value.error()); }
return out << minify<document>(value.first);
}
template<>
inline std::ostream& minify<document::doc_result>::print(std::ostream& out) {
if (value.error) { throw simdjson_error(value.error); }
return out << minify<document>(value.doc);
if (value.error()) { throw simdjson_error(value.error()); }
return out << minify<document>(value.first);
}
template<>
inline std::ostream& minify<document::doc_ref_result>::print(std::ostream& out) {
if (value.error) { throw simdjson_error(value.error); }
return out << minify<document>(value.doc);
inline std::ostream& minify<document::element_result>::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::element_result<document::element>>::print(std::ostream& out) {
if (value.error) { throw simdjson_error(value.error); }
return out << minify<document::element>(value.value);
inline std::ostream& minify<document::array_result>::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::element_result<document::array>>::print(std::ostream& out) {
if (value.error) { throw simdjson_error(value.error); }
return out << minify<document::array>(value.value);
}
template<>
inline std::ostream& minify<document::element_result<document::object>>::print(std::ostream& out) {
if (value.error) { throw simdjson_error(value.error); }
return out << minify<document::object>(value.value);
inline std::ostream& minify<document::object_result>::print(std::ostream& out) {
if (value.error()) { throw simdjson_error(value.error()); }
return out << minify<document::object>(value.first);
}
} // namespace simdjson

View File

@ -241,10 +241,14 @@ document_iterator<max_depth>::document_iterator(const document &doc_) noexcept
}
}
#if SIMDJSON_EXCEPTIONS
template <size_t max_depth>
document_iterator<max_depth>::document_iterator(const document::parser &parser)
document_iterator<max_depth>::document_iterator(const document::parser &parser) noexcept(false)
: document_iterator(parser.get_document()) {}
#endif
template <size_t max_depth>
document_iterator<max_depth>::document_iterator(
const document_iterator &o) noexcept

View File

@ -127,8 +127,8 @@ really_inline document::stream::iterator::iterator(stream& stream, bool _is_end)
: _stream{stream}, finished{_is_end} {
}
really_inline document::doc_ref_result document::stream::iterator::operator*() noexcept {
return doc_ref_result(_stream.parser.doc, _stream.error == SUCCESS_AND_HAS_MORE ? SUCCESS : _stream.error);
really_inline document::doc_result document::stream::iterator::operator*() noexcept {
return doc_result(_stream.parser.doc, _stream.error == SUCCESS_AND_HAS_MORE ? SUCCESS : _stream.error);
}
really_inline document::stream::iterator& document::stream::iterator::operator++() noexcept {

View File

@ -98,7 +98,7 @@ inline const char *padded_string::data() const noexcept { return data_ptr; }
inline char *padded_string::data() noexcept { return data_ptr; }
inline simdjson_result<padded_string> padded_string::load(const std::string &filename) noexcept {
inline simdjson_move_result<padded_string> padded_string::load(const std::string &filename) noexcept {
// Open the file
std::FILE *fp = std::fopen(filename.c_str(), "rb");
if (fp == nullptr) {

View File

@ -14,7 +14,7 @@ namespace simdjson {
//
inline int json_parse(const uint8_t *buf, size_t len, document::parser &parser, bool realloc_if_needed = true) noexcept {
error_code code = parser.parse(buf, len, realloc_if_needed).error;
error_code code = parser.parse(buf, len, realloc_if_needed).error();
// The deprecated json_parse API is a signal that the user plans to *use* the error code / valid
// bits in the parser instead of heeding the result code. The normal parser unsets those in
// anticipation of making the error code ephemeral.

View File

@ -94,7 +94,7 @@ struct padded_string final {
*
* @param path the path to the file.
**/
inline static simdjson_result<padded_string> load(const std::string &path) noexcept;
inline static simdjson_move_result<padded_string> load(const std::string &path) noexcept;
private:
padded_string &operator=(const padded_string &o) = delete;

View File

@ -486,11 +486,11 @@ public:
/**
* Get the root element of this document as a JSON array.
*/
element_result<array> as_array() const noexcept;
array_result as_array() const noexcept;
/**
* Get the root element of this document as a JSON object.
*/
element_result<object> as_object() const noexcept;
object_result as_object() const noexcept;
/**
* Get the root element of this document.
*/
@ -522,7 +522,7 @@ public:
* - NO_SUCH_FIELD if the field does not exist in the object
* - UNEXPECTED_TYPE if the document is not an object
*/
element_result<element> operator[](const std::string_view &s) const noexcept;
element_result operator[](const std::string_view &s) const noexcept;
/**
* Get the value associated with the given key.
*
@ -535,7 +535,7 @@ public:
* - NO_SUCH_FIELD if the field does not exist in the object
* - UNEXPECTED_TYPE if the document is not an object
*/
element_result<element> operator[](const char *s) const noexcept;
element_result operator[](const char *s) const noexcept;
/**
* Print this JSON to a std::ostream.
@ -804,7 +804,7 @@ public:
* @return The boolean value, or:
* - UNEXPECTED_TYPE error if the JSON element is not a boolean
*/
inline element_result<bool> as_bool() const noexcept;
inline simdjson_result<bool> as_bool() const noexcept;
/**
* Read this element as a null-terminated string.
@ -815,7 +815,7 @@ public:
* @return A `string_view` into the string, or:
* - UNEXPECTED_TYPE error if the JSON element is not a string
*/
inline element_result<const char *> as_c_str() const noexcept;
inline simdjson_result<const char *> as_c_str() const noexcept;
/**
* Read this element as a C++ string_view (string with length).
@ -826,7 +826,7 @@ public:
* @return A `string_view` into the string, or:
* - UNEXPECTED_TYPE error if the JSON element is not a string
*/
inline element_result<std::string_view> as_string() const noexcept;
inline simdjson_result<std::string_view> as_string() const noexcept;
/**
* Read this element as an unsigned integer.
@ -835,7 +835,7 @@ public:
* - UNEXPECTED_TYPE if the JSON element is not an integer
* - NUMBER_OUT_OF_RANGE if the integer doesn't fit in 64 bits or is negative
*/
inline element_result<uint64_t> as_uint64_t() const noexcept;
inline simdjson_result<uint64_t> as_uint64_t() const noexcept;
/**
* Read this element as a signed integer.
@ -844,7 +844,7 @@ public:
* - UNEXPECTED_TYPE if the JSON element is not an integer
* - NUMBER_OUT_OF_RANGE if the integer doesn't fit in 64 bits
*/
inline element_result<int64_t> as_int64_t() const noexcept;
inline simdjson_result<int64_t> as_int64_t() const noexcept;
/**
* Read this element as a floating point value.
@ -852,7 +852,7 @@ public:
* @return The double value, or:
* - UNEXPECTED_TYPE if the JSON element is not a number
*/
inline element_result<double> as_double() const noexcept;
inline simdjson_result<double> as_double() const noexcept;
/**
* Read this element as a JSON array.
@ -860,7 +860,7 @@ public:
* @return The array value, or:
* - UNEXPECTED_TYPE if the JSON element is not an array
*/
inline element_result<document::array> as_array() const noexcept;
inline array_result as_array() const noexcept;
/**
* Read this element as a JSON object (key/value pairs).
@ -868,7 +868,7 @@ public:
* @return The object value, or:
* - UNEXPECTED_TYPE if the JSON element is not an object
*/
inline element_result<document::object> as_object() const noexcept;
inline object_result as_object() const noexcept;
/**
* Read this element as a boolean.
@ -951,7 +951,7 @@ public:
* - NO_SUCH_FIELD if the field does not exist in the object
* - UNEXPECTED_TYPE if the document is not an object
*/
inline element_result<element> operator[](const std::string_view &s) const noexcept;
inline element_result operator[](const std::string_view &s) const noexcept;
/**
* Get the value associated with the given key.
*
@ -964,7 +964,7 @@ public:
* - NO_SUCH_FIELD if the field does not exist in the object
* - UNEXPECTED_TYPE if the document is not an object
*/
inline element_result<element> operator[](const char *s) const noexcept;
inline element_result operator[](const char *s) const noexcept;
private:
really_inline element() noexcept;
@ -1087,7 +1087,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<element> operator[](const std::string_view &s) const noexcept;
inline element_result operator[](const std::string_view &s) const noexcept;
/**
* Get the value associated with the given key.
*
@ -1099,7 +1099,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<element> operator[](const char *s) const noexcept;
inline element_result operator[](const char *s) const noexcept;
private:
really_inline object() noexcept;
@ -1156,9 +1156,9 @@ private:
friend class element;
};
// Add exception-throwing navigation / conversion methods to element_result<element>
// Add exception-throwing navigation / conversion methods to element_result
template<>
class document::element_result<document::element> {
class document::element_result {
public:
/** The value */
element value;
@ -1166,15 +1166,15 @@ public:
error_code error;
/** Whether this is a JSON `null` */
inline element_result<bool> is_null() const noexcept;
inline element_result<bool> as_bool() const noexcept;
inline element_result<std::string_view> as_string() const noexcept;
inline element_result<const char *> as_c_str() const noexcept;
inline element_result<uint64_t> as_uint64_t() const noexcept;
inline element_result<int64_t> as_int64_t() const noexcept;
inline element_result<double> as_double() const noexcept;
inline element_result<array> as_array() const noexcept;
inline element_result<object> as_object() const noexcept;
inline simdjson_result<bool> is_null() const noexcept;
inline simdjson_result<bool> as_bool() const noexcept;
inline simdjson_result<std::string_view> as_string() const noexcept;
inline simdjson_result<const char *> as_c_str() const noexcept;
inline simdjson_result<uint64_t> as_uint64_t() const noexcept;
inline simdjson_result<int64_t> as_int64_t() const noexcept;
inline simdjson_result<double> as_double() const noexcept;
inline array_result as_array() const noexcept;
inline object_result as_object() const noexcept;
inline operator bool() const noexcept(false);
inline explicit operator const char*() const noexcept(false);
@ -1185,8 +1185,8 @@ public:
inline operator array() const noexcept(false);
inline operator object() const noexcept(false);
inline element_result<element> operator[](const std::string_view &s) const noexcept;
inline element_result<element> operator[](const char *s) const noexcept;
inline element_result operator[](const std::string_view &s) const noexcept;
inline element_result operator[](const char *s) const noexcept;
private:
really_inline element_result(element value) noexcept;
@ -1195,9 +1195,9 @@ private:
friend class element;
};
// Add exception-throwing navigation methods to element_result<array>
// Add exception-throwing navigation methods to array_result
template<>
class document::element_result<document::array> {
class document::array_result {
public:
/** The value */
array value;
@ -1216,9 +1216,9 @@ private:
friend class element;
};
// Add exception-throwing navigation methods to element_result<object>
// Add exception-throwing navigation methods to object_result
template<>
class document::element_result<document::object> {
class document::object_result {
public:
/** The value */
object value;
@ -1230,8 +1230,8 @@ public:
inline object::iterator begin() const noexcept(false);
inline object::iterator end() const noexcept(false);
inline element_result<element> operator[](const std::string_view &s) const noexcept;
inline element_result<element> operator[](const char *s) const noexcept;
inline element_result operator[](const std::string_view &s) const noexcept;
inline element_result operator[](const char *s) const noexcept;
private:
really_inline element_result(object value) noexcept;
@ -2430,151 +2430,151 @@ inline document::element_result<T>::element_result(T _value) noexcept : value(_v
template<typename T>
inline document::element_result<T>::element_result(error_code _error) noexcept : value(), error{_error} {}
template<>
inline document::element_result<std::string_view>::operator std::string_view() const noexcept(false) {
inline document::simdjson_result<std::string_view>::operator std::string_view() const noexcept(false) {
if (error) { throw invalid_json(error); }
return value;
}
template<>
inline document::element_result<const char *>::operator const char *() const noexcept(false) {
inline document::simdjson_result<const char *>::operator const char *() const noexcept(false) {
if (error) { throw invalid_json(error); }
return value;
}
template<>
inline document::element_result<bool>::operator bool() const noexcept(false) {
inline document::simdjson_result<bool>::operator bool() const noexcept(false) {
if (error) { throw invalid_json(error); }
return value;
}
template<>
inline document::element_result<uint64_t>::operator uint64_t() const noexcept(false) {
inline document::simdjson_result<uint64_t>::operator uint64_t() const noexcept(false) {
if (error) { throw invalid_json(error); }
return value;
}
template<>
inline document::element_result<int64_t>::operator int64_t() const noexcept(false) {
inline document::simdjson_result<int64_t>::operator int64_t() const noexcept(false) {
if (error) { throw invalid_json(error); }
return value;
}
template<>
inline document::element_result<double>::operator double() const noexcept(false) {
inline document::simdjson_result<double>::operator double() const noexcept(false) {
if (error) { throw invalid_json(error); }
return value;
}
//
// document::element_result<document::array> inline implementation
// document::array_result inline implementation
//
inline document::element_result<document::array>::element_result(document::array _value) noexcept : value(_value), error{SUCCESS} {}
inline document::element_result<document::array>::element_result(error_code _error) noexcept : value(), error{_error} {}
inline document::element_result<document::array>::operator document::array() const noexcept(false) {
inline document::array_result::element_result(document::array _value) noexcept : value(_value), error{SUCCESS} {}
inline document::array_result::element_result(error_code _error) noexcept : value(), error{_error} {}
inline document::array_result::operator document::array() const noexcept(false) {
if (error) { throw invalid_json(error); }
return value;
}
inline document::array::iterator document::element_result<document::array>::begin() const noexcept(false) {
inline document::array::iterator document::array_result::begin() const noexcept(false) {
if (error) { throw invalid_json(error); }
return value.begin();
}
inline document::array::iterator document::element_result<document::array>::end() const noexcept(false) {
inline document::array::iterator document::array_result::end() const noexcept(false) {
if (error) { throw invalid_json(error); }
return value.end();
}
//
// document::element_result<document::object> inline implementation
// document::object_result inline implementation
//
inline document::element_result<document::object>::element_result(document::object _value) noexcept : value(_value), error{SUCCESS} {}
inline document::element_result<document::object>::element_result(error_code _error) noexcept : value(), error{_error} {}
inline document::element_result<document::object>::operator document::object() const noexcept(false) {
inline document::object_result::element_result(document::object _value) noexcept : value(_value), error{SUCCESS} {}
inline document::object_result::element_result(error_code _error) noexcept : value(), error{_error} {}
inline document::object_result::operator document::object() const noexcept(false) {
if (error) { throw invalid_json(error); }
return value;
}
inline document::element_result<document::element> document::element_result<document::object>::operator[](const std::string_view &key) const noexcept {
inline document::element_result document::object_result::operator[](const std::string_view &key) const noexcept {
if (error) { return error; }
return value[key];
}
inline document::element_result<document::element> document::element_result<document::object>::operator[](const char *key) const noexcept {
inline document::element_result document::object_result::operator[](const char *key) const noexcept {
if (error) { return error; }
return value[key];
}
inline document::object::iterator document::element_result<document::object>::begin() const noexcept(false) {
inline document::object::iterator document::object_result::begin() const noexcept(false) {
if (error) { throw invalid_json(error); }
return value.begin();
}
inline document::object::iterator document::element_result<document::object>::end() const noexcept(false) {
inline document::object::iterator document::object_result::end() const noexcept(false) {
if (error) { throw invalid_json(error); }
return value.end();
}
//
// document::element_result<document::element> inline implementation
// document::element_result inline implementation
//
inline document::element_result<document::element>::element_result(document::element _value) noexcept : value(_value), error{SUCCESS} {}
inline document::element_result<document::element>::element_result(error_code _error) noexcept : value(), error{_error} {}
inline document::element_result<bool> document::element_result<document::element>::is_null() const noexcept {
inline document::element_result::element_result(document::element _value) noexcept : value(_value), error{SUCCESS} {}
inline document::element_result::element_result(error_code _error) noexcept : value(), error{_error} {}
inline document::simdjson_result<bool> document::element_result::is_null() const noexcept {
if (error) { return error; }
return value.is_null();
}
inline document::element_result<bool> document::element_result<document::element>::as_bool() const noexcept {
inline document::simdjson_result<bool> document::element_result::as_bool() const noexcept {
if (error) { return error; }
return value.as_bool();
}
inline document::element_result<const char*> document::element_result<document::element>::as_c_str() const noexcept {
inline document::element_result<const char*> document::element_result::as_c_str() const noexcept {
if (error) { return error; }
return value.as_c_str();
}
inline document::element_result<std::string_view> document::element_result<document::element>::as_string() const noexcept {
inline document::simdjson_result<std::string_view> document::element_result::as_string() const noexcept {
if (error) { return error; }
return value.as_string();
}
inline document::element_result<uint64_t> document::element_result<document::element>::as_uint64_t() const noexcept {
inline document::simdjson_result<uint64_t> document::element_result::as_uint64_t() const noexcept {
if (error) { return error; }
return value.as_uint64_t();
}
inline document::element_result<int64_t> document::element_result<document::element>::as_int64_t() const noexcept {
inline document::simdjson_result<int64_t> document::element_result::as_int64_t() const noexcept {
if (error) { return error; }
return value.as_int64_t();
}
inline document::element_result<double> document::element_result<document::element>::as_double() const noexcept {
inline document::simdjson_result<double> document::element_result::as_double() const noexcept {
if (error) { return error; }
return value.as_double();
}
inline document::element_result<document::array> document::element_result<document::element>::as_array() const noexcept {
inline document::array_result document::element_result::as_array() const noexcept {
if (error) { return error; }
return value.as_array();
}
inline document::element_result<document::object> document::element_result<document::element>::as_object() const noexcept {
inline document::object_result document::element_result::as_object() const noexcept {
if (error) { return error; }
return value.as_object();
}
inline document::element_result<document::element>::operator bool() const noexcept(false) {
inline document::element_result::operator bool() const noexcept(false) {
return as_bool();
}
inline document::element_result<document::element>::operator const char *() const noexcept(false) {
inline document::element_result::operator const char *() const noexcept(false) {
return as_c_str();
}
inline document::element_result<document::element>::operator std::string_view() const noexcept(false) {
inline document::element_result::operator std::string_view() const noexcept(false) {
return as_string();
}
inline document::element_result<document::element>::operator uint64_t() const noexcept(false) {
inline document::element_result::operator uint64_t() const noexcept(false) {
return as_uint64_t();
}
inline document::element_result<document::element>::operator int64_t() const noexcept(false) {
inline document::element_result::operator int64_t() const noexcept(false) {
return as_int64_t();
}
inline document::element_result<document::element>::operator double() const noexcept(false) {
inline document::element_result::operator double() const noexcept(false) {
return as_double();
}
inline document::element_result<document::element>::operator document::array() const noexcept(false) {
inline document::element_result::operator document::array() const noexcept(false) {
return as_array();
}
inline document::element_result<document::element>::operator document::object() const noexcept(false) {
inline document::element_result::operator document::object() const noexcept(false) {
return as_object();
}
inline document::element_result<document::element> document::element_result<document::element>::operator[](const std::string_view &key) const noexcept {
inline document::element_result document::element_result::operator[](const std::string_view &key) const noexcept {
if (error) { return *this; }
return value[key];
}
inline document::element_result<document::element> document::element_result<document::element>::operator[](const char *key) const noexcept {
inline document::element_result document::element_result::operator[](const char *key) const noexcept {
if (error) { return *this; }
return value[key];
}
@ -2585,10 +2585,10 @@ inline document::element_result<document::element> document::element_result<docu
inline document::element document::root() const noexcept {
return document::element(this, 1);
}
inline document::element_result<document::array> document::as_array() const noexcept {
inline document::array_result document::as_array() const noexcept {
return root().as_array();
}
inline document::element_result<document::object> document::as_object() const noexcept {
inline document::object_result document::as_object() const noexcept {
return root().as_object();
}
inline document::operator document::element() const noexcept {
@ -2600,10 +2600,10 @@ inline document::operator document::array() const noexcept(false) {
inline document::operator document::object() const noexcept(false) {
return root();
}
inline document::element_result<document::element> document::operator[](const std::string_view &key) const noexcept {
inline document::element_result document::operator[](const std::string_view &key) const noexcept {
return root()[key];
}
inline document::element_result<document::element> document::operator[](const char *key) const noexcept {
inline document::element_result document::operator[](const char *key) const noexcept {
return root()[key];
}
@ -3085,7 +3085,7 @@ inline document::object::iterator document::object::begin() const noexcept {
inline document::object::iterator document::object::end() const noexcept {
return iterator(doc, after_element() - 1);
}
inline document::element_result<document::element> document::object::operator[](const std::string_view &key) const noexcept {
inline document::element_result document::object::operator[](const std::string_view &key) const noexcept {
iterator end_field = end();
for (iterator field = begin(); field != end_field; ++field) {
if (key == field.key()) {
@ -3094,7 +3094,7 @@ inline document::element_result<document::element> document::object::operator[](
}
return NO_SUCH_FIELD;
}
inline document::element_result<document::element> document::object::operator[](const char *key) const noexcept {
inline document::element_result document::object::operator[](const char *key) const noexcept {
iterator end_field = end();
for (iterator field = begin(); field != end_field; ++field) {
if (!strcmp(key, field.key_c_str())) {
@ -3174,7 +3174,7 @@ inline document::element::operator int64_t() const noexcept(false) { return as_i
inline document::element::operator double() const noexcept(false) { return as_double(); }
inline document::element::operator document::array() const noexcept(false) { return as_array(); }
inline document::element::operator document::object() const noexcept(false) { return as_object(); }
inline document::element_result<bool> document::element::as_bool() const noexcept {
inline document::simdjson_result<bool> document::element::as_bool() const noexcept {
switch (type()) {
case tape_type::TRUE_VALUE:
return true;
@ -3184,7 +3184,7 @@ inline document::element_result<bool> document::element::as_bool() const noexcep
return INCORRECT_TYPE;
}
}
inline document::element_result<const char *> document::element::as_c_str() const noexcept {
inline document::simdjson_result<const char *> document::element::as_c_str() const noexcept {
switch (type()) {
case tape_type::STRING: {
size_t string_buf_index = tape_value();
@ -3194,7 +3194,7 @@ inline document::element_result<const char *> document::element::as_c_str() cons
return INCORRECT_TYPE;
}
}
inline document::element_result<std::string_view> document::element::as_string() const noexcept {
inline document::simdjson_result<std::string_view> document::element::as_string() const noexcept {
switch (type()) {
case tape_type::STRING: {
size_t string_buf_index = tape_value();
@ -3209,7 +3209,7 @@ inline document::element_result<std::string_view> document::element::as_string()
return INCORRECT_TYPE;
}
}
inline document::element_result<uint64_t> document::element::as_uint64_t() const noexcept {
inline document::simdjson_result<uint64_t> document::element::as_uint64_t() const noexcept {
switch (type()) {
case tape_type::UINT64:
return next_tape_value<uint64_t>();
@ -3224,7 +3224,7 @@ inline document::element_result<uint64_t> document::element::as_uint64_t() const
return INCORRECT_TYPE;
}
}
inline document::element_result<int64_t> document::element::as_int64_t() const noexcept {
inline document::simdjson_result<int64_t> document::element::as_int64_t() const noexcept {
switch (type()) {
case tape_type::UINT64: {
uint64_t result = next_tape_value<uint64_t>();
@ -3241,7 +3241,7 @@ inline document::element_result<int64_t> document::element::as_int64_t() const n
return INCORRECT_TYPE;
}
}
inline document::element_result<double> document::element::as_double() const noexcept {
inline document::simdjson_result<double> document::element::as_double() const noexcept {
switch (type()) {
case tape_type::UINT64:
return next_tape_value<uint64_t>();
@ -3259,7 +3259,7 @@ inline document::element_result<double> document::element::as_double() const noe
return INCORRECT_TYPE;
}
}
inline document::element_result<document::array> document::element::as_array() const noexcept {
inline document::array_result document::element::as_array() const noexcept {
switch (type()) {
case tape_type::START_ARRAY:
return array(doc, json_index);
@ -3267,7 +3267,7 @@ inline document::element_result<document::array> document::element::as_array() c
return INCORRECT_TYPE;
}
}
inline document::element_result<document::object> document::element::as_object() const noexcept {
inline document::object_result document::element::as_object() const noexcept {
switch (type()) {
case tape_type::START_OBJECT:
return object(doc, json_index);
@ -3275,12 +3275,12 @@ inline document::element_result<document::object> document::element::as_object()
return INCORRECT_TYPE;
}
}
inline document::element_result<document::element> document::element::operator[](const std::string_view &key) const noexcept {
inline document::element_result document::element::operator[](const std::string_view &key) const noexcept {
auto [obj, error] = as_object();
if (error) { return error; }
return obj[key];
}
inline document::element_result<document::element> document::element::operator[](const char *key) const noexcept {
inline document::element_result document::element::operator[](const char *key) const noexcept {
auto [obj, error] = as_object();
if (error) { return error; }
return obj[key];

View File

@ -27,17 +27,17 @@ really_inline error_code document::parser::on_success(error_code success_code) n
}
really_inline bool document::parser::on_start_document(uint32_t depth) noexcept {
containing_scope_offset[depth] = current_loc;
write_tape(0, tape_type::ROOT);
write_tape(0, internal::tape_type::ROOT);
return true;
}
really_inline bool document::parser::on_start_object(uint32_t depth) noexcept {
containing_scope_offset[depth] = current_loc;
write_tape(0, tape_type::START_OBJECT);
write_tape(0, internal::tape_type::START_OBJECT);
return true;
}
really_inline bool document::parser::on_start_array(uint32_t depth) noexcept {
containing_scope_offset[depth] = current_loc;
write_tape(0, tape_type::START_ARRAY);
write_tape(0, internal::tape_type::START_ARRAY);
return true;
}
// TODO we're not checking this bool
@ -45,39 +45,39 @@ really_inline bool document::parser::on_end_document(uint32_t depth) noexcept {
// write our doc.tape location to the header scope
// The root scope gets written *at* the previous location.
annotate_previous_loc(containing_scope_offset[depth], current_loc);
write_tape(containing_scope_offset[depth], tape_type::ROOT);
write_tape(containing_scope_offset[depth], internal::tape_type::ROOT);
return true;
}
really_inline bool document::parser::on_end_object(uint32_t depth) noexcept {
// write our doc.tape location to the header scope
write_tape(containing_scope_offset[depth], tape_type::END_OBJECT);
write_tape(containing_scope_offset[depth], internal::tape_type::END_OBJECT);
annotate_previous_loc(containing_scope_offset[depth], current_loc);
return true;
}
really_inline bool document::parser::on_end_array(uint32_t depth) noexcept {
// write our doc.tape location to the header scope
write_tape(containing_scope_offset[depth], tape_type::END_ARRAY);
write_tape(containing_scope_offset[depth], internal::tape_type::END_ARRAY);
annotate_previous_loc(containing_scope_offset[depth], current_loc);
return true;
}
really_inline bool document::parser::on_true_atom() noexcept {
write_tape(0, tape_type::TRUE_VALUE);
write_tape(0, internal::tape_type::TRUE_VALUE);
return true;
}
really_inline bool document::parser::on_false_atom() noexcept {
write_tape(0, tape_type::FALSE_VALUE);
write_tape(0, internal::tape_type::FALSE_VALUE);
return true;
}
really_inline bool document::parser::on_null_atom() noexcept {
write_tape(0, tape_type::NULL_VALUE);
write_tape(0, internal::tape_type::NULL_VALUE);
return true;
}
really_inline uint8_t *document::parser::on_start_string() noexcept {
/* we advance the point, accounting for the fact that we have a NULL
* termination */
write_tape(current_string_buf_loc - doc.string_buf.get(), tape_type::STRING);
write_tape(current_string_buf_loc - doc.string_buf.get(), internal::tape_type::STRING);
return current_string_buf_loc + sizeof(uint32_t);
}
@ -95,25 +95,25 @@ really_inline bool document::parser::on_end_string(uint8_t *dst) noexcept {
}
really_inline bool document::parser::on_number_s64(int64_t value) noexcept {
write_tape(0, tape_type::INT64);
write_tape(0, internal::tape_type::INT64);
std::memcpy(&doc.tape[current_loc], &value, sizeof(value));
++current_loc;
return true;
}
really_inline bool document::parser::on_number_u64(uint64_t value) noexcept {
write_tape(0, tape_type::UINT64);
write_tape(0, internal::tape_type::UINT64);
doc.tape[current_loc++] = value;
return true;
}
really_inline bool document::parser::on_number_double(double value) noexcept {
write_tape(0, tape_type::DOUBLE);
write_tape(0, internal::tape_type::DOUBLE);
static_assert(sizeof(value) == sizeof(doc.tape[current_loc]), "mismatch size");
memcpy(&doc.tape[current_loc++], &value, sizeof(double));
// doc.tape[doc.current_loc++] = *((uint64_t *)&d);
return true;
}
really_inline void document::parser::write_tape(uint64_t val, document::tape_type t) noexcept {
really_inline void document::parser::write_tape(uint64_t val, internal::tape_type t) noexcept {
doc.tape[current_loc++] = val | ((static_cast<uint64_t>(static_cast<char>(t))) << 56);
}

View File

@ -9,6 +9,7 @@
#include <set>
#include <string_view>
#include <sstream>
#include <utility>
#include "simdjson.h"
@ -38,12 +39,12 @@ bool number_test_small_integers() {
auto n = sprintf(buf, "%*d", m, i);
buf[n] = '\0';
fflush(NULL);
auto ok1 = json_parse(buf, n, parser);
if (ok1 != 0 || !parser.is_valid()) {
printf("Could not parse '%s': %s\n", buf, simdjson::error_message(ok1).c_str());
auto [doc, error] = parser.parse(buf, n);
if (error) {
printf("Could not parse '%s': %s\n", buf, simdjson::error_message(error));
return false;
}
simdjson::document::iterator iter(parser);
simdjson::document::iterator iter(doc);
if(!iter.is_number()) {
printf("Root should be number\n");
return false;
@ -73,12 +74,12 @@ bool number_test_powers_of_two() {
auto n = sprintf(buf, "%.*e", std::numeric_limits<double>::max_digits10 - 1, expected);
buf[n] = '\0';
fflush(NULL);
auto ok1 = json_parse(buf, n, parser);
if (ok1 != 0 || !parser.is_valid()) {
printf("Could not parse: %s.\n", buf);
auto [doc, error] = parser.parse(buf, n);
if (error) {
printf("Could not parse '%s': %s\n", buf, simdjson::error_message(error));
return false;
}
simdjson::document::iterator iter(parser);
simdjson::document::iterator iter(doc);
if(!iter.is_number()) {
printf("Root should be number\n");
return false;
@ -207,12 +208,12 @@ bool number_test_powers_of_ten() {
auto n = sprintf(buf,"1e%d", i);
buf[n] = '\0';
fflush(NULL);
auto ok1 = json_parse(buf, n, parser);
if (ok1 != 0 || !parser.is_valid()) {
printf("Could not parse: %s.\n", buf);
auto [doc, error] = parser.parse(buf, n);
if (error) {
printf("Could not parse '%s': %s\n", buf, simdjson::error_message(error));
return false;
}
simdjson::document::iterator iter(parser);
simdjson::document::iterator iter(doc);
if(!iter.is_number()) {
printf("Root should be number\n");
return false;
@ -365,12 +366,12 @@ bool navigate_test() {
"}"
"}";
simdjson::document::parser parser = simdjson::build_parsed_json(json);
if (!parser.is_valid()) {
printf("Something is wrong in navigate: %s.\n", json.c_str());
return false;
auto [doc, error] = simdjson::document::parse(json);
if (error) {
printf("Could not parse '%s': %s\n", json.data(), simdjson::error_message(error));
return false;
}
simdjson::document::iterator iter(parser);
simdjson::document::iterator iter(doc);
if(!iter.is_object()) {
printf("Root should be object\n");
return false;
@ -482,7 +483,10 @@ bool JsonStream_utf8_test() {
simdjson::document::parser parser;
while (parse_res == simdjson::SUCCESS_AND_HAS_MORE) {
parse_res = js.json_parse(parser);
simdjson::document::iterator iter(parser);
if (parse_res != simdjson::SUCCESS && parse_res != simdjson::SUCCESS_AND_HAS_MORE) {
break;
}
simdjson::document::iterator iter(parser.doc);
if(!iter.is_object()) {
printf("Root should be object\n");
return false;
@ -543,7 +547,10 @@ bool JsonStream_test() {
simdjson::document::parser parser;
while (parse_res == simdjson::SUCCESS_AND_HAS_MORE) {
parse_res = js.json_parse(parser);
simdjson::document::iterator iter(parser);
if (parse_res != simdjson::SUCCESS && parse_res != simdjson::SUCCESS_AND_HAS_MORE) {
break;
}
simdjson::document::iterator iter(parser.doc);
if(!iter.is_object()) {
printf("Root should be object\n");
return false;
@ -733,6 +740,7 @@ bool skyprophet_test() {
namespace dom_api {
using namespace std;
using namespace simdjson;
bool object_iterator() {
std::cout << "Running " << __func__ << std::endl;
string json(R"({ "a": 1, "b": 2, "c": 3 })");
@ -740,9 +748,11 @@ namespace dom_api {
uint64_t expected_value[] = { 1, 2, 3 };
int i = 0;
document doc = document::parse(json);
for (auto [key, value] : document::object(doc)) {
if (key != expected_key[i] || uint64_t(value) != expected_value[i]) { cerr << "Expected " << expected_key[i] << " = " << expected_value[i] << ", got " << key << "=" << uint64_t(value) << endl; return false; }
document::parser parser;
auto [object, error] = parser.parse(json).as_object();
if (error) { cerr << "Error: " << error << endl; return false; }
for (auto [key, value] : object) {
if (key != expected_key[i] || value.as_uint64_t().first != expected_value[i]) { cerr << "Expected " << expected_key[i] << " = " << expected_value[i] << ", got " << key << "=" << value << endl; return false; }
i++;
}
if (i*sizeof(uint64_t) != sizeof(expected_value)) { cout << "Expected " << sizeof(expected_value) << " values, got " << i << endl; return false; }
@ -755,6 +765,246 @@ namespace dom_api {
uint64_t expected_value[] = { 1, 10, 100 };
int i=0;
document::parser parser;
auto [array, error] = parser.parse(json).as_array();
if (error) { cerr << "Error: " << error << endl; return false; }
for (auto value : array) {
if (value.as_uint64_t().first != expected_value[i]) { cerr << "Expected " << expected_value[i] << ", got " << value << endl; return false; }
i++;
}
if (i*sizeof(uint64_t) != sizeof(expected_value)) { cout << "Expected " << sizeof(expected_value) << " values, got " << i << endl; return false; }
return true;
}
bool object_iterator_empty() {
std::cout << "Running " << __func__ << std::endl;
string json(R"({})");
int i = 0;
document::parser parser;
auto [object, error] = parser.parse(json).as_object();
if (error) { cerr << "Error: " << error << endl; return false; }
for (auto [key, value] : object) {
cout << "Unexpected " << key << " = " << value << endl;
i++;
}
if (i > 0) { cout << "Expected 0 values, got " << i << endl; return false; }
return true;
}
bool array_iterator_empty() {
std::cout << "Running " << __func__ << std::endl;
string json(R"([])");
int i=0;
document::parser parser;
auto [array, error] = parser.parse(json).as_array();
if (error) { cerr << "Error: " << error << endl; return false; }
for (auto value : array) {
cout << "Unexpected value " << value << endl;
i++;
}
if (i > 0) { cout << "Expected 0 values, got " << i << endl; return false; }
return true;
}
bool string_value() {
std::cout << "Running " << __func__ << std::endl;
string json(R"([ "hi", "has backslash\\" ])");
document::parser parser;
auto [array, error] = parser.parse(json).as_array();
if (error) { cerr << "Error: " << error << endl; return false; }
auto val = array.begin();
if ((*val).as_string().first != "hi") { cerr << "Expected value to be \"hi\", was " << (*val).as_string().first << endl; return false; }
++val;
if ((*val).as_string().first != "has backslash\\") { cerr << "Expected string_view(\"has backslash\\\\\") to be \"has backslash\\\", was " << (*val).as_string().first << endl; return false; }
return true;
}
bool numeric_values() {
std::cout << "Running " << __func__ << std::endl;
string json(R"([ 0, 1, -1, 1.1 ])");
document::parser parser;
auto [array, error] = parser.parse(json).as_array();
if (error) { cerr << "Error: " << error << endl; return false; }
auto val = array.begin();
if ((*val).as_uint64_t().first != 0) { cerr << "Expected uint64_t(0) to be 0, was " << (*val) << endl; return false; }
if ((*val).as_int64_t().first != 0) { cerr << "Expected int64_t(0) to be 0, was " << (*val).as_int64_t().first << endl; return false; }
if ((*val).as_double().first != 0) { cerr << "Expected double(0) to be 0, was " << (*val).as_double().first << endl; return false; }
++val;
if ((*val).as_uint64_t().first != 1) { cerr << "Expected uint64_t(1) to be 1, was " << (*val) << endl; return false; }
if ((*val).as_int64_t().first != 1) { cerr << "Expected int64_t(1) to be 1, was " << (*val).as_int64_t().first << endl; return false; }
if ((*val).as_double().first != 1) { cerr << "Expected double(1) to be 1, was " << (*val).as_double().first << endl; return false; }
++val;
if ((*val).as_int64_t().first != -1) { cerr << "Expected int64_t(-1) to be -1, was " << (*val).as_int64_t().first << endl; return false; }
if ((*val).as_double().first != -1) { cerr << "Expected double(-1) to be -1, was " << (*val).as_double().first << endl; return false; }
++val;
if ((*val).as_double().first != 1.1) { cerr << "Expected double(1.1) to be 1.1, was " << (*val).as_double().first << endl; return false; }
return true;
}
bool boolean_values() {
std::cout << "Running " << __func__ << std::endl;
string json(R"([ true, false ])");
document::parser parser;
auto [array, error] = parser.parse(json).as_array();
if (error) { cerr << "Error: " << error << endl; return false; }
auto val = array.begin();
if ((*val).as_bool().first != true) { cerr << "Expected bool(true) to be true, was " << (*val) << endl; return false; }
++val;
if ((*val).as_bool().first != false) { cerr << "Expected bool(false) to be false, was " << (*val) << endl; return false; }
return true;
}
bool null_value() {
std::cout << "Running " << __func__ << std::endl;
string json(R"([ null ])");
document::parser parser;
auto [array, error] = parser.parse(json).as_array();
if (error) { cerr << "Error: " << error << endl; return false; }
auto val = array.begin();
if (!(*val).is_null()) { cerr << "Expected null to be null!" << endl; return false; }
return true;
}
bool document_object_index() {
std::cout << "Running " << __func__ << std::endl;
string json(R"({ "a": 1, "b": 2, "c": 3})");
document::parser parser;
auto [doc, error] = parser.parse(json);
if (doc["a"].as_uint64_t().first != 1) { cerr << "Expected uint64_t(doc[\"a\"]) to be 1, was " << doc["a"] << endl; return false; }
if (doc["b"].as_uint64_t().first != 2) { cerr << "Expected uint64_t(doc[\"b\"]) to be 2, was " << doc["b"] << endl; return false; }
if (doc["c"].as_uint64_t().first != 3) { cerr << "Expected uint64_t(doc[\"c\"]) to be 3, was " << doc["c"] << endl; return false; }
// Check all three again in backwards order, to ensure we can go backwards
if (doc["c"].as_uint64_t().first != 3) { cerr << "Expected uint64_t(doc[\"c\"]) to be 3, was " << doc["c"] << endl; return false; }
if (doc["b"].as_uint64_t().first != 2) { cerr << "Expected uint64_t(doc[\"b\"]) to be 2, was " << doc["b"] << endl; return false; }
if (doc["a"].as_uint64_t().first != 1) { cerr << "Expected uint64_t(doc[\"a\"]) to be 1, was " << doc["a"] << endl; return false; }
UNUSED document::element val;
tie(val, error) = doc["d"];
if (error != simdjson::NO_SUCH_FIELD) { cerr << "Expected NO_SUCH_FIELD error for uint64_t(doc[\"d\"]), got " << error << endl; return false; }
return true;
}
bool object_index() {
std::cout << "Running " << __func__ << std::endl;
string json(R"({ "obj": { "a": 1, "b": 2, "c": 3 } })");
document::parser parser;
auto [doc, error] = parser.parse(json);
if (error) { cerr << "Error: " << error << endl; return false; }
if (doc["obj"]["a"].as_uint64_t().first != 1) { cerr << "Expected uint64_t(doc[\"obj\"][\"a\"]) to be 1, was " << doc["obj"]["a"].first << endl; return false; }
document::object obj;
tie(obj, error) = doc.as_object();
if (error) { cerr << "Error: " << error << endl; return false; }
if (obj["obj"]["a"].as_uint64_t().first != 1) { cerr << "Expected uint64_t(doc[\"obj\"][\"a\"]) to be 1, was " << doc["obj"]["a"].first << endl; return false; }
tie(obj, error) = obj["obj"].as_object();
if (obj["a"].as_uint64_t().first != 1) { cerr << "Expected uint64_t(obj[\"a\"]) to be 1, was " << obj["a"] << endl; return false; }
if (obj["b"].as_uint64_t().first != 2) { cerr << "Expected uint64_t(obj[\"b\"]) to be 2, was " << obj["a"] << endl; return false; }
if (obj["c"].as_uint64_t().first != 3) { cerr << "Expected uint64_t(obj[\"c\"]) to be 3, was " << obj["a"] << endl; return false; }
// Check all three again in backwards order, to ensure we can go backwards
if (obj["c"].as_uint64_t().first != 3) { cerr << "Expected uint64_t(obj[\"c\"]) to be 3, was " << obj["a"] << endl; return false; }
if (obj["b"].as_uint64_t().first != 2) { cerr << "Expected uint64_t(obj[\"b\"]) to be 2, was " << obj["a"] << endl; return false; }
if (obj["a"].as_uint64_t().first != 1) { cerr << "Expected uint64_t(obj[\"a\"]) to be 1, was " << obj["a"] << endl; return false; }
UNUSED document::element val;
tie(val, error) = doc["d"];
if (error != simdjson::NO_SUCH_FIELD) { cerr << "Expected NO_SUCH_FIELD error for uint64_t(obj[\"d\"]), got " << error << endl; return false; }
return true;
}
bool twitter_count() {
std::cout << "Running " << __func__ << std::endl;
// Prints the number of results in twitter.json
document::parser parser;
auto [result_count, error] = parser.load(JSON_TEST_PATH)["search_metadata"]["count"].as_uint64_t();
if (error) { cerr << "Error: " << error << endl; return false; }
if (result_count != 100) { cerr << "Expected twitter.json[metadata_count][count] = 100, got " << result_count << endl; return false; }
return true;
}
bool twitter_default_profile() {
std::cout << "Running " << __func__ << std::endl;
// Print users with a default profile.
set<string_view> default_users;
document::parser parser;
auto [tweets, error] = parser.load(JSON_TEST_PATH)["statuses"].as_array();
if (error) { cerr << "Error: " << error << endl; return false; }
for (auto tweet : tweets) {
document::object user;
tie(user, error) = tweet["user"].as_object();
if (error) { cerr << "Error: " << error << endl; return false; }
bool default_profile;
tie(default_profile, error) = user["default_profile"].as_bool();
if (error) { cerr << "Error: " << error << endl; return false; }
if (default_profile) {
std::string_view screen_name;
tie(screen_name, error) = user["screen_name"].as_string();
if (error) { cerr << "Error: " << error << endl; return false; }
default_users.insert(screen_name);
}
}
if (default_users.size() != 86) { cerr << "Expected twitter.json[statuses][user] to contain 86 default_profile users, got " << default_users.size() << endl; return false; }
return true;
}
bool twitter_image_sizes() {
std::cout << "Running " << __func__ << std::endl;
// Print image names and sizes
set<pair<uint64_t, uint64_t>> image_sizes;
document::parser parser;
auto [tweets, error] = parser.load(JSON_TEST_PATH)["statuses"].as_array();
if (error) { cerr << "Error: " << error << endl; return false; }
for (auto tweet : tweets) {
auto [media, not_found] = tweet["entities"]["media"].as_array();
if (!not_found) {
for (auto image : media) {
document::object sizes;
tie(sizes, error) = image["sizes"].as_object();
if (error) { cerr << "Error: " << error << endl; return false; }
for (auto [key, size] : sizes) {
uint64_t width, height;
tie(width, error) = size["w"].as_uint64_t();
if (error) { cerr << "Error: " << error << endl; return false; }
tie(height, error) = size["h"].as_uint64_t();
if (error) { cerr << "Error: " << error << endl; return false; }
image_sizes.insert(make_pair(width, height));
}
}
}
}
if (image_sizes.size() != 15) { cerr << "Expected twitter.json[statuses][entities][media][sizes] to contain 15 different sizes, got " << image_sizes.size() << endl; return false; }
return true;
}
#if SIMDJSON_EXCEPTIONS
bool object_iterator_exception() {
std::cout << "Running " << __func__ << std::endl;
string json(R"({ "a": 1, "b": 2, "c": 3 })");
const char* expected_key[] = { "a", "b", "c" };
uint64_t expected_value[] = { 1, 2, 3 };
int i = 0;
document doc = document::parse(json);
for (auto [key, value] : doc.as_object()) {
if (key != expected_key[i] || uint64_t(value) != expected_value[i]) { cerr << "Expected " << expected_key[i] << " = " << expected_value[i] << ", got " << key << "=" << uint64_t(value) << endl; return false; }
i++;
}
if (i*sizeof(uint64_t) != sizeof(expected_value)) { cout << "Expected " << sizeof(expected_value) << " values, got " << i << endl; return false; }
return true;
}
bool array_iterator_exception() {
std::cout << "Running " << __func__ << std::endl;
string json(R"([ 1, 10, 100 ])");
uint64_t expected_value[] = { 1, 10, 100 };
int i=0;
document doc = document::parse(json);
for (uint64_t value : doc.as_array()) {
if (value != expected_value[i]) { cerr << "Expected " << expected_value[i] << ", got " << value << endl; return false; }
@ -764,39 +1014,13 @@ namespace dom_api {
return true;
}
bool object_iterator_empty() {
std::cout << "Running " << __func__ << std::endl;
string json(R"({})");
int i = 0;
document doc = document::parse(json);
for (auto [key, value] : doc.as_object()) {
cout << "Unexpected " << key << " = " << uint64_t(value) << endl;
i++;
}
if (i > 0) { cout << "Expected 0 values, got " << i << endl; return false; }
return true;
}
bool array_iterator_empty() {
std::cout << "Running " << __func__ << std::endl;
string json(R"([])");
int i=0;
document doc = document::parse(json);
for (uint64_t value : doc.as_array()) {
cout << "Unexpected value " << value << endl;
i++;
}
if (i > 0) { cout << "Expected 0 values, got " << i << endl; return false; }
return true;
}
bool string_value() {
bool string_value_exception() {
std::cout << "Running " << __func__ << std::endl;
string json(R"([ "hi", "has backslash\\" ])");
document doc = document::parse(json);
auto val = document::array(doc).begin();
document::parser parser;
document::array array = parser.parse(json).as_array();
auto val = array.begin();
if (strcmp((const char*)*val, "hi")) { cerr << "Expected const char*(\"hi\") to be \"hi\", was " << (const char*)*val << endl; return false; }
if (string_view(*val) != "hi") { cerr << "Expected string_view(\"hi\") to be \"hi\", was " << string_view(*val) << endl; return false; }
++val;
@ -805,11 +1029,13 @@ namespace dom_api {
return true;
}
bool numeric_values() {
bool numeric_values_exception() {
std::cout << "Running " << __func__ << std::endl;
string json(R"([ 0, 1, -1, 1.1 ])");
document doc = document::parse(json);
auto val = document::array(doc).begin();
document::parser parser;
document::array array = parser.parse(json).as_array();
auto val = array.begin();
if (uint64_t(*val) != 0) { cerr << "Expected uint64_t(0) to be 0, was " << uint64_t(*val) << endl; return false; }
if (int64_t(*val) != 0) { cerr << "Expected int64_t(0) to be 0, was " << int64_t(*val) << endl; return false; }
if (double(*val) != 0) { cerr << "Expected double(0) to be 0, was " << double(*val) << endl; return false; }
@ -825,63 +1051,48 @@ namespace dom_api {
return true;
}
bool boolean_values() {
bool boolean_values_exception() {
std::cout << "Running " << __func__ << std::endl;
string json(R"([ true, false ])");
document doc = document::parse(json);
auto val = document::array(doc).begin();
document::parser parser;
document::array array = parser.parse(json).as_array();
auto val = array.begin();
if (bool(*val) != true) { cerr << "Expected bool(true) to be true, was " << bool(*val) << endl; return false; }
++val;
if (bool(*val) != false) { cerr << "Expected bool(false) to be false, was " << bool(*val) << endl; return false; }
return true;
}
bool null_value() {
bool null_value_exception() {
std::cout << "Running " << __func__ << std::endl;
string json(R"([ null ])");
document doc = document::parse(json);
auto val = document::array(doc).begin();
document::parser parser;
document::array array = parser.parse(json).as_array();
auto val = array.begin();
if (!(*val).is_null()) { cerr << "Expected null to be null!" << endl; return false; }
return true;
}
bool document_object_index() {
bool document_object_index_exception() {
std::cout << "Running " << __func__ << std::endl;
string json(R"({ "a": 1, "b": 2, "c": 3})");
document doc = document::parse(json);
if (uint64_t(doc["a"]) != 1) { cerr << "Expected uint64_t(doc[\"a\"]) to be 1, was " << uint64_t(doc["a"]) << endl; return false; }
if (uint64_t(doc["b"]) != 2) { cerr << "Expected uint64_t(doc[\"b\"]) to be 2, was " << uint64_t(doc["b"]) << endl; return false; }
if (uint64_t(doc["c"]) != 3) { cerr << "Expected uint64_t(doc[\"c\"]) to be 3, was " << uint64_t(doc["c"]) << endl; return false; }
// Check all three again in backwards order, to ensure we can go backwards
if (uint64_t(doc["c"]) != 3) { cerr << "Expected uint64_t(doc[\"c\"]) to be 3, was " << uint64_t(doc["c"]) << endl; return false; }
if (uint64_t(doc["b"]) != 2) { cerr << "Expected uint64_t(doc[\"b\"]) to be 2, was " << uint64_t(doc["b"]) << endl; return false; }
if (uint64_t(doc["a"]) != 1) { cerr << "Expected uint64_t(doc[\"a\"]) to be 1, was " << uint64_t(doc["a"]) << endl; return false; }
auto [val, error] = doc["d"];
if (error != simdjson::NO_SUCH_FIELD) { cerr << "Expected NO_SUCH_FIELD error for uint64_t(doc[\"d\"]), got " << error << endl; return false; }
return true;
}
bool object_index() {
bool object_index_exception() {
std::cout << "Running " << __func__ << std::endl;
string json(R"({ "obj": { "a": 1, "b": 2, "c": 3 } })");
document doc = document::parse(json);
if (uint64_t(doc["obj"]["a"]) != 1) { cerr << "Expected uint64_t(doc[\"obj\"][\"a\"]) to be 1, was " << uint64_t(doc["obj"]["a"]) << endl; return false; }
document::object obj = doc["obj"];
if (uint64_t(obj["a"]) != 1) { cerr << "Expected uint64_t(obj[\"a\"]) to be 1, was " << uint64_t(obj["a"]) << endl; return false; }
if (uint64_t(obj["b"]) != 2) { cerr << "Expected uint64_t(obj[\"b\"]) to be 2, was " << uint64_t(obj["b"]) << endl; return false; }
if (uint64_t(obj["c"]) != 3) { cerr << "Expected uint64_t(obj[\"c\"]) to be 3, was " << uint64_t(obj["c"]) << endl; return false; }
// Check all three again in backwards order, to ensure we can go backwards
if (uint64_t(obj["c"]) != 3) { cerr << "Expected uint64_t(obj[\"c\"]) to be 3, was " << uint64_t(obj["c"]) << endl; return false; }
if (uint64_t(obj["b"]) != 2) { cerr << "Expected uint64_t(obj[\"b\"]) to be 2, was " << uint64_t(obj["b"]) << endl; return false; }
if (uint64_t(obj["a"]) != 1) { cerr << "Expected uint64_t(obj[\"a\"]) to be 1, was " << uint64_t(obj["a"]) << endl; return false; }
auto [val, error] = obj["d"];
if (error != simdjson::NO_SUCH_FIELD) { cerr << "Expected NO_SUCH_FIELD error for uint64_t(obj[\"d\"]), got " << error << endl; return false; }
document::parser parser;
document::object obj = parser.parse(json)["obj"];
if (uint64_t(obj["a"]) != 1) { cerr << "Expected uint64_t(doc[\"a\"]) to be 1, was " << uint64_t(obj["a"]) << endl; return false; }
return true;
}
bool twitter_count() {
bool twitter_count_exception() {
std::cout << "Running " << __func__ << std::endl;
// Prints the number of results in twitter.json
document doc = document::load(JSON_TEST_PATH);
@ -890,7 +1101,7 @@ namespace dom_api {
return true;
}
bool twitter_default_profile() {
bool twitter_default_profile_exception() {
std::cout << "Running " << __func__ << std::endl;
// Print users with a default profile.
set<string_view> default_users;
@ -905,17 +1116,17 @@ namespace dom_api {
return true;
}
bool twitter_image_sizes() {
bool twitter_image_sizes_exception() {
std::cout << "Running " << __func__ << std::endl;
// Print image names and sizes
set<tuple<uint64_t, uint64_t>> image_sizes;
set<pair<uint64_t, uint64_t>> image_sizes;
document doc = document::load(JSON_TEST_PATH);
for (document::object tweet : doc["statuses"].as_array()) {
auto [media, not_found] = tweet["entities"]["media"];
if (!not_found) {
for (document::object image : media.as_array()) {
for (auto [key, size] : image["sizes"].as_object()) {
image_sizes.insert({ size["w"], size["h"] });
image_sizes.insert(make_pair(size["w"], size["h"]));
}
}
}
@ -924,21 +1135,35 @@ namespace dom_api {
return true;
}
#endif
bool run_tests() {
if (!object_iterator()) { return false; }
if (!array_iterator()) { return false; }
if (!object_iterator_empty()) { return false; }
if (!array_iterator_empty()) { return false; }
if (!string_value()) { return false; }
if (!numeric_values()) { return false; }
if (!boolean_values()) { return false; }
if (!null_value()) { return false; }
if (!document_object_index()) { return false; }
if (!object_index()) { return false; }
if (!twitter_count()) { return false; }
if (!twitter_default_profile()) { return false; }
if (!twitter_image_sizes()) { return false; }
return true;
return object_iterator() &&
array_iterator() &&
object_iterator_empty() &&
array_iterator_empty() &&
string_value() &&
numeric_values() &&
boolean_values() &&
null_value() &&
document_object_index() &&
object_index() &&
twitter_count() &&
twitter_default_profile() &&
twitter_image_sizes() &&
#if SIMDJSON_EXCEPTIONS
object_iterator_exception() &&
array_iterator_exception() &&
string_value_exception() &&
numeric_values_exception() &&
boolean_values_exception() &&
null_value_exception() &&
document_object_index() &&
twitter_count_exception() &&
twitter_default_profile_exception() &&
twitter_image_sizes_exception() &&
#endif
true;
}
}
@ -1068,6 +1293,22 @@ namespace format_tests {
return assert_minified(s, "[1,2,3]");
}
bool print_object_result() {
std::cout << "Running " << __func__ << std::endl;
const document &doc = document::parse(DOCUMENT);
ostringstream s;
s << doc["baz"].as_object();
return assert_minified(s, R"({"a":1,"b":2,"c":3})");
}
bool print_minify_object_result() {
std::cout << "Running " << __func__ << std::endl;
const document &doc = document::parse(DOCUMENT);
ostringstream s;
s << minify(doc["baz"].as_object());
return assert_minified(s, R"({"a":1,"b":2,"c":3})");
}
#if SIMDJSON_EXCEPTIONS
bool print_array() {
std::cout << "Running " << __func__ << std::endl;
const document &doc = document::parse(DOCUMENT);
@ -1085,21 +1326,6 @@ namespace format_tests {
return assert_minified(s, "[1,2,3]");
}
bool print_object_result() {
std::cout << "Running " << __func__ << std::endl;
const document &doc = document::parse(DOCUMENT);
ostringstream s;
s << doc["baz"].as_object();
return assert_minified(s, R"({"a":1,"b":2,"c":3})");
}
bool print_minify_object_result() {
std::cout << "Running " << __func__ << std::endl;
const document &doc = document::parse(DOCUMENT);
ostringstream s;
s << minify(doc["baz"].as_object());
return assert_minified(s, R"({"a":1,"b":2,"c":3})");
}
bool print_object() {
std::cout << "Running " << __func__ << std::endl;
const document &doc = document::parse(DOCUMENT);
@ -1116,6 +1342,7 @@ namespace format_tests {
s << minify(value);
return assert_minified(s, R"({"a":1,"b":2,"c":3})");
}
#endif // SIMDJSON_EXCEPTIONS
bool run_tests() {
return print_document_parse() && print_minify_document_parse() &&
@ -1126,8 +1353,11 @@ namespace format_tests {
print_array_result() && print_minify_array_result() &&
print_object_result() && print_minify_object_result() &&
print_element() && print_minify_element() &&
#if SIMDJSON_EXCEPTIONS
print_array() && print_minify_array() &&
print_object() && print_minify_object();
print_object() && print_minify_object() &&
#endif
true;
}
}

View File

@ -35,7 +35,7 @@ static void parse_and_validate(const std::string src, T expected) {
auto json = build_parsed_json(pstr);
ASSERT(json.is_valid());
ParsedJson::Iterator it{json};
ParsedJson::Iterator it{json.doc};
ASSERT(it.down());
ASSERT(it.next());
bool result;
@ -59,7 +59,7 @@ static bool parse_and_check_signed(const std::string src) {
auto json = build_parsed_json(pstr);
ASSERT(json.is_valid());
document::iterator it{json};
document::iterator it{json.doc};
ASSERT(it.down());
ASSERT(it.next());
return it.is_integer() && it.is_number();
@ -71,7 +71,7 @@ static bool parse_and_check_unsigned(const std::string src) {
auto json = build_parsed_json(pstr);
ASSERT(json.is_valid());
document::iterator it{json};
document::iterator it{json.doc};
ASSERT(it.down());
ASSERT(it.next());
return it.is_unsigned_integer() && it.is_number();

View File

@ -81,7 +81,7 @@ bool validate(const char *dirname) {
++how_many;
simdjson::error_code error = simdjson::SUCCESS;
for (auto result : parser.parse_many(json)) {
error = result.error;
error = result.error();
}
printf("%s\n", error ? "ok" : "invalid");
/* Check if the file is supposed to pass or not. Print the results */

View File

@ -21,7 +21,7 @@ int main() {
simdjson::ParsedJson pj;
simdjson::json_parse(json.c_str(), json.length(), pj);
ASSERT(pj.is_valid());
simdjson::ParsedJson::Iterator it(pj);
simdjson::ParsedJson::Iterator it(pj.doc);
// valid JSON String Representation pointer
std::string pointer1("/~1~001abc/1/\\\\\\\" 0/0");

View File

@ -35,6 +35,13 @@ if(X64)
endif()
endif()
if(SIMDJSON_EXCEPTIONS)
set(OPT_FLAGS "${OPT_FLAGS} -DSIMDJSON_EXCEPTIONS=1")
else()
message(STATUS "simdjson exception interface turned off. Code that does not check error codes will not compile.")
set(OPT_FLAGS "${OPT_FLAGS} -DSIMDJSON_EXCEPTIONS=0")
endif()
if(NOT MSVC)
set(CXXSTD_FLAGS "-std=c++17 -fPIC")
endif()

View File

@ -86,7 +86,7 @@ int main(int argc, char *argv[]) {
return EXIT_FAILURE;
}
if (apidump) {
simdjson::ParsedJson::Iterator pjh(pj);
simdjson::ParsedJson::Iterator pjh(pj.doc);
if (!pjh.is_ok()) {
std::cerr << " Could not iterate parsed result. " << std::endl;
return EXIT_FAILURE;