mirror of
https://github.com/simdjson/simdjson
synced 2026-06-08 17:27:07 +00:00
Add actual examples from basics.md to readme_examples
This commit is contained in:
@@ -103,6 +103,7 @@ objs
|
||||
/perfdiff
|
||||
/pointercheck
|
||||
/readme_examples
|
||||
/readme_examples_noexceptions
|
||||
/statisticalmodel
|
||||
/stringparsingcheck
|
||||
/submodules
|
||||
@@ -119,6 +120,7 @@ objs
|
||||
/tests/integer_tests
|
||||
/tests/parse_many_test
|
||||
/tests/readme_examples
|
||||
/tests/readme_examples_noexceptions
|
||||
/tools/json2json
|
||||
/tools/jsonstats
|
||||
/tools/minify
|
||||
|
||||
@@ -91,7 +91,7 @@ JSON_INCLUDE:=dependencies/json/single_include/nlohmann/json.hpp
|
||||
EXTRAOBJECTS=ujdecode.o
|
||||
|
||||
MAINEXECUTABLES=parse minify json2json jsonstats statisticalmodel jsonpointer get_corpus_benchmark
|
||||
TESTEXECUTABLES=jsoncheck jsoncheck_westmere jsoncheck_fallback integer_tests numberparsingcheck stringparsingcheck pointercheck parse_many_test basictests errortests readme_examples
|
||||
TESTEXECUTABLES=jsoncheck jsoncheck_westmere jsoncheck_fallback integer_tests numberparsingcheck stringparsingcheck pointercheck parse_many_test basictests errortests readme_examples readme_examples_noexceptions
|
||||
COMPARISONEXECUTABLES=minifiercompetition parsingcompetition parseandstatcompetition distinctuseridcompetition allparserscheckfile allparsingcompetition
|
||||
SUPPLEMENTARYEXECUTABLES=parse_noutf8validation parse_nonumberparsing parse_nostringparsing
|
||||
|
||||
@@ -111,9 +111,6 @@ run_basictests: basictests
|
||||
run_errortests: errortests
|
||||
./errortests
|
||||
|
||||
run_readme_examples: readme_examples
|
||||
./readme_examples
|
||||
|
||||
run_numberparsingcheck: numberparsingcheck
|
||||
./numberparsingcheck
|
||||
|
||||
@@ -161,7 +158,7 @@ test: quicktests slowtests
|
||||
|
||||
quiettest: quicktests slowtests
|
||||
|
||||
quicktests: run_basictests run_quickstart run_readme_examples run_jsoncheck run_numberparsingcheck run_integer_tests run_stringparsingcheck run_jsoncheck run_parse_many_test run_pointercheck run_jsoncheck_westmere run_jsoncheck_fallback
|
||||
quicktests: run_basictests run_quickstart readme_examples readme_examples_noexceptions run_jsoncheck run_numberparsingcheck run_integer_tests run_stringparsingcheck run_jsoncheck run_parse_many_test run_pointercheck run_jsoncheck_westmere run_jsoncheck_fallback
|
||||
|
||||
slowtests: run_testjson2json_sh run_issue150_sh
|
||||
|
||||
@@ -234,6 +231,8 @@ errortests:tests/errortests.cpp $(HEADERS) $(LIBFILES)
|
||||
readme_examples: tests/readme_examples.cpp $(HEADERS) $(LIBFILES)
|
||||
$(CXX) $(CXXFLAGS) -o readme_examples tests/readme_examples.cpp -I. $(LIBFILES) $(LIBFLAGS)
|
||||
|
||||
readme_examples_noexceptions: tests/readme_examples_noexceptions.cpp $(HEADERS) $(LIBFILES)
|
||||
$(CXX) $(CXXFLAGS) -o readme_examples_noexceptions tests/readme_examples_noexceptions.cpp -I. $(LIBFILES) $(LIBFLAGS) -fno-exceptions
|
||||
|
||||
numberparsingcheck: tests/numberparsingcheck.cpp $(HEADERS) src/simdjson.cpp
|
||||
$(CXX) $(CXXFLAGS) -o numberparsingcheck tests/numberparsingcheck.cpp -I. $(LIBFLAGS) -DJSON_TEST_NUMBERS
|
||||
|
||||
+36
-35
@@ -102,8 +102,6 @@ for (dom::object car : cars) {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
JSON Pointer
|
||||
------------
|
||||
|
||||
@@ -144,7 +142,7 @@ behavior.
|
||||
>
|
||||
> ```c++
|
||||
> dom::element doc;
|
||||
> error_code error;
|
||||
> simdjson::error_code error;
|
||||
> parser.parse(json).tie(doc, error); // <-- Assigns to doc and error just like "auto [doc, error]"
|
||||
> ```
|
||||
|
||||
@@ -154,48 +152,50 @@ This is how the example in "Using the Parsed JSON" could be written using only e
|
||||
|
||||
```c++
|
||||
auto cars_json = R"( [
|
||||
{ "make": "Toyota", "model": "Camry", "year": 2018, "tire_pressure": [ 40.1, 39.9, 37.7, 40.4 ] },
|
||||
{ "make": "Kia", "model": "Soul", "year": 2012, "tire_pressure": [ 30.1, 31.0, 28.6, 28.7 ] },
|
||||
{ "make": "Toyota", "model": "Tercel", "year": 1999, "tire_pressure": [ 29.8, 30.0, 30.2, 30.5 ] }
|
||||
{ "make": "Toyota", "model": "Camry", "year": 2018, "tire_pressure": [ 40.1, 39.9, 37.7, 40.4 ] },
|
||||
{ "make": "Kia", "model": "Soul", "year": 2012, "tire_pressure": [ 30.1, 31.0, 28.6, 28.7 ] },
|
||||
{ "make": "Toyota", "model": "Tercel", "year": 1999, "tire_pressure": [ 29.8, 30.0, 30.2, 30.5 ] }
|
||||
] )"_padded;
|
||||
dom::parser parser;
|
||||
auto [doc, error] = parser.parse(cars_json);
|
||||
auto [cars, error] = parser.parse(cars_json).get<dom::array>();
|
||||
if (error) { cerr << error << endl; exit(1); }
|
||||
|
||||
// Iterating through an array of objects
|
||||
for (dom::element car_element : cars) {
|
||||
dom::object car;
|
||||
car_element.get<dom::object>().tie(car, error);
|
||||
if (error) { cerr << error << endl; exit(1); }
|
||||
dom::object car;
|
||||
car_element.get<dom::object>().tie(car, error);
|
||||
if (error) { cerr << error << endl; exit(1); }
|
||||
|
||||
// Accessing a field by name
|
||||
dom::element make, model;
|
||||
car["make"].tie(make, error);
|
||||
if (error) { cerr << error << endl; exit(1); }
|
||||
car["model"].tie(model, error);
|
||||
if (error) { cerr << error << endl; exit(1); }
|
||||
cout << "Make/Model: " << make << "/" << model << endl;
|
||||
// Accessing a field by name
|
||||
dom::element make, model;
|
||||
car["make"].tie(make, error);
|
||||
if (error) { cerr << error << endl; exit(1); }
|
||||
car["model"].tie(model, error);
|
||||
if (error) { cerr << error << endl; exit(1); }
|
||||
cout << "Make/Model: " << make << "/" << model << endl;
|
||||
|
||||
// Casting a JSON element to an integer
|
||||
uint64_t year;
|
||||
car["year"].get<uint64_t>().tie(year, error);
|
||||
if (error) { cerr << error << endl; exit(1); }
|
||||
cout << "- This car is " << 2020 - year << "years old." << endl;
|
||||
// Casting a JSON element to an integer
|
||||
uint64_t year;
|
||||
car["year"].get<uint64_t>().tie(year, error);
|
||||
if (error) { cerr << error << endl; exit(1); }
|
||||
cout << "- This car is " << 2020 - year << "years old." << endl;
|
||||
|
||||
// Iterating through an array of floats
|
||||
double total_tire_pressure = 0;
|
||||
for (dom::element tire_pressure_element : car["tire_pressure"]) {
|
||||
// Iterating through an array of floats
|
||||
double total_tire_pressure = 0;
|
||||
dom::array tire_pressure_array;
|
||||
car["tire_pressure"].get<dom::array>().tie(tire_pressure_array, error);
|
||||
if (error) { cerr << error << endl; exit(1); }
|
||||
for (dom::element tire_pressure_element : tire_pressure_array) {
|
||||
double tire_pressure;
|
||||
tire_pressure_element.get<uint64_t>().tie(tire_pressure, error);
|
||||
tire_pressure_element.get<double>().tie(tire_pressure, error);
|
||||
if (error) { cerr << error << endl; exit(1); }
|
||||
total_tire_pressure += tire_pressure;
|
||||
}
|
||||
cout << "- Average tire pressure: " << (total_tire_pressure / 4) << endl;
|
||||
}
|
||||
cout << "- Average tire pressure: " << (total_tire_pressure / 4) << endl;
|
||||
|
||||
// Writing out all the information about the car
|
||||
for (auto [key, value] : car) {
|
||||
// Writing out all the information about the car
|
||||
for (auto [key, value] : car) {
|
||||
cout << "- " << key << ": " << value << endl;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -215,14 +215,15 @@ Newline-Delimited JSON (ndjson) and JSON lines
|
||||
|
||||
The simdjson library also support multithreaded JSON streaming through a large file containing many smaller JSON documents in either [ndjson](http://ndjson.org) or [JSON lines](http://jsonlines.org) format. If your JSON documents all contain arrays or objects, we even support direct file concatenation without whitespace. The concatenated file has no size restrictions (including larger than 4GB), though each individual document must be less than 4GB.
|
||||
|
||||
Here is a simple example:
|
||||
Here is a simple example, given "x.json" with this content:
|
||||
|
||||
```cpp
|
||||
auto ndjson = R"(
|
||||
```json
|
||||
{ "foo": 1 }
|
||||
{ "foo": 2 }
|
||||
{ "foo": 3 }
|
||||
)"_padded;
|
||||
```
|
||||
|
||||
```c++
|
||||
dom::parser parser;
|
||||
for (dom::element doc : parser.load_many(filename)) {
|
||||
cout << doc["foo"] << endl;
|
||||
|
||||
+276
-257
@@ -85,263 +85,6 @@ class tape_ref;
|
||||
|
||||
namespace simdjson::dom {
|
||||
|
||||
/**
|
||||
* A parsed JSON document.
|
||||
*
|
||||
* This class cannot be copied, only moved, to avoid unintended allocations.
|
||||
*/
|
||||
class document {
|
||||
public:
|
||||
/**
|
||||
* Create a document container with zero capacity.
|
||||
*
|
||||
* The parser will allocate capacity as needed.
|
||||
*/
|
||||
document() noexcept=default;
|
||||
~document() noexcept=default;
|
||||
|
||||
/**
|
||||
* Take another document's buffers.
|
||||
*
|
||||
* @param other The document to take. Its capacity is zeroed and it is invalidated.
|
||||
*/
|
||||
document(document &&other) noexcept = default;
|
||||
document(const document &) = delete; // Disallow copying
|
||||
/**
|
||||
* Take another document's buffers.
|
||||
*
|
||||
* @param other The document to take. Its capacity is zeroed.
|
||||
*/
|
||||
document &operator=(document &&other) noexcept = default;
|
||||
document &operator=(const document &) = delete; // Disallow copying
|
||||
|
||||
/**
|
||||
* Get the root element of this document as a JSON array.
|
||||
*/
|
||||
element root() const noexcept;
|
||||
|
||||
/**
|
||||
* Dump the raw tape for debugging.
|
||||
*
|
||||
* @param os the stream to output to.
|
||||
* @return false if the tape is likely wrong (e.g., you did not parse a valid JSON).
|
||||
*/
|
||||
bool dump_raw_tape(std::ostream &os) const noexcept;
|
||||
|
||||
std::unique_ptr<uint64_t[]> tape;
|
||||
std::unique_ptr<uint8_t[]> string_buf;// should be at least byte_capacity
|
||||
|
||||
private:
|
||||
inline error_code set_capacity(size_t len) noexcept;
|
||||
template<typename T>
|
||||
friend class simdjson::minify;
|
||||
friend class parser;
|
||||
}; // class document
|
||||
|
||||
/**
|
||||
* A JSON element.
|
||||
*
|
||||
* References an element in a JSON document, representing a JSON null, boolean, string, number,
|
||||
* array or object.
|
||||
*/
|
||||
class 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;
|
||||
|
||||
/**
|
||||
* Tell whether the value can be cast to the given primitive type.
|
||||
*
|
||||
* Supported types:
|
||||
* - Boolean: bool
|
||||
* - Number: double, uint64_t, int64_t
|
||||
* - String: std::string_view, const char *
|
||||
* - Array: array
|
||||
*/
|
||||
template<typename T>
|
||||
really_inline bool is() const noexcept;
|
||||
|
||||
/**
|
||||
* Get the value as the given primitive type.
|
||||
*
|
||||
* Supported types:
|
||||
* - Boolean: bool
|
||||
* - Number: double, uint64_t, int64_t
|
||||
* - String: std::string_view, const char *
|
||||
* - Array: array
|
||||
*
|
||||
* @returns The value cast to the given type, or:
|
||||
* INCORRECT_TYPE if the value cannot be cast to the given type.
|
||||
*/
|
||||
template<typename T>
|
||||
really_inline simdjson_result<T> get() const noexcept;
|
||||
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
/**
|
||||
* Read this element as a boolean.
|
||||
*
|
||||
* @return The boolean value
|
||||
* @exception simdjson_error(UNEXPECTED_TYPE) if the JSON element is not a boolean.
|
||||
*/
|
||||
inline operator bool() const noexcept(false);
|
||||
|
||||
/**
|
||||
* Read this element as a null-terminated string.
|
||||
*
|
||||
* Does *not* convert other types to a string; requires that the JSON type of the element was
|
||||
* an actual string.
|
||||
*
|
||||
* @return The string value.
|
||||
* @exception simdjson_error(UNEXPECTED_TYPE) if the JSON element is not a string.
|
||||
*/
|
||||
inline explicit operator const char*() const noexcept(false);
|
||||
|
||||
/**
|
||||
* Read this element as a null-terminated string.
|
||||
*
|
||||
* Does *not* convert other types to a string; requires that the JSON type of the element was
|
||||
* an actual string.
|
||||
*
|
||||
* @return The string value.
|
||||
* @exception simdjson_error(UNEXPECTED_TYPE) if the JSON element is not a string.
|
||||
*/
|
||||
inline operator std::string_view() const noexcept(false);
|
||||
|
||||
/**
|
||||
* Read this element as an unsigned integer.
|
||||
*
|
||||
* @return The integer value.
|
||||
* @exception simdjson_error(UNEXPECTED_TYPE) if the JSON element is not an integer
|
||||
* @exception simdjson_error(NUMBER_OUT_OF_RANGE) if the integer doesn't fit in 64 bits or is negative
|
||||
*/
|
||||
inline operator uint64_t() const noexcept(false);
|
||||
/**
|
||||
* Read this element as an signed integer.
|
||||
*
|
||||
* @return The integer value.
|
||||
* @exception simdjson_error(UNEXPECTED_TYPE) if the JSON element is not an integer
|
||||
* @exception simdjson_error(NUMBER_OUT_OF_RANGE) if the integer doesn't fit in 64 bits
|
||||
*/
|
||||
inline operator int64_t() const noexcept(false);
|
||||
/**
|
||||
* Read this element as an double.
|
||||
*
|
||||
* @return The double value.
|
||||
* @exception simdjson_error(UNEXPECTED_TYPE) if the JSON element is not a number
|
||||
* @exception simdjson_error(NUMBER_OUT_OF_RANGE) if the integer doesn't fit in 64 bits or is negative
|
||||
*/
|
||||
inline operator double() const noexcept(false);
|
||||
/**
|
||||
* Read this element as a JSON array.
|
||||
*
|
||||
* @return The JSON array.
|
||||
* @exception simdjson_error(UNEXPECTED_TYPE) if the JSON element is not an array
|
||||
*/
|
||||
inline operator array() const noexcept(false);
|
||||
/**
|
||||
* Read this element as a JSON object (key/value pairs).
|
||||
*
|
||||
* @return The JSON object.
|
||||
* @exception simdjson_error(UNEXPECTED_TYPE) if the JSON element is not an object
|
||||
*/
|
||||
inline operator object() const noexcept(false);
|
||||
#endif // SIMDJSON_EXCEPTIONS
|
||||
|
||||
/**
|
||||
* Get the value associated with the given key.
|
||||
*
|
||||
* The key will be matched against **unescaped** JSON:
|
||||
*
|
||||
* dom::parser parser;
|
||||
* parser.parse(R"({ "a\n": 1 })")["a\n"].get<uint64_t>().value == 1
|
||||
* parser.parse(R"({ "a\n": 1 })")["a\\n"].get<uint64_t>().error == NO_SUCH_FIELD
|
||||
*
|
||||
* @return The value associated with this field, or:
|
||||
* - NO_SUCH_FIELD if the field does not exist in the object
|
||||
* - INCORRECT_TYPE if this is not an object
|
||||
*/
|
||||
inline simdjson_result<element> operator[](const std::string_view &key) const noexcept;
|
||||
|
||||
/**
|
||||
* Get the value associated with the given key.
|
||||
*
|
||||
* The key will be matched against **unescaped** JSON:
|
||||
*
|
||||
* dom::parser parser;
|
||||
* parser.parse(R"({ "a\n": 1 })")["a\n"].get<uint64_t>().value == 1
|
||||
* parser.parse(R"({ "a\n": 1 })")["a\\n"].get<uint64_t>().error == NO_SUCH_FIELD
|
||||
*
|
||||
* @return The value associated with this field, or:
|
||||
* - NO_SUCH_FIELD if the field does not exist in the object
|
||||
* - INCORRECT_TYPE if this is not an object
|
||||
*/
|
||||
inline simdjson_result<element> operator[](const char *key) const noexcept;
|
||||
|
||||
/**
|
||||
* Get the value associated with the given JSON pointer.
|
||||
*
|
||||
* dom::parser parser;
|
||||
* element doc = parser.parse(R"({ "foo": { "a": [ 10, 20, 30 ] }})");
|
||||
* doc.at("/foo/a/1") == 20
|
||||
* doc.at("/")["foo"]["a"].at(1) == 20
|
||||
* doc.at("")["foo"]["a"].at(1) == 20
|
||||
*
|
||||
* @return The value associated with the given JSON pointer, or:
|
||||
* - NO_SUCH_FIELD if a field does not exist in an object
|
||||
* - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
|
||||
* - INCORRECT_TYPE if a non-integer is used to access an array
|
||||
* - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
|
||||
*/
|
||||
inline simdjson_result<element> at(const std::string_view &json_pointer) const noexcept;
|
||||
|
||||
/**
|
||||
* Get the value at the given index.
|
||||
*
|
||||
* @return The value at the given index, or:
|
||||
* - INDEX_OUT_OF_BOUNDS if the array index is larger than an array length
|
||||
*/
|
||||
inline simdjson_result<element> at(size_t index) const noexcept;
|
||||
|
||||
/**
|
||||
* Get the value associated with the given key.
|
||||
*
|
||||
* The key will be matched against **unescaped** JSON:
|
||||
*
|
||||
* dom::parser parser;
|
||||
* parser.parse(R"({ "a\n": 1 })")["a\n"].get<uint64_t>().value == 1
|
||||
* parser.parse(R"({ "a\n": 1 })")["a\\n"].get<uint64_t>().error == NO_SUCH_FIELD
|
||||
*
|
||||
* @return The value associated with this field, or:
|
||||
* - NO_SUCH_FIELD if the field does not exist in the object
|
||||
*/
|
||||
inline simdjson_result<element> at_key(const std::string_view &key) const noexcept;
|
||||
|
||||
/**
|
||||
* Get the value associated with the given key in a case-insensitive manner.
|
||||
*
|
||||
* Note: The key will be matched against **unescaped** JSON.
|
||||
*
|
||||
* @return The value associated with this field, or:
|
||||
* - NO_SUCH_FIELD if the field does not exist in the object
|
||||
*/
|
||||
inline simdjson_result<element> at_key_case_insensitive(const std::string_view &key) const noexcept;
|
||||
|
||||
/** @private for debugging. Prints out the root element. */
|
||||
inline bool dump_raw_tape(std::ostream &out) const noexcept;
|
||||
|
||||
private:
|
||||
really_inline element(const document *doc, size_t json_index) noexcept;
|
||||
friend class document;
|
||||
friend class object;
|
||||
friend class array;
|
||||
friend struct simdjson_result<element>;
|
||||
template<typename T>
|
||||
friend class simdjson::minify;
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents a JSON array.
|
||||
*/
|
||||
@@ -552,6 +295,279 @@ private:
|
||||
friend class simdjson::minify;
|
||||
};
|
||||
|
||||
/**
|
||||
* A parsed JSON document.
|
||||
*
|
||||
* This class cannot be copied, only moved, to avoid unintended allocations.
|
||||
*/
|
||||
class document {
|
||||
public:
|
||||
/**
|
||||
* Create a document container with zero capacity.
|
||||
*
|
||||
* The parser will allocate capacity as needed.
|
||||
*/
|
||||
document() noexcept=default;
|
||||
~document() noexcept=default;
|
||||
|
||||
/**
|
||||
* Take another document's buffers.
|
||||
*
|
||||
* @param other The document to take. Its capacity is zeroed and it is invalidated.
|
||||
*/
|
||||
document(document &&other) noexcept = default;
|
||||
document(const document &) = delete; // Disallow copying
|
||||
/**
|
||||
* Take another document's buffers.
|
||||
*
|
||||
* @param other The document to take. Its capacity is zeroed.
|
||||
*/
|
||||
document &operator=(document &&other) noexcept = default;
|
||||
document &operator=(const document &) = delete; // Disallow copying
|
||||
|
||||
/**
|
||||
* Get the root element of this document as a JSON array.
|
||||
*/
|
||||
element root() const noexcept;
|
||||
|
||||
/**
|
||||
* Dump the raw tape for debugging.
|
||||
*
|
||||
* @param os the stream to output to.
|
||||
* @return false if the tape is likely wrong (e.g., you did not parse a valid JSON).
|
||||
*/
|
||||
bool dump_raw_tape(std::ostream &os) const noexcept;
|
||||
|
||||
std::unique_ptr<uint64_t[]> tape;
|
||||
std::unique_ptr<uint8_t[]> string_buf;// should be at least byte_capacity
|
||||
|
||||
private:
|
||||
inline error_code set_capacity(size_t len) noexcept;
|
||||
template<typename T>
|
||||
friend class simdjson::minify;
|
||||
friend class parser;
|
||||
}; // class document
|
||||
|
||||
/**
|
||||
* A JSON element.
|
||||
*
|
||||
* References an element in a JSON document, representing a JSON null, boolean, string, number,
|
||||
* array or object.
|
||||
*/
|
||||
class 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;
|
||||
|
||||
/**
|
||||
* Tell whether the value can be cast to the given primitive type.
|
||||
*
|
||||
* Supported types:
|
||||
* - Boolean: bool
|
||||
* - Number: double, uint64_t, int64_t
|
||||
* - String: std::string_view, const char *
|
||||
* - Array: array
|
||||
*/
|
||||
template<typename T>
|
||||
really_inline bool is() const noexcept;
|
||||
|
||||
/**
|
||||
* Get the value as the given primitive type.
|
||||
*
|
||||
* Supported types:
|
||||
* - Boolean: bool
|
||||
* - Number: double, uint64_t, int64_t
|
||||
* - String: std::string_view, const char *
|
||||
* - Array: array
|
||||
*
|
||||
* @returns The value cast to the given type, or:
|
||||
* INCORRECT_TYPE if the value cannot be cast to the given type.
|
||||
*/
|
||||
template<typename T>
|
||||
really_inline simdjson_result<T> get() const noexcept;
|
||||
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
/**
|
||||
* Read this element as a boolean.
|
||||
*
|
||||
* @return The boolean value
|
||||
* @exception simdjson_error(INCORRECT_TYPE) if the JSON element is not a boolean.
|
||||
*/
|
||||
inline operator bool() const noexcept(false);
|
||||
|
||||
/**
|
||||
* Read this element as a null-terminated string.
|
||||
*
|
||||
* Does *not* convert other types to a string; requires that the JSON type of the element was
|
||||
* an actual string.
|
||||
*
|
||||
* @return The string value.
|
||||
* @exception simdjson_error(INCORRECT_TYPE) if the JSON element is not a string.
|
||||
*/
|
||||
inline explicit operator const char*() const noexcept(false);
|
||||
|
||||
/**
|
||||
* Read this element as a null-terminated string.
|
||||
*
|
||||
* Does *not* convert other types to a string; requires that the JSON type of the element was
|
||||
* an actual string.
|
||||
*
|
||||
* @return The string value.
|
||||
* @exception simdjson_error(INCORRECT_TYPE) if the JSON element is not a string.
|
||||
*/
|
||||
inline operator std::string_view() const noexcept(false);
|
||||
|
||||
/**
|
||||
* Read this element as an unsigned integer.
|
||||
*
|
||||
* @return The integer value.
|
||||
* @exception simdjson_error(INCORRECT_TYPE) if the JSON element is not an integer
|
||||
* @exception simdjson_error(NUMBER_OUT_OF_RANGE) if the integer doesn't fit in 64 bits or is negative
|
||||
*/
|
||||
inline operator uint64_t() const noexcept(false);
|
||||
/**
|
||||
* Read this element as an signed integer.
|
||||
*
|
||||
* @return The integer value.
|
||||
* @exception simdjson_error(INCORRECT_TYPE) if the JSON element is not an integer
|
||||
* @exception simdjson_error(NUMBER_OUT_OF_RANGE) if the integer doesn't fit in 64 bits
|
||||
*/
|
||||
inline operator int64_t() const noexcept(false);
|
||||
/**
|
||||
* Read this element as an double.
|
||||
*
|
||||
* @return The double value.
|
||||
* @exception simdjson_error(INCORRECT_TYPE) if the JSON element is not a number
|
||||
* @exception simdjson_error(NUMBER_OUT_OF_RANGE) if the integer doesn't fit in 64 bits or is negative
|
||||
*/
|
||||
inline operator double() const noexcept(false);
|
||||
/**
|
||||
* Read this element as a JSON array.
|
||||
*
|
||||
* @return The JSON array.
|
||||
* @exception simdjson_error(INCORRECT_TYPE) if the JSON element is not an array
|
||||
*/
|
||||
inline operator array() const noexcept(false);
|
||||
/**
|
||||
* Read this element as a JSON object (key/value pairs).
|
||||
*
|
||||
* @return The JSON object.
|
||||
* @exception simdjson_error(INCORRECT_TYPE) if the JSON element is not an object
|
||||
*/
|
||||
inline operator object() const noexcept(false);
|
||||
|
||||
/**
|
||||
* Iterate over each element in this array.
|
||||
*
|
||||
* @return The beginning of the iteration.
|
||||
* @exception simdjson_error(INCORRECT_TYPE) if the JSON element is not an array
|
||||
*/
|
||||
inline dom::array::iterator begin() const noexcept(false);
|
||||
|
||||
/**
|
||||
* Iterate over each element in this array.
|
||||
*
|
||||
* @return The end of the iteration.
|
||||
* @exception simdjson_error(INCORRECT_TYPE) if the JSON element is not an array
|
||||
*/
|
||||
inline dom::array::iterator end() const noexcept(false);
|
||||
#endif // SIMDJSON_EXCEPTIONS
|
||||
|
||||
/**
|
||||
* Get the value associated with the given key.
|
||||
*
|
||||
* The key will be matched against **unescaped** JSON:
|
||||
*
|
||||
* dom::parser parser;
|
||||
* parser.parse(R"({ "a\n": 1 })")["a\n"].get<uint64_t>().value == 1
|
||||
* parser.parse(R"({ "a\n": 1 })")["a\\n"].get<uint64_t>().error == NO_SUCH_FIELD
|
||||
*
|
||||
* @return The value associated with this field, or:
|
||||
* - NO_SUCH_FIELD if the field does not exist in the object
|
||||
* - INCORRECT_TYPE if this is not an object
|
||||
*/
|
||||
inline simdjson_result<element> operator[](const std::string_view &key) const noexcept;
|
||||
|
||||
/**
|
||||
* Get the value associated with the given key.
|
||||
*
|
||||
* The key will be matched against **unescaped** JSON:
|
||||
*
|
||||
* dom::parser parser;
|
||||
* parser.parse(R"({ "a\n": 1 })")["a\n"].get<uint64_t>().value == 1
|
||||
* parser.parse(R"({ "a\n": 1 })")["a\\n"].get<uint64_t>().error == NO_SUCH_FIELD
|
||||
*
|
||||
* @return The value associated with this field, or:
|
||||
* - NO_SUCH_FIELD if the field does not exist in the object
|
||||
* - INCORRECT_TYPE if this is not an object
|
||||
*/
|
||||
inline simdjson_result<element> operator[](const char *key) const noexcept;
|
||||
|
||||
/**
|
||||
* Get the value associated with the given JSON pointer.
|
||||
*
|
||||
* dom::parser parser;
|
||||
* element doc = parser.parse(R"({ "foo": { "a": [ 10, 20, 30 ] }})");
|
||||
* doc.at("/foo/a/1") == 20
|
||||
* doc.at("/")["foo"]["a"].at(1) == 20
|
||||
* doc.at("")["foo"]["a"].at(1) == 20
|
||||
*
|
||||
* @return The value associated with the given JSON pointer, or:
|
||||
* - NO_SUCH_FIELD if a field does not exist in an object
|
||||
* - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
|
||||
* - INCORRECT_TYPE if a non-integer is used to access an array
|
||||
* - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
|
||||
*/
|
||||
inline simdjson_result<element> at(const std::string_view &json_pointer) const noexcept;
|
||||
|
||||
/**
|
||||
* Get the value at the given index.
|
||||
*
|
||||
* @return The value at the given index, or:
|
||||
* - INDEX_OUT_OF_BOUNDS if the array index is larger than an array length
|
||||
*/
|
||||
inline simdjson_result<element> at(size_t index) const noexcept;
|
||||
|
||||
/**
|
||||
* Get the value associated with the given key.
|
||||
*
|
||||
* The key will be matched against **unescaped** JSON:
|
||||
*
|
||||
* dom::parser parser;
|
||||
* parser.parse(R"({ "a\n": 1 })")["a\n"].get<uint64_t>().value == 1
|
||||
* parser.parse(R"({ "a\n": 1 })")["a\\n"].get<uint64_t>().error == NO_SUCH_FIELD
|
||||
*
|
||||
* @return The value associated with this field, or:
|
||||
* - NO_SUCH_FIELD if the field does not exist in the object
|
||||
*/
|
||||
inline simdjson_result<element> at_key(const std::string_view &key) const noexcept;
|
||||
|
||||
/**
|
||||
* Get the value associated with the given key in a case-insensitive manner.
|
||||
*
|
||||
* Note: The key will be matched against **unescaped** JSON.
|
||||
*
|
||||
* @return The value associated with this field, or:
|
||||
* - NO_SUCH_FIELD if the field does not exist in the object
|
||||
*/
|
||||
inline simdjson_result<element> at_key_case_insensitive(const std::string_view &key) const noexcept;
|
||||
|
||||
/** @private for debugging. Prints out the root element. */
|
||||
inline bool dump_raw_tape(std::ostream &out) const noexcept;
|
||||
|
||||
private:
|
||||
really_inline element(const document *doc, size_t json_index) noexcept;
|
||||
friend class document;
|
||||
friend class object;
|
||||
friend class array;
|
||||
friend struct simdjson_result<element>;
|
||||
template<typename T>
|
||||
friend class simdjson::minify;
|
||||
};
|
||||
|
||||
/**
|
||||
* Key/value pair in an object.
|
||||
*/
|
||||
@@ -1445,6 +1461,9 @@ public:
|
||||
inline operator double() const noexcept(false);
|
||||
inline operator dom::array() const noexcept(false);
|
||||
inline operator dom::object() const noexcept(false);
|
||||
|
||||
inline dom::array::iterator begin() const noexcept(false);
|
||||
inline dom::array::iterator end() const noexcept(false);
|
||||
#endif // SIMDJSON_EXCEPTIONS
|
||||
};
|
||||
|
||||
|
||||
@@ -90,6 +90,15 @@ inline simdjson_result<dom::element>::operator dom::object() const noexcept(fals
|
||||
return get<dom::object>();
|
||||
}
|
||||
|
||||
inline dom::array::iterator simdjson_result<dom::element>::begin() const noexcept(false) {
|
||||
if (error()) { throw simdjson_error(error()); }
|
||||
return first.begin();
|
||||
}
|
||||
inline dom::array::iterator simdjson_result<dom::element>::end() const noexcept(false) {
|
||||
if (error()) { throw simdjson_error(error()); }
|
||||
return first.end();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//
|
||||
@@ -830,6 +839,13 @@ inline element::operator double() const noexcept(false) { return get<double>();
|
||||
inline element::operator array() const noexcept(false) { return get<array>(); }
|
||||
inline element::operator object() const noexcept(false) { return get<object>(); }
|
||||
|
||||
inline dom::array::iterator dom::element::begin() const noexcept(false) {
|
||||
return get<array>().begin();
|
||||
}
|
||||
inline dom::array::iterator dom::element::end() const noexcept(false) {
|
||||
return get<array>().end();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
inline simdjson_result<element> element::operator[](const std::string_view &key) const noexcept {
|
||||
|
||||
@@ -211,7 +211,11 @@ bool ParsedJson::Iterator::next() {
|
||||
|
||||
ParsedJson::Iterator::Iterator(const ParsedJson &pj) noexcept(false)
|
||||
: doc(pj.doc), depth(0), location(0), tape_length(0) {
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
if (!pj.valid) { throw simdjson_error(pj.error); }
|
||||
#else
|
||||
if (!pj.valid) { abort(); }
|
||||
#endif
|
||||
|
||||
max_depth = pj.max_depth();
|
||||
depth_index = new scopeindex_t[max_depth + 1];
|
||||
|
||||
+59
-101
@@ -1,123 +1,81 @@
|
||||
#include <iostream>
|
||||
#include "simdjson.h"
|
||||
|
||||
namespace compile_tests {
|
||||
|
||||
using namespace std;
|
||||
using namespace simdjson;
|
||||
using error_code=simdjson::error_code;
|
||||
|
||||
void parser_parse_error_code() {
|
||||
cout << __func__ << endl;
|
||||
void basics_1() {
|
||||
const char *filename = "x.txt";
|
||||
|
||||
// Allocate a parser big enough for all files
|
||||
dom::parser parser;
|
||||
dom::element doc = parser.load(filename); // load and parse a file
|
||||
|
||||
// Read files with the parser, one by one
|
||||
for (padded_string json : { string("[1, 2, 3]"), string("true"), string("[ true, false ]") }) {
|
||||
cout << "Parsing " << json.data() << " ..." << endl;
|
||||
auto [doc, error] = parser.parse(json);
|
||||
if (error) { cerr << "Error: " << error << endl; exit(1); }
|
||||
cout << doc << endl;
|
||||
cout << doc;
|
||||
}
|
||||
|
||||
void basics_2() {
|
||||
dom::parser parser;
|
||||
dom::element doc = parser.parse("[1,2,3]"_padded); // parse a string
|
||||
|
||||
cout << doc;
|
||||
}
|
||||
|
||||
void basics_dom_1() {
|
||||
auto cars_json = R"( [
|
||||
{ "make": "Toyota", "model": "Camry", "year": 2018, "tire_pressure": [ 40.1, 39.9, 37.7, 40.4 ] },
|
||||
{ "make": "Kia", "model": "Soul", "year": 2012, "tire_pressure": [ 30.1, 31.0, 28.6, 28.7 ] },
|
||||
{ "make": "Toyota", "model": "Tercel", "year": 1999, "tire_pressure": [ 29.8, 30.0, 30.2, 30.5 ] }
|
||||
] )"_padded;
|
||||
dom::parser parser;
|
||||
dom::array cars = parser.parse(cars_json).get<dom::array>();
|
||||
|
||||
// Iterating through an array of objects
|
||||
for (dom::object car : cars) {
|
||||
// Accessing a field by name
|
||||
cout << "Make/Model: " << car["make"] << "/" << car["model"] << endl;
|
||||
|
||||
// Casting a JSON element to an integer
|
||||
uint64_t year = car["year"];
|
||||
cout << "- This car is " << 2020 - year << "years old." << endl;
|
||||
|
||||
// Iterating through an array of floats
|
||||
double total_tire_pressure = 0;
|
||||
for (double tire_pressure : car["tire_pressure"]) {
|
||||
total_tire_pressure += tire_pressure;
|
||||
}
|
||||
cout << "- Average tire pressure: " << (total_tire_pressure / 4) << endl;
|
||||
|
||||
// Writing out all the information about the car
|
||||
for (auto [key, value] : car) {
|
||||
cout << "- " << key << ": " << value << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void parser_parse_many_error_code() {
|
||||
cout << __func__ << endl;
|
||||
|
||||
// Read files with the parser
|
||||
auto json = "[1, 2, 3] true [ true, false ]"_padded;
|
||||
cout << "Parsing " << json.data() << " ..." << endl;
|
||||
void basics_dom_2() {
|
||||
auto cars_json = R"( [
|
||||
{ "make": "Toyota", "model": "Camry", "year": 2018, "tire_pressure": [ 40.1, 39.9, 37.7, 40.4 ] },
|
||||
{ "make": "Kia", "model": "Soul", "year": 2012, "tire_pressure": [ 30.1, 31.0, 28.6, 28.7 ] },
|
||||
{ "make": "Toyota", "model": "Tercel", "year": 1999, "tire_pressure": [ 29.8, 30.0, 30.2, 30.5 ] }
|
||||
] )"_padded;
|
||||
dom::parser parser;
|
||||
for (auto [doc, error] : parser.parse_many(json)) {
|
||||
if (error) { cerr << "Error: " << error << endl; exit(1); }
|
||||
cout << doc << endl;
|
||||
}
|
||||
dom::element cars = parser.parse(cars_json);
|
||||
cout << cars.at("0/tire_pressure/1") << endl; // Prints 39.9}
|
||||
}
|
||||
|
||||
void parser_parse_max_capacity() {
|
||||
cout << __func__ << endl;
|
||||
|
||||
int argc = 2;
|
||||
padded_string argv[] { string("[1,2,3]"), string("true") };
|
||||
dom::parser parser(1024*1024); // Set max capacity to 1MB
|
||||
for (int i=0;i<argc;i++) {
|
||||
auto [doc, error] = parser.parse(argv[i]);
|
||||
if (error == CAPACITY) { cerr << "JSON files larger than 1MB are not supported!" << endl; exit(1); }
|
||||
if (error) { cerr << error << endl; exit(1); }
|
||||
cout << doc << endl;
|
||||
}
|
||||
}
|
||||
|
||||
void parser_parse_fixed_capacity() {
|
||||
cout << __func__ << endl;
|
||||
|
||||
int argc = 2;
|
||||
padded_string argv[] { string("[1,2,3]"), string("true") };
|
||||
dom::parser parser(0); // This parser is not allowed to auto-allocate
|
||||
auto alloc_error = parser.set_capacity(1024*1024);
|
||||
if (alloc_error) { cerr << alloc_error << endl; exit(1); }; // Set initial capacity to 1MB
|
||||
for (int i=0;i<argc;i++) {
|
||||
auto [doc, error] = parser.parse(argv[i]);
|
||||
if (error == CAPACITY) { cerr << "JSON files larger than 1MB are not supported!" << endl; exit(1); }
|
||||
if (error) { cerr << error << endl; exit(1); }
|
||||
cout << doc << endl;
|
||||
}
|
||||
}
|
||||
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
|
||||
void parser_parse_padded_string() {
|
||||
cout << __func__ << endl;
|
||||
|
||||
auto json = "[ 1, 2, 3 ]"_padded;
|
||||
void basics_ndjson() {
|
||||
dom::parser parser;
|
||||
cout << parser.parse(json) << endl;
|
||||
}
|
||||
|
||||
void parser_parse_get_corpus() {
|
||||
cout << __func__ << endl;
|
||||
|
||||
auto json = get_corpus("jsonexamples/small/demo.json");
|
||||
dom::parser parser;
|
||||
cout << parser.parse(json) << endl;
|
||||
}
|
||||
|
||||
void parser_parse_exception() {
|
||||
cout << __func__ << endl;
|
||||
|
||||
// Allocate a parser big enough for all files
|
||||
dom::parser parser;
|
||||
|
||||
// Read files with the parser, one by one
|
||||
for (padded_string json : { string("[1, 2, 3]"), string("true"), string("[ true, false ]") }) {
|
||||
cout << "Parsing " << json.data() << " ..." << endl;
|
||||
cout << parser.parse(json) << endl;
|
||||
for (dom::element doc : parser.load_many("x.txt")) {
|
||||
cout << doc["foo"] << endl;
|
||||
}
|
||||
// Prints 1 2 3
|
||||
}
|
||||
|
||||
void parser_parse_many_exception() {
|
||||
cout << __func__ << endl;
|
||||
|
||||
// Read files with the parser
|
||||
auto json = "[1, 2, 3] true [ true, false ]"_padded;
|
||||
cout << "Parsing " << json.data() << " ..." << endl;
|
||||
dom::parser parser;
|
||||
for (const dom::element doc : parser.parse_many(json)) {
|
||||
cout << doc << endl;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SIMDJSON_EXCEPTIONS
|
||||
} // namespace basics
|
||||
|
||||
int main() {
|
||||
cout << "Running examples." << endl;
|
||||
parser_parse_error_code();
|
||||
parser_parse_many_error_code();
|
||||
parser_parse_max_capacity();
|
||||
parser_parse_fixed_capacity();
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
parser_parse_exception();
|
||||
parser_parse_many_exception();
|
||||
parser_parse_padded_string();
|
||||
parser_parse_get_corpus();
|
||||
#endif // SIMDJSON_EXCEPTIONS
|
||||
cout << "Ran to completion!" << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
#include <iostream>
|
||||
#include "simdjson.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace simdjson;
|
||||
|
||||
void basics_error_1() {
|
||||
dom::parser parser;
|
||||
auto json = "1"_padded;
|
||||
|
||||
auto [doc, error] = parser.parse(json); // doc is a dom::element
|
||||
if (error) { cerr << error << endl; exit(1); }
|
||||
// Use document here now that we've checked for the error
|
||||
}
|
||||
|
||||
void basics_error_2() {
|
||||
dom::parser parser;
|
||||
auto json = "1"_padded;
|
||||
|
||||
dom::element doc;
|
||||
simdjson::error_code error;
|
||||
parser.parse(json).tie(doc, error); // <-- Assigns to doc and error just like "auto [doc, error]"}
|
||||
}
|
||||
|
||||
void basics_error_3() {
|
||||
auto cars_json = R"( [
|
||||
{ "make": "Toyota", "model": "Camry", "year": 2018, "tire_pressure": [ 40.1, 39.9, 37.7, 40.4 ] },
|
||||
{ "make": "Kia", "model": "Soul", "year": 2012, "tire_pressure": [ 30.1, 31.0, 28.6, 28.7 ] },
|
||||
{ "make": "Toyota", "model": "Tercel", "year": 1999, "tire_pressure": [ 29.8, 30.0, 30.2, 30.5 ] }
|
||||
] )"_padded;
|
||||
dom::parser parser;
|
||||
auto [cars, error] = parser.parse(cars_json).get<dom::array>();
|
||||
if (error) { cerr << error << endl; exit(1); }
|
||||
|
||||
// Iterating through an array of objects
|
||||
for (dom::element car_element : cars) {
|
||||
dom::object car;
|
||||
car_element.get<dom::object>().tie(car, error);
|
||||
if (error) { cerr << error << endl; exit(1); }
|
||||
|
||||
// Accessing a field by name
|
||||
dom::element make, model;
|
||||
car["make"].tie(make, error);
|
||||
if (error) { cerr << error << endl; exit(1); }
|
||||
car["model"].tie(model, error);
|
||||
if (error) { cerr << error << endl; exit(1); }
|
||||
cout << "Make/Model: " << make << "/" << model << endl;
|
||||
|
||||
// Casting a JSON element to an integer
|
||||
uint64_t year;
|
||||
car["year"].get<uint64_t>().tie(year, error);
|
||||
if (error) { cerr << error << endl; exit(1); }
|
||||
cout << "- This car is " << 2020 - year << "years old." << endl;
|
||||
|
||||
// Iterating through an array of floats
|
||||
double total_tire_pressure = 0;
|
||||
dom::array tire_pressure_array;
|
||||
car["tire_pressure"].get<dom::array>().tie(tire_pressure_array, error);
|
||||
if (error) { cerr << error << endl; exit(1); }
|
||||
for (dom::element tire_pressure_element : tire_pressure_array) {
|
||||
double tire_pressure;
|
||||
tire_pressure_element.get<double>().tie(tire_pressure, error);
|
||||
if (error) { cerr << error << endl; exit(1); }
|
||||
total_tire_pressure += tire_pressure;
|
||||
}
|
||||
cout << "- Average tire pressure: " << (total_tire_pressure / 4) << endl;
|
||||
|
||||
// Writing out all the information about the car
|
||||
for (auto [key, value] : car) {
|
||||
cout << "- " << key << ": " << value << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user