Move document/element/etc. under dom

This commit is contained in:
John Keiser 2020-03-28 11:43:41 -07:00
parent de001da35b
commit 03746b966b
52 changed files with 820 additions and 783 deletions

View File

@ -48,8 +48,8 @@ The simdjson library is easily consumable with a single .h and .cpp file.
```c++
#include "simdjson.h"
int main(void) {
simdjson::document::parser parser;
simdjson::document::element tweets = parser.load("twitter.json");
simdjson::dom::parser parser;
simdjson::dom::element tweets = parser.load("twitter.json");
std::cout << tweets["search_metadata"]["count"] << " results." << std::endl;
}
```

View File

@ -127,7 +127,7 @@ int main(int argc, char *argv[]) {
std::cerr << "Please specify at least one file name. " << std::endl;
}
const char * filename = argv[1];
simdjson::document::parser parser;
simdjson::dom::parser parser;
auto [doc, error] = parser.load(filename); // do the parsing
if (error) {
std::cout << "parse failed" << std::endl;

View File

@ -16,8 +16,8 @@ const padded_string EMPTY_ARRAY("[]", 2);
static void twitter_count(State& state) {
// Prints the number of results in twitter.json
document::parser parser;
document::element doc = parser.load(JSON_TEST_PATH);
dom::parser parser;
dom::element doc = parser.load(JSON_TEST_PATH);
for (auto _ : state) {
uint64_t result_count = doc["search_metadata"]["count"];
if (result_count != 100) { return; }
@ -44,12 +44,12 @@ BENCHMARK(iterator_twitter_count);
static void twitter_default_profile(State& state) {
// Count unique users with a default profile.
document::parser parser;
document::element doc = parser.load(JSON_TEST_PATH);
dom::parser parser;
dom::element doc = parser.load(JSON_TEST_PATH);
for (auto _ : state) {
set<string_view> default_users;
for (document::object tweet : doc["statuses"].as_array()) {
document::object user = tweet["user"];
for (dom::object tweet : doc["statuses"].as_array()) {
dom::object user = tweet["user"];
if (user["default_profile"]) {
default_users.insert(user["screen_name"]);
}
@ -61,14 +61,14 @@ BENCHMARK(twitter_default_profile);
static void twitter_image_sizes(State& state) {
// Count unique image sizes
document::parser parser;
document::element doc = parser.load(JSON_TEST_PATH);
dom::parser parser;
dom::element doc = parser.load(JSON_TEST_PATH);
for (auto _ : state) {
set<tuple<uint64_t, uint64_t>> image_sizes;
for (document::object tweet : doc["statuses"].as_array()) {
for (dom::object tweet : doc["statuses"].as_array()) {
auto [media, not_found] = tweet["entities"]["media"];
if (!not_found) {
for (document::object image : media.as_array()) {
for (dom::object image : media.as_array()) {
for (auto [key, size] : image["sizes"].as_object()) {
image_sizes.insert({ size["w"], size["h"] });
}
@ -84,8 +84,8 @@ BENCHMARK(twitter_image_sizes);
static void error_code_twitter_count(State& state) noexcept {
// Prints the number of results in twitter.json
document::parser parser;
document::element doc = parser.load(JSON_TEST_PATH);
dom::parser parser;
dom::element doc = parser.load(JSON_TEST_PATH);
for (auto _ : state) {
auto [value, error] = doc["search_metadata"]["count"].as_uint64_t();
if (error) { return; }
@ -96,14 +96,14 @@ BENCHMARK(error_code_twitter_count);
static void error_code_twitter_default_profile(State& state) noexcept {
// Count unique users with a default profile.
document::parser parser;
document::element doc = parser.load(JSON_TEST_PATH);
dom::parser parser;
dom::element doc = parser.load(JSON_TEST_PATH);
for (auto _ : state) {
set<string_view> default_users;
auto [tweets, error] = doc["statuses"].as_array();
if (error) { return; }
for (document::element tweet : tweets) {
for (dom::element tweet : tweets) {
auto [user, error2] = tweet["user"].as_object();
if (error2) { return; }
auto [default_profile, error3] = user["default_profile"].as_bool();
@ -128,12 +128,12 @@ static void iterator_twitter_default_profile(State& state) {
set<string_view> default_users;
ParsedJson::Iterator iter(pj);
// for (document::object tweet : doc["statuses"].as_array()) {
// for (dom::object tweet : doc["statuses"].as_array()) {
if (!(iter.move_to_key("statuses") && iter.is_array())) { return; }
if (iter.down()) { // first status
do {
// document::object user = tweet["user"];
// dom::object user = tweet["user"];
if (!(iter.move_to_key("user") && iter.is_object())) { return; }
// if (user["default_profile"]) {
@ -160,16 +160,16 @@ BENCHMARK(iterator_twitter_default_profile);
static void error_code_twitter_image_sizes(State& state) noexcept {
// Count unique image sizes
document::parser parser;
document::element doc = parser.load(JSON_TEST_PATH);
dom::parser parser;
dom::element doc = parser.load(JSON_TEST_PATH);
for (auto _ : state) {
set<tuple<uint64_t, uint64_t>> image_sizes;
auto [statuses, error] = doc["statuses"].as_array();
if (error) { return; }
for (document::element tweet : statuses) {
for (dom::element tweet : statuses) {
auto [images, not_found] = tweet["entities"]["media"].as_array();
if (!not_found) {
for (document::element image : images) {
for (dom::element image : images) {
auto [sizes, error2] = image["sizes"].as_object();
if (error2) { return; }
for (auto [key, size] : sizes) {
@ -194,7 +194,7 @@ static void iterator_twitter_image_sizes(State& state) {
set<tuple<uint64_t, uint64_t>> image_sizes;
ParsedJson::Iterator iter(pj);
// for (document::object tweet : doc["statuses"].as_array()) {
// for (dom::object tweet : doc["statuses"].as_array()) {
if (!(iter.move_to_key("statuses") && iter.is_array())) { return; }
if (iter.down()) { // first status
do {
@ -206,7 +206,7 @@ static void iterator_twitter_image_sizes(State& state) {
if (iter.move_to_key("media")) {
if (!iter.is_array()) { return; }
// for (document::object image : media.as_array()) {
// for (dom::object image : media.as_array()) {
if (iter.down()) { // first media
do {
@ -247,7 +247,7 @@ BENCHMARK(iterator_twitter_image_sizes);
static void print_json(State& state) noexcept {
// Prints the number of results in twitter.json
padded_string json = get_corpus(JSON_TEST_PATH);
document::parser parser;
dom::parser parser;
if (!parser.allocate_capacity(json.length())) { cerr << "allocation failed" << endl; return; }
if (int error = json_parse(json, parser); error != SUCCESS) { cerr << error_message(error) << endl; return; }
for (auto _ : state) {

View File

@ -7,7 +7,7 @@ using namespace std;
const padded_string EMPTY_ARRAY("[]", 2);
static void json_parse(State& state) {
document::parser parser;
dom::parser parser;
if (parser.set_capacity(EMPTY_ARRAY.length())) { return; }
for (auto _ : state) {
auto error = simdjson::json_parse(EMPTY_ARRAY, parser);
@ -16,7 +16,7 @@ static void json_parse(State& state) {
}
BENCHMARK(json_parse);
static void parser_parse_error_code(State& state) {
document::parser parser;
dom::parser parser;
if (parser.set_capacity(EMPTY_ARRAY.length())) { return; }
for (auto _ : state) {
auto [doc, error] = parser.parse(EMPTY_ARRAY);
@ -25,11 +25,11 @@ static void parser_parse_error_code(State& state) {
}
BENCHMARK(parser_parse_error_code);
static void parser_parse_exception(State& state) {
document::parser parser;
dom::parser parser;
if (parser.set_capacity(EMPTY_ARRAY.length())) { return; }
for (auto _ : state) {
try {
UNUSED document::element doc = parser.parse(EMPTY_ARRAY);
UNUSED dom::element doc = parser.parse(EMPTY_ARRAY);
} catch(simdjson_error &j) {
return;
}
@ -39,14 +39,14 @@ BENCHMARK(parser_parse_exception);
static void build_parsed_json(State& state) {
for (auto _ : state) {
document::parser parser = simdjson::build_parsed_json(EMPTY_ARRAY);
dom::parser parser = simdjson::build_parsed_json(EMPTY_ARRAY);
if (!parser.valid) { return; }
}
}
BENCHMARK(build_parsed_json);
static void document_parse_error_code(State& state) {
for (auto _ : state) {
document::parser parser;
dom::parser parser;
auto [doc, error] = parser.parse(EMPTY_ARRAY);
if (error) { return; }
}
@ -55,8 +55,8 @@ BENCHMARK(document_parse_error_code);
static void document_parse_exception(State& state) {
for (auto _ : state) {
try {
document::parser parser;
UNUSED document::element doc = parser.parse(EMPTY_ARRAY);
dom::parser parser;
UNUSED dom::element doc = parser.parse(EMPTY_ARRAY);
} catch(simdjson_error &j) {
return;
}

View File

@ -125,7 +125,7 @@ struct option_struct {
if (arch == architecture::UNSUPPORTED) {
arch = find_best_supported_architecture();
}
document::parser::use_implementation(arch);
dom::parser::use_implementation(arch);
}
template<typename F>

View File

@ -77,7 +77,7 @@ struct json_stats {
size_t blocks_with_16_structurals = 0;
size_t blocks_with_16_structurals_flipped = 0;
json_stats(const padded_string& json, const document::parser& parser) {
json_stats(const padded_string& json, const dom::parser& parser) {
bytes = json.size();
blocks = bytes / BYTES_PER_BLOCK;
if (bytes % BYTES_PER_BLOCK > 0) { blocks++; } // Account for remainder block
@ -291,9 +291,9 @@ struct benchmarker {
}
really_inline void run_iteration(bool stage1_only, bool hotbuffers=false) {
// Allocate document::parser
// Allocate dom::parser
collector.start();
document::parser parser;
dom::parser parser;
bool alloc_ok = parser.allocate_capacity(json.size());
event_count allocate_count = collector.end();
allocate_stage << allocate_count;

View File

@ -38,7 +38,7 @@ void print_vec(const std::vector<int64_t> &v) {
// clang-format off
// simdjson_recurse below come be implemented like so but it is slow:
/*void simdjson_recurse(std::vector<int64_t> & v, simdjson::document::element element) {
/*void simdjson_recurse(std::vector<int64_t> & v, simdjson::dom::element element) {
if (element.is_array()) {
auto [array, array_error] = element.as_array();
for (auto child : array) {
@ -63,7 +63,7 @@ void print_vec(const std::vector<int64_t> &v) {
// clang-format on
void simdjson_recurse(std::vector<int64_t> & v, simdjson::document::element element) {
void simdjson_recurse(std::vector<int64_t> & v, simdjson::dom::element element) {
if (element.is_array()) {
auto array = element.as_array();
for (auto child : array) {
@ -100,7 +100,7 @@ void simdjson_recurse(std::vector<int64_t> & v, simdjson::document::element elem
}
__attribute__((noinline)) std::vector<int64_t>
simdjson_just_dom(simdjson::document::element doc) {
simdjson_just_dom(simdjson::dom::element doc) {
std::vector<int64_t> answer;
simdjson_recurse(answer, doc);
remove_duplicates(answer);
@ -110,8 +110,8 @@ simdjson_just_dom(simdjson::document::element doc) {
__attribute__((noinline)) std::vector<int64_t>
simdjson_compute_stats(const simdjson::padded_string &p) {
std::vector<int64_t> answer;
simdjson::document::parser parser;
simdjson::document::element doc = parser.parse(p);
simdjson::dom::parser parser;
simdjson::dom::element doc = parser.parse(p);
simdjson_recurse(answer, doc);
remove_duplicates(answer);
return answer;
@ -119,7 +119,7 @@ simdjson_compute_stats(const simdjson::padded_string &p) {
__attribute__((noinline)) simdjson::error_code
simdjson_just_parse(const simdjson::padded_string &p) {
simdjson::document::parser parser;
simdjson::dom::parser parser;
return parser.parse(p).error();
}
@ -372,8 +372,8 @@ int main(int argc, char *argv[]) {
volume, !just_data);
BEST_TIME("sasjon (just parse) ", sasjon_just_parse(p), false, , repeat,
volume, !just_data);
simdjson::document::parser parser;
simdjson::document::element doc = parser.parse(p);
simdjson::dom::parser parser;
simdjson::dom::element doc = parser.parse(p);
BEST_TIME("simdjson (just dom) ", simdjson_just_dom(doc).size(), size,
, repeat, volume, !just_data);
char *buffer = (char *)malloc(p.size() + 1);

View File

@ -151,7 +151,7 @@ int main(int argc, char *argv[]) {
.is_valid(),
true, memcpy(buffer, mini_buffer, p.size()), repeat, volume, !just_data);
simdjson::document::parser parser;
simdjson::dom::parser parser;
bool automated_reallocation = false;
BEST_TIME("simdjson orig",
parser.parse((const uint8_t *)buffer, p.size(),

View File

@ -35,7 +35,7 @@ int main (int argc, char *argv[]){
std::cout << "Gigabytes/second\t" << "Nb of documents parsed" << std::endl;
for (auto i = 0; i < 3; i++) {
//Actual test
simdjson::document::parser parser;
simdjson::dom::parser parser;
simdjson::error_code alloc_error = parser.set_capacity(p.size());
if (alloc_error) {
std::cerr << alloc_error << std::endl;
@ -76,7 +76,7 @@ int main (int argc, char *argv[]){
int count;
for (size_t j = 0; j < 5; j++) {
//Actual test
simdjson::document::parser parser;
simdjson::dom::parser parser;
simdjson::error_code error;
auto start = std::chrono::steady_clock::now();
@ -115,7 +115,7 @@ int main (int argc, char *argv[]){
for (int i = 0; i < NB_ITERATION; i++) {
// Actual test
simdjson::document::parser parser;
simdjson::dom::parser parser;
simdjson::error_code error;
auto start = std::chrono::steady_clock::now();

View File

@ -50,7 +50,7 @@ void print_stat(const stat_t &s) {
really_inline void simdjson_process_atom(stat_t &s,
simdjson::document::element element) {
simdjson::dom::element element) {
if (element.is_number()) {
s.number_count++;
} else if (element.is_bool()) {
@ -64,7 +64,7 @@ really_inline void simdjson_process_atom(stat_t &s,
}
}
void simdjson_recurse(stat_t &s, simdjson::document::element element) {
void simdjson_recurse(stat_t &s, simdjson::dom::element element) {
if (element.is_array()) {
s.array_count++;
auto [array, array_error] = element.as_array();
@ -93,7 +93,7 @@ void simdjson_recurse(stat_t &s, simdjson::document::element element) {
__attribute__((noinline)) stat_t
simdjson_compute_stats(const simdjson::padded_string &p) {
stat_t s{};
simdjson::document::parser parser;
simdjson::dom::parser parser;
auto [doc, error] = parser.parse(p);
if (error) {
s.valid = false;

View File

@ -109,10 +109,10 @@ bool bench(const char *filename, bool verbose, bool just_data, int repeat_multip
}
if (!just_data)
BEST_TIME("simdjson (dynamic mem) ", !simdjson::document::parser().parse(p).error(), true,
BEST_TIME("simdjson (dynamic mem) ", !simdjson::dom::parser().parse(p).error(), true,
, repeat, volume, !just_data);
// (static alloc)
simdjson::document::parser parser;
simdjson::dom::parser parser;
BEST_TIME("simdjson ", parser.parse(p).error(), simdjson::SUCCESS, , repeat, volume,
!just_data);

View File

@ -44,7 +44,7 @@ using stat_t = struct stat_s;
really_inline void simdjson_process_atom(stat_t &s,
simdjson::document::element element) {
simdjson::dom::element element) {
if (element.is_integer()) {
s.integer_count++;
} else if(element.is_string()) {
@ -62,7 +62,7 @@ really_inline void simdjson_process_atom(stat_t &s,
}
}
void simdjson_recurse(stat_t &s, simdjson::document::element element) {
void simdjson_recurse(stat_t &s, simdjson::dom::element element) {
if (element.is_array()) {
s.array_count++;
auto [array, array_error] = element.as_array();
@ -91,7 +91,7 @@ void simdjson_recurse(stat_t &s, simdjson::document::element element) {
stat_t simdjson_compute_stats(const simdjson::padded_string &p) {
stat_t answer{};
simdjson::document::parser parser;
simdjson::dom::parser parser;
auto [doc, error] = parser.parse(p);
if (error) {
answer.valid = false;
@ -159,7 +159,7 @@ int main(int argc, char *argv[]) {
s.non_ascii_byte_count, s.object_count, s.array_count, s.null_count,
s.true_count, s.false_count, s.byte_count, s.structural_indexes_count);
#ifdef __linux__
simdjson::document::parser parser;
simdjson::dom::parser parser;
const simdjson::implementation &stage_parser = *simdjson::active_implementation;
bool allocok = parser.allocate_capacity(p.size());
if (!allocok) {

View File

@ -34,19 +34,19 @@ The Basics: Loading and Parsing JSON Documents
----------------------------------------------
The simdjson library offers a simple DOM tree API, which you can access by creating a
`document::parser` and calling the `load()` method:
`dom::parser` and calling the `load()` method:
```c++
document::parser parser;
document::element doc = parser.load(filename); // load and parse a file
dom::parser parser;
dom::element doc = parser.load(filename); // load and parse a file
```
Or by creating a padded string (for efficiency reasons, simdjson requires a string with
SIMDJSON_PADDING bytes at the end) and calling `parse()`:
```c++
document::parser parser;
document::element doc = parser.parse("[1,2,3]"_padded); // parse a string
dom::parser parser;
dom::element doc = parser.parse("[1,2,3]"_padded); // parse a string
```
Using the Parsed JSON
@ -56,7 +56,7 @@ Once you have an element, you can navigate it with idiomatic C++ iterators, oper
* **Extracting Values:** You can cast a JSON element to a native type: `double(element)` or
`double x = json_element`. This works for double, uint64_t, int64_t, bool,
document::object and document::array. You can also use is_*typename*()` to test if it is a
dom::object and dom::array. You can also use is_*typename*()` to test if it is a
given type, and as_*typename*() to do the cast and return an error code on failure instead of an
exception.
* **Field Access:** To get the value of the "foo" field in an object, use `object["foo"]`.
@ -72,11 +72,11 @@ auto cars_json = R"( [
{ "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;
document::parser parser;
document::array cars = parser.parse(cars_json).as_array();
dom::parser parser;
dom::array cars = parser.parse(cars_json).as_array();
// Iterating through an array of objects
for (document::object car : cars) {
for (dom::object car : cars) {
// Accessing a field by name
cout << "Make/Model: " << car["make"] << "/" << car["model"] << endl;
@ -109,8 +109,8 @@ auto cars_json = R"( [
{ "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;
document::parser parser;
document::element cars = parser.parse(cars_json);
dom::parser parser;
dom::element cars = parser.parse(cars_json);
cout << cars["/0/tire_pressure/1"] << endl; // Prints 39.9
```
@ -121,7 +121,7 @@ All simdjson APIs that can fail return `simdjson_result<T>`, which is a &lt;valu
pair. The error codes and values can be accessed directly, reading the error like so:
```c++
auto [doc, error] = parser.parse(json); // doc is a document::element
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
```
@ -136,7 +136,7 @@ behavior.
> circumvent this, you can use this instead:
>
> ```c++
> document::element doc;
> dom::element doc;
> error_code error;
> parser.parse(json).tie(doc, error); // <-- Assigns to doc and error just like "auto [doc, error]"
> ```
@ -151,18 +151,18 @@ auto cars_json = R"( [
{ "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;
document::parser parser;
dom::parser parser;
auto [doc, error] = parser.parse(cars_json);
if (error) { cerr << error << endl; exit(1); }
// Iterating through an array of objects
for (document::element car_element : cars) {
document::object car;
for (dom::element car_element : cars) {
dom::object car;
car_element.as_object().tie(car, error);
if (error) { cerr << error << endl; exit(1); }
// Accessing a field by name
document::element make, model;
dom::element make, model;
car["make"].tie(make, error);
if (error) { cerr << error << endl; exit(1); }
car["model"].tie(model, error);
@ -177,7 +177,7 @@ for (document::element car_element : cars) {
// Iterating through an array of floats
double total_tire_pressure = 0;
for (document::element tire_pressure_element : car["tire_pressure"]) {
for (dom::element tire_pressure_element : car["tire_pressure"]) {
double tire_pressure;
tire_pressure_element.as_uint64_t().tie(tire_pressure, error);
if (error) { cerr << error << endl; exit(1); }
@ -197,7 +197,7 @@ for (document::element car_element : cars) {
Users more comfortable with an exception flow may choose to directly cast the `simdjson_result<T>` to the desired type:
```c++
document::element doc = parser.parse(json); // Throws an exception if there was an error!
dom::element doc = parser.parse(json); // Throws an exception if there was an error!
```
When used this way, a `simdjson_error` exception will be thrown if an error occurs, preventing the
@ -216,8 +216,8 @@ auto ndjson = R"(
{ "foo": 2 }
{ "foo": 3 }
)"_padded;
document::parser parser;
for (document::element doc : parser.load_many(filename)) {
dom::parser parser;
for (dom::element doc : parser.load_many(filename)) {
cout << doc["foo"] << endl;
}
// Prints 1 2 3
@ -229,7 +229,7 @@ Thread Safety
-------------
The simdjson library is mostly single-threaded. Thread safety is the responsibility of the caller:
it is unsafe to reuse a document::parser object between different threads.
it is unsafe to reuse a dom::parser object between different threads.
simdjson's CPU detection, which runs the first time parsing is attempted and switches to the fastest
parser for your CPU, is transparent and thread-safe.

View File

@ -18,10 +18,10 @@ and reuse it. The simdjson library will allocate and retain internal buffers bet
buffers hot in cache and keeping memory allocation and initialization to a minimum.
```c++
document::parser parser;
dom::parser parser;
// This initializes buffers and a document big enough to handle this JSON.
document::element doc = parser.parse("[ true, false ]"_padded);
dom::element doc = parser.parse("[ true, false ]"_padded);
cout << doc << endl;
// This reuses the existing buffers, and reuses and *overwrites* the old document
@ -29,20 +29,20 @@ doc = parser.parse("[1, 2, 3]"_padded);
cout << doc << endl;
// This also reuses the existing buffers, and reuses and *overwrites* the old document
document::element doc2 = parser.parse("true"_padded);
dom::element doc2 = parser.parse("true"_padded);
// Even if you keep the old reference around, doc and doc2 refer to the same document.
cout << doc << endl;
cout << doc2 << endl;
```
It's not just internal buffers though. The simdjson library reuses the document itself. document::element, document::object and document::array are *references* to the internal document.
It's not just internal buffers though. The simdjson library reuses the document itself. dom::element, dom::object and dom::array are *references* to the internal document.
You are only *borrowing* the document from simdjson, which purposely reuses and overwrites it each
time you call parse. This prevent wasteful and unnecessary memory allocation in 99% of cases where
JSON is just read, used, and converted to native values or thrown away.
> **You are only borrowing the document from the simdjson parser. Don't keep it long term!**
This is key: don't keep the `document&`, `document::element`, `document::array`, `document::object`
This is key: don't keep the `document&`, `dom::element`, `dom::array`, `dom::object`
or `string_view` objects you get back from the API. Convert them to C++ native values, structs and
arrays that you own.
@ -61,7 +61,7 @@ without bound:
* You can set a *max capacity* when constructing a parser:
```c++
document::parser parser(1024*1024); // Never grow past documents > 1MB
dom::parser parser(1024*1024); // Never grow past documents > 1MB
for (web_request request : listen()) {
auto [doc, error] = parser.parse(request.body);
// If the document was above our limit, emit 413 = payload too large
@ -76,7 +76,7 @@ without bound:
predictability and reliability, since simdjson will never call malloc after startup!
```c++
document::parser parser(0); // This parser will refuse to automatically grow capacity
dom::parser parser(0); // This parser will refuse to automatically grow capacity
parser.set_capacity(1024*1024); // This allocates enough capacity to handle documents <= 1MB
for (web_request request : listen()) {
auto [doc, error] = parser.parse(request.body);

View File

@ -30,7 +30,7 @@ constexpr size_t SIMDJSON_PADDING = 32;
/**
* By default, simdjson supports this many nested objects and arrays.
*
* This is the default for document::parser::max_depth().
* This is the default for parser::max_depth().
*/
constexpr size_t DEFAULT_MAX_DEPTH = 1024;

View File

@ -10,13 +10,80 @@
#include "simdjson/simdjson.h"
#include "simdjson/padded_string.h"
namespace simdjson::dom {
class parser;
class element;
class array;
class object;
class key_value_pair;
class stream;
class document;
/** The default batch size for parser.parse_many() and parser.load_many() */
static constexpr size_t DEFAULT_BATCH_SIZE = 1000000;
} // namespace simdjson::dom
namespace simdjson {
template<> struct simdjson_result<dom::element>;
template<> struct simdjson_result<dom::array>;
template<> struct simdjson_result<dom::object>;
template<typename T>
class minify;
} // namespace simdjson
namespace simdjson::internal {
using namespace simdjson::dom;
constexpr const uint64_t JSON_VALUE_MASK = 0x00FFFFFFFFFFFFFF;
enum class tape_type;
class tape_ref;
/**
* 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.
*/
class tape_ref {
public:
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 index of this element on `doc.tape[]` */
size_t json_index;
};
} // namespace simdjson::internal
namespace simdjson {
namespace simdjson::dom {
/**
* A parsed JSON document.
@ -48,17 +115,6 @@ public:
document &operator=(document &&other) noexcept = default;
document &operator=(const document &) = delete; // Disallow copying
/** The default batch size for parse_many and load_many */
static constexpr size_t DEFAULT_BATCH_SIZE = 1000000;
// Nested classes
class element;
class array;
class object;
class key_value_pair;
class parser;
class stream;
/**
* Get the root element of this document as a JSON array.
*/
@ -78,64 +134,17 @@ public:
private:
inline error_code set_capacity(size_t len) noexcept;
template<typename T>
friend class minify;
friend class simdjson::minify;
friend class parser;
}; // class document
template<typename T>
class minify;
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.
*/
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;
/** The document this element references. */
const document *doc;
/** The index of this element on `doc.tape[]` */
size_t json_index;
friend class document::key_value_pair;
template<typename T>
friend class simdjson::minify;
};
} // namespace simdjson::internal
/**
* A JSON element.
*
* References an element in a JSON document, representing a JSON null, boolean, string, number,
* array or object.
*/
class document::element : protected internal::tape_ref {
class element : protected internal::tape_ref {
public:
/** Create a new, invalid element. */
really_inline element() noexcept;
@ -295,21 +304,21 @@ public:
* @return The JSON array.
* @exception simdjson_error(UNEXPECTED_TYPE) if the JSON element is not an array
*/
inline operator document::array() const noexcept(false);
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 document::object() const noexcept(false);
inline operator object() const noexcept(false);
#endif // SIMDJSON_EXCEPTIONS
/**
* Get the value associated with the given JSON pointer.
*
* document::parser parser;
* document::element doc = parser.parse(R"({ "foo": { "a": [ 10, 20, 30 ] }})");
* dom::parser parser;
* element doc = parser.parse(R"({ "foo": { "a": [ 10, 20, 30 ] }})");
* doc["/foo/a/1"] == 20
* doc["/"]["foo"]["a"].at(1) == 20
* doc[""]["foo"]["a"].at(1) == 20
@ -325,8 +334,8 @@ public:
/**
* Get the value associated with the given JSON pointer.
*
* document::parser parser;
* document::element doc = parser.parse(R"({ "foo": { "a": [ 10, 20, 30 ] }})");
* dom::parser parser;
* element doc = parser.parse(R"({ "foo": { "a": [ 10, 20, 30 ] }})");
* doc["/foo/a/1"] == 20
* doc["/"]["foo"]["a"].at(1) == 20
* doc[""]["foo"]["a"].at(1) == 20
@ -342,8 +351,8 @@ public:
/**
* Get the value associated with the given JSON pointer.
*
* document::parser parser;
* document::element doc = parser.parse(R"({ "foo": { "a": [ 10, 20, 30 ] }})");
* 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
@ -369,7 +378,7 @@ public:
*
* The key will be matched against **unescaped** JSON:
*
* document::parser parser;
* dom::parser parser;
* parser.parse(R"({ "a\n": 1 })")["a\n"].as_uint64_t().value == 1
* parser.parse(R"({ "a\n": 1 })")["a\\n"].as_uint64_t().error == NO_SUCH_FIELD
*
@ -392,9 +401,11 @@ public:
inline bool dump_raw_tape(std::ostream &out) const noexcept;
private:
really_inline element(const document *_doc, size_t _json_index) noexcept;
really_inline element(const document *doc, size_t json_index) noexcept;
friend class document;
friend struct simdjson_result<document::element>;
friend class object;
friend class array;
friend struct simdjson_result<element>;
template<typename T>
friend class simdjson::minify;
};
@ -402,12 +413,12 @@ private:
/**
* Represents a JSON array.
*/
class document::array : protected internal::tape_ref {
class array : protected internal::tape_ref {
public:
/** Create a new, invalid array */
really_inline array() noexcept;
class iterator : tape_ref {
class iterator : protected internal::tape_ref {
public:
/**
* Get the actual value
@ -426,7 +437,7 @@ public:
*/
inline bool operator!=(const iterator& other) const noexcept;
private:
really_inline iterator(const document *_doc, size_t _json_index) noexcept;
really_inline iterator(const document *doc, size_t json_index) noexcept;
friend class array;
};
@ -446,8 +457,8 @@ public:
/**
* Get the value associated with the given JSON pointer.
*
* document::parser parser;
* document::array a = parser.parse(R"([ { "foo": { "a": [ 10, 20, 30 ] }} ])");
* dom::parser parser;
* array a = parser.parse(R"([ { "foo": { "a": [ 10, 20, 30 ] }} ])");
* a["0/foo/a/1"] == 20
* a["0"]["foo"]["a"].at(1) == 20
*
@ -462,8 +473,8 @@ public:
/**
* Get the value associated with the given JSON pointer.
*
* document::parser parser;
* document::array a = parser.parse(R"([ { "foo": { "a": [ 10, 20, 30 ] }} ])");
* dom::parser parser;
* array a = parser.parse(R"([ { "foo": { "a": [ 10, 20, 30 ] }} ])");
* a["0/foo/a/1"] == 20
* a["0"]["foo"]["a"].at(1) == 20
*
@ -478,8 +489,8 @@ public:
/**
* Get the value associated with the given JSON pointer.
*
* document::parser parser;
* document::array a = parser.parse(R"([ { "foo": { "a": [ 10, 20, 30 ] }} ])");
* dom::parser parser;
* array a = parser.parse(R"([ { "foo": { "a": [ 10, 20, 30 ] }} ])");
* a.at("0/foo/a/1") == 20
* a.at("0")["foo"]["a"].at(1) == 20
*
@ -500,7 +511,7 @@ public:
inline simdjson_result<element> at(size_t index) const noexcept;
private:
really_inline array(const document *_doc, size_t _json_index) noexcept;
really_inline array(const document *doc, size_t json_index) noexcept;
friend class element;
friend struct simdjson_result<element>;
template<typename T>
@ -510,7 +521,7 @@ private:
/**
* Represents a JSON object.
*/
class document::object : protected internal::tape_ref {
class object : protected internal::tape_ref {
public:
/** Create a new, invalid object */
really_inline object() noexcept;
@ -520,7 +531,7 @@ public:
/**
* Get the actual key/value pair
*/
inline const document::key_value_pair operator*() const noexcept;
inline const key_value_pair operator*() const noexcept;
/**
* Get the next key/value pair.
*
@ -546,7 +557,7 @@ public:
*/
inline element value() const noexcept;
private:
really_inline iterator(const document *_doc, size_t _json_index) noexcept;
really_inline iterator(const document *doc, size_t json_index) noexcept;
friend class object;
};
@ -566,8 +577,8 @@ public:
/**
* Get the value associated with the given JSON pointer.
*
* document::parser parser;
* document::object obj = parser.parse(R"({ "foo": { "a": [ 10, 20, 30 ] }})");
* dom::parser parser;
* object obj = parser.parse(R"({ "foo": { "a": [ 10, 20, 30 ] }})");
* obj["foo/a/1"] == 20
* obj["foo"]["a"].at(1) == 20
*
@ -582,8 +593,8 @@ public:
/**
* Get the value associated with the given JSON pointer.
*
* document::parser parser;
* document::object obj = parser.parse(R"({ "foo": { "a": [ 10, 20, 30 ] }})");
* dom::parser parser;
* object obj = parser.parse(R"({ "foo": { "a": [ 10, 20, 30 ] }})");
* obj["foo/a/1"] == 20
* obj["foo"]["a"].at(1) == 20
*
@ -598,8 +609,8 @@ public:
/**
* Get the value associated with the given JSON pointer.
*
* document::parser parser;
* document::object obj = parser.parse(R"({ "foo": { "a": [ 10, 20, 30 ] }})");
* dom::parser parser;
* object obj = parser.parse(R"({ "foo": { "a": [ 10, 20, 30 ] }})");
* obj.at("foo/a/1") == 20
* obj.at("foo")["a"].at(1) == 20
*
@ -616,7 +627,7 @@ public:
*
* The key will be matched against **unescaped** JSON:
*
* document::parser parser;
* dom::parser parser;
* parser.parse(R"({ "a\n": 1 })")["a\n"].as_uint64_t().value == 1
* parser.parse(R"({ "a\n": 1 })")["a\\n"].as_uint64_t().error == NO_SUCH_FIELD
*
@ -636,7 +647,7 @@ public:
inline simdjson_result<element> at_key_case_insensitive(const std::string_view &key) const noexcept;
private:
really_inline object(const document *_doc, size_t _json_index) noexcept;
really_inline object(const document *doc, size_t json_index) noexcept;
friend class element;
friend struct simdjson_result<element>;
template<typename T>
@ -646,93 +657,16 @@ private:
/**
* Key/value pair in an object.
*/
class document::key_value_pair {
class key_value_pair {
public:
std::string_view key;
document::element value;
element value;
private:
really_inline key_value_pair(const std::string_view &_key, document::element _value) noexcept;
really_inline key_value_pair(const std::string_view &_key, element _value) noexcept;
friend class object;
};
/** The result of a JSON navigation that may fail. */
template<>
struct simdjson_result<document::element> : public internal::simdjson_result_base<document::element> {
public:
really_inline simdjson_result() noexcept;
really_inline simdjson_result(document::element &&value) noexcept;
really_inline simdjson_result(error_code error) noexcept;
/** Whether this is a JSON `null` */
inline simdjson_result<bool> is_null() const noexcept;
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 simdjson_result<document::array> as_array() const noexcept;
inline simdjson_result<document::object> as_object() const noexcept;
inline simdjson_result<document::element> operator[](const std::string_view &json_pointer) const noexcept;
inline simdjson_result<document::element> operator[](const char *json_pointer) const noexcept;
inline simdjson_result<document::element> at(const std::string_view &json_pointer) const noexcept;
inline simdjson_result<document::element> at(size_t index) const noexcept;
inline simdjson_result<document::element> at_key(const std::string_view &key) const noexcept;
inline simdjson_result<document::element> at_key_case_insensitive(const std::string_view &key) const noexcept;
#if SIMDJSON_EXCEPTIONS
inline operator bool() const noexcept(false);
inline explicit operator const char*() const noexcept(false);
inline operator std::string_view() const noexcept(false);
inline operator uint64_t() const noexcept(false);
inline operator int64_t() const noexcept(false);
inline operator double() const noexcept(false);
inline operator document::array() const noexcept(false);
inline operator document::object() const noexcept(false);
#endif // SIMDJSON_EXCEPTIONS
};
/** The result of a JSON conversion that may fail. */
template<>
struct simdjson_result<document::array> : public internal::simdjson_result_base<document::array> {
public:
really_inline simdjson_result() noexcept;
really_inline simdjson_result(document::array value) noexcept;
really_inline simdjson_result(error_code error) noexcept;
inline simdjson_result<document::element> operator[](const std::string_view &json_pointer) const noexcept;
inline simdjson_result<document::element> operator[](const char *json_pointer) const noexcept;
inline simdjson_result<document::element> at(const std::string_view &json_pointer) const noexcept;
inline simdjson_result<document::element> at(size_t index) const noexcept;
#if SIMDJSON_EXCEPTIONS
inline document::array::iterator begin() const noexcept(false);
inline document::array::iterator end() const noexcept(false);
#endif // SIMDJSON_EXCEPTIONS
};
/** The result of a JSON conversion that may fail. */
template<>
struct simdjson_result<document::object> : public internal::simdjson_result_base<document::object> {
public:
really_inline simdjson_result() noexcept;
really_inline simdjson_result(document::object value) noexcept;
really_inline simdjson_result(error_code error) noexcept;
inline simdjson_result<document::element> operator[](const std::string_view &json_pointer) const noexcept;
inline simdjson_result<document::element> operator[](const char *json_pointer) const noexcept;
inline simdjson_result<document::element> at(const std::string_view &json_pointer) const noexcept;
inline simdjson_result<document::element> at_key(const std::string_view &key) const noexcept;
inline simdjson_result<document::element> at_key_case_insensitive(const std::string_view &key) const noexcept;
#if SIMDJSON_EXCEPTIONS
inline document::object::iterator begin() const noexcept(false);
inline document::object::iterator end() const noexcept(false);
#endif // SIMDJSON_EXCEPTIONS
};
/**
* A persistent document parser.
*
@ -743,7 +677,7 @@ public:
*
* @note This is not thread safe: one parser cannot produce two documents at the same time!
*/
class document::parser {
class parser {
public:
/**
* Create a JSON parser.
@ -767,21 +701,21 @@ public:
*
* @param other The parser to take. Its capacity is zeroed.
*/
parser(document::parser &&other) = default;
parser(const document::parser &) = delete; // Disallow copying
parser(parser &&other) = default;
parser(const parser &) = delete; // Disallow copying
/**
* Take another parser's buffers and state.
*
* @param other The parser to take. Its capacity is zeroed.
*/
parser &operator=(document::parser &&other) = default;
parser &operator=(const document::parser &) = delete; // Disallow copying
parser &operator=(parser &&other) = default;
parser &operator=(const parser &) = delete; // Disallow copying
/**
* Load a JSON document from a file and return a reference to it.
*
* document::parser parser;
* const document::element doc = parser.load("jsonexamples/twitter.json");
* dom::parser parser;
* const element doc = parser.load("jsonexamples/twitter.json");
*
* ### IMPORTANT: Document Lifetime
*
@ -806,8 +740,8 @@ public:
/**
* Load a file containing many JSON documents.
*
* document::parser parser;
* for (const document::element doc : parser.parse_many(path)) {
* dom::parser parser;
* for (const element doc : parser.parse_many(path)) {
* cout << std::string(doc["title"]) << endl;
* }
*
@ -830,7 +764,7 @@ public:
* As with all other simdjson methods, non-exception error handling is readily available through
* the same interface, requiring you to check the error before using the document:
*
* document::parser parser;
* dom::parser parser;
* for (auto [doc, error] : parser.load_many(path)) {
* if (error) { cerr << error << endl; exit(1); }
* cout << std::string(doc["title"]) << endl;
@ -858,13 +792,13 @@ public:
* - CAPACITY if the parser does not have enough capacity and batch_size > max_capacity.
* - other json errors if parsing fails.
*/
inline document::stream load_many(const std::string &path, size_t batch_size = DEFAULT_BATCH_SIZE) noexcept;
inline stream load_many(const std::string &path, size_t batch_size = DEFAULT_BATCH_SIZE) noexcept;
/**
* Parse a JSON document and return a temporary reference to it.
*
* document::parser parser;
* document::element doc = parser.parse(buf, len);
* dom::parser parser;
* element doc = parser.parse(buf, len);
*
* ### IMPORTANT: Document Lifetime
*
@ -900,8 +834,8 @@ public:
/**
* Parse a JSON document and return a temporary reference to it.
*
* document::parser parser;
* const document::element doc = parser.parse(buf, len);
* dom::parser parser;
* const element doc = parser.parse(buf, len);
*
* ### IMPORTANT: Document Lifetime
*
@ -937,8 +871,8 @@ public:
/**
* Parse a JSON document and return a temporary reference to it.
*
* document::parser parser;
* const document::element doc = parser.parse(s);
* dom::parser parser;
* const element doc = parser.parse(s);
*
* ### IMPORTANT: Document Lifetime
*
@ -972,8 +906,8 @@ public:
/**
* Parse a JSON document and return a temporary reference to it.
*
* document::parser parser;
* const document::element doc = parser.parse(s);
* dom::parser parser;
* const element doc = parser.parse(s);
*
* ### IMPORTANT: Document Lifetime
*
@ -1000,8 +934,8 @@ public:
/**
* Parse a buffer containing many JSON documents.
*
* document::parser parser;
* for (const document::element doc : parser.parse_many(buf, len)) {
* dom::parser parser;
* for (const element doc : parser.parse_many(buf, len)) {
* cout << std::string(doc["title"]) << endl;
* }
*
@ -1024,7 +958,7 @@ public:
* As with all other simdjson methods, non-exception error handling is readily available through
* the same interface, requiring you to check the error before using the document:
*
* document::parser parser;
* dom::parser parser;
* for (auto [doc, error] : parser.parse_many(buf, len)) {
* if (error) { cerr << error << endl; exit(1); }
* cout << std::string(doc["title"]) << endl;
@ -1062,8 +996,8 @@ public:
/**
* Parse a buffer containing many JSON documents.
*
* document::parser parser;
* for (const document::element doc : parser.parse_many(buf, len)) {
* dom::parser parser;
* for (const element doc : parser.parse_many(buf, len)) {
* cout << std::string(doc["title"]) << endl;
* }
*
@ -1086,7 +1020,7 @@ public:
* As with all other simdjson methods, non-exception error handling is readily available through
* the same interface, requiring you to check the error before using the document:
*
* document::parser parser;
* dom::parser parser;
* for (auto [doc, error] : parser.parse_many(buf, len)) {
* if (error) { cerr << error << endl; exit(1); }
* cout << std::string(doc["title"]) << endl;
@ -1124,8 +1058,8 @@ public:
/**
* Parse a buffer containing many JSON documents.
*
* document::parser parser;
* for (const document::element doc : parser.parse_many(buf, len)) {
* dom::parser parser;
* for (const element doc : parser.parse_many(buf, len)) {
* cout << std::string(doc["title"]) << endl;
* }
*
@ -1148,7 +1082,7 @@ public:
* As with all other simdjson methods, non-exception error handling is readily available through
* the same interface, requiring you to check the error before using the document:
*
* document::parser parser;
* dom::parser parser;
* for (auto [doc, error] : parser.parse_many(buf, len)) {
* if (error) { cerr << error << endl; exit(1); }
* cout << std::string(doc["title"]) << endl;
@ -1185,8 +1119,8 @@ public:
/**
* Parse a buffer containing many JSON documents.
*
* document::parser parser;
* for (const document::element doc : parser.parse_many(buf, len)) {
* dom::parser parser;
* for (const element doc : parser.parse_many(buf, len)) {
* cout << std::string(doc["title"]) << endl;
* }
*
@ -1209,7 +1143,7 @@ public:
* As with all other simdjson methods, non-exception error handling is readily available through
* the same interface, requiring you to check the error before using the document:
*
* document::parser parser;
* dom::parser parser;
* for (auto [doc, error] : parser.parse_many(buf, len)) {
* if (error) { cerr << error << endl; exit(1); }
* cout << std::string(doc["title"]) << endl;
@ -1449,11 +1383,15 @@ private:
friend class stream;
}; // class parser
} // namespace simdjson::dom
namespace simdjson {
/**
* Minifies a JSON element or document, printing the smallest possible valid JSON.
*
* document::parser parser;
* document::element doc = parser.parse(" [ 1 , 2 , 3 ] "_padded);
* dom::parser parser;
* element doc = parser.parse(" [ 1 , 2 , 3 ] "_padded);
* cout << minify(doc) << endl; // prints [1,2,3]
*
*/
@ -1490,6 +1428,11 @@ private:
template<typename T>
inline std::ostream& operator<<(std::ostream& out, minify<T> formatter) { return formatter.print(out); }
namespace dom {
// << operators need to be in the same namespace as the class being output, so C++ can find them
// automatically
/**
* Print JSON to an output stream.
*
@ -1499,7 +1442,7 @@ inline std::ostream& operator<<(std::ostream& out, minify<T> formatter) { return
* @param value The value to print.
* @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::element &value) { return out << minify(value); };
inline std::ostream& operator<<(std::ostream& out, const element &value) { return out << minify(value); };
/**
* Print JSON to an output stream.
*
@ -1509,7 +1452,7 @@ inline std::ostream& operator<<(std::ostream& out, const document::element &valu
* @param value The value to print.
* @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::array &value) { return out << minify(value); }
inline std::ostream& operator<<(std::ostream& out, const array &value) { return out << minify(value); }
/**
* Print JSON to an output stream.
*
@ -1519,7 +1462,7 @@ inline std::ostream& operator<<(std::ostream& out, const document::array &value)
* @param value The value to print.
* @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::object &value) { return out << minify(value); }
inline std::ostream& operator<<(std::ostream& out, const object &value) { return out << minify(value); }
/**
* Print JSON to an output stream.
*
@ -1529,7 +1472,9 @@ inline std::ostream& operator<<(std::ostream& out, const document::object &value
* @param value The value to print.
* @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); }
inline std::ostream& operator<<(std::ostream& out, const key_value_pair &value) { return out << minify(value); }
} // namespace dom
#if SIMDJSON_EXCEPTIONS
@ -1544,7 +1489,7 @@ inline std::ostream& operator<<(std::ostream& out, const document::key_value_pai
* underlying output stream, that error will be propagated (simdjson_error will not be
* thrown).
*/
inline std::ostream& operator<<(std::ostream& out, const simdjson_result<document::element> &value) noexcept(false) { return out << minify(value); }
inline std::ostream& operator<<(std::ostream& out, const simdjson_result<dom::element> &value) noexcept(false) { return out << minify(value); }
/**
* Print JSON to an output stream.
*
@ -1556,7 +1501,7 @@ inline std::ostream& operator<<(std::ostream& out, const simdjson_result<documen
* underlying output stream, that error will be propagated (simdjson_error will not be
* thrown).
*/
inline std::ostream& operator<<(std::ostream& out, const simdjson_result<document::array> &value) noexcept(false) { return out << minify(value); }
inline std::ostream& operator<<(std::ostream& out, const simdjson_result<dom::array> &value) noexcept(false) { return out << minify(value); }
/**
* Print JSON to an output stream.
*
@ -1568,10 +1513,87 @@ inline std::ostream& operator<<(std::ostream& out, const simdjson_result<documen
* underlying output stream, that error will be propagated (simdjson_error will not be
* thrown).
*/
inline std::ostream& operator<<(std::ostream& out, const simdjson_result<document::object> &value) noexcept(false) { return out << minify(value); }
inline std::ostream& operator<<(std::ostream& out, const simdjson_result<dom::object> &value) noexcept(false) { return out << minify(value); }
#endif
/** The result of a JSON navigation that may fail. */
template<>
struct simdjson_result<dom::element> : public internal::simdjson_result_base<dom::element> {
public:
really_inline simdjson_result() noexcept;
really_inline simdjson_result(dom::element &&value) noexcept;
really_inline simdjson_result(error_code error) noexcept;
/** Whether this is a JSON `null` */
inline simdjson_result<bool> is_null() const noexcept;
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 simdjson_result<dom::array> as_array() const noexcept;
inline simdjson_result<dom::object> as_object() const noexcept;
inline simdjson_result<dom::element> operator[](const std::string_view &json_pointer) const noexcept;
inline simdjson_result<dom::element> operator[](const char *json_pointer) const noexcept;
inline simdjson_result<dom::element> at(const std::string_view &json_pointer) const noexcept;
inline simdjson_result<dom::element> at(size_t index) const noexcept;
inline simdjson_result<dom::element> at_key(const std::string_view &key) const noexcept;
inline simdjson_result<dom::element> at_key_case_insensitive(const std::string_view &key) const noexcept;
#if SIMDJSON_EXCEPTIONS
inline operator bool() const noexcept(false);
inline explicit operator const char*() const noexcept(false);
inline operator std::string_view() const noexcept(false);
inline operator uint64_t() const noexcept(false);
inline operator int64_t() const noexcept(false);
inline operator double() const noexcept(false);
inline operator dom::array() const noexcept(false);
inline operator dom::object() const noexcept(false);
#endif // SIMDJSON_EXCEPTIONS
};
/** The result of a JSON conversion that may fail. */
template<>
struct simdjson_result<dom::array> : public internal::simdjson_result_base<dom::array> {
public:
really_inline simdjson_result() noexcept;
really_inline simdjson_result(dom::array value) noexcept;
really_inline simdjson_result(error_code error) noexcept;
inline simdjson_result<dom::element> operator[](const std::string_view &json_pointer) const noexcept;
inline simdjson_result<dom::element> operator[](const char *json_pointer) const noexcept;
inline simdjson_result<dom::element> at(const std::string_view &json_pointer) const noexcept;
inline simdjson_result<dom::element> at(size_t index) const noexcept;
#if SIMDJSON_EXCEPTIONS
inline dom::array::iterator begin() const noexcept(false);
inline dom::array::iterator end() const noexcept(false);
#endif // SIMDJSON_EXCEPTIONS
};
/** The result of a JSON conversion that may fail. */
template<>
struct simdjson_result<dom::object> : public internal::simdjson_result_base<dom::object> {
public:
really_inline simdjson_result() noexcept;
really_inline simdjson_result(dom::object value) noexcept;
really_inline simdjson_result(error_code error) noexcept;
inline simdjson_result<dom::element> operator[](const std::string_view &json_pointer) const noexcept;
inline simdjson_result<dom::element> operator[](const char *json_pointer) const noexcept;
inline simdjson_result<dom::element> at(const std::string_view &json_pointer) const noexcept;
inline simdjson_result<dom::element> at_key(const std::string_view &key) const noexcept;
inline simdjson_result<dom::element> at_key_case_insensitive(const std::string_view &key) const noexcept;
#if SIMDJSON_EXCEPTIONS
inline dom::object::iterator begin() const noexcept(false);
inline dom::object::iterator end() const noexcept(false);
#endif // SIMDJSON_EXCEPTIONS
};
} // namespace simdjson
#endif // SIMDJSON_DOCUMENT_H

View File

@ -4,15 +4,15 @@
#include <thread>
#include "simdjson/document.h"
namespace simdjson {
namespace simdjson::dom {
/**
* A forward-only stream of documents.
*
* Produced by document::parser::parse_many.
* Produced by parser::parse_many.
*
*/
class document::stream {
class stream {
public:
really_inline ~stream() noexcept;
@ -55,11 +55,11 @@ public:
private:
stream &operator=(const document::stream &) = delete; // Disallow copying
stream &operator=(const stream &) = delete; // Disallow copying
stream(document::stream &other) = delete; // Disallow copying
stream(stream &other) = delete; // Disallow copying
really_inline stream(document::parser &parser, const uint8_t *buf, size_t len, size_t batch_size, error_code error = SUCCESS) noexcept;
really_inline stream(dom::parser &parser, const uint8_t *buf, size_t len, size_t batch_size, error_code error = SUCCESS) noexcept;
/**
* Parse the next document found in the buffer previously given to stream.
@ -116,7 +116,7 @@ private:
inline size_t remaining() const { return _len - buf_start; }
document::parser &parser;
dom::parser &parser;
const uint8_t *_buf;
const size_t _len;
size_t _batch_size; // this is actually variable!
@ -133,10 +133,11 @@ private:
#ifdef SIMDJSON_THREADS_ENABLED
error_code stage1_is_ok_thread{SUCCESS};
std::thread stage_1_thread;
document::parser parser_thread;
dom::parser parser_thread;
#endif
friend class document::parser;
}; // class document::stream
friend class dom::parser;
}; // class stream
} // end of namespace simdjson::dom
} // end of namespace simdjson
#endif // SIMDJSON_DOCUMENT_STREAM_H

View File

@ -43,7 +43,7 @@ enum error_code {
/**
* Get the error message for the given error code.
*
* document::parser parser;
* dom::parser parser;
* auto [doc, error] = parser.parse("foo");
* if (error) { printf("Error: %s\n", error_message(error)); }
*

View File

@ -54,7 +54,7 @@ public:
* @param parser the parser with the buffers to use. *MUST* have allocated up to at least len capacity.
* @return the error code, or SUCCESS if there was no error.
*/
WARN_UNUSED virtual error_code parse(const uint8_t *buf, size_t len, document::parser &parser) const noexcept = 0;
WARN_UNUSED virtual error_code parse(const uint8_t *buf, size_t len, dom::parser &parser) const noexcept = 0;
/**
* Run a full document parse (ensure_capacity, stage1 and stage2).
@ -77,10 +77,10 @@ public:
* @param buf the json document to parse. *MUST* be allocated up to len + SIMDJSON_PADDING bytes.
* @param len the length of the json document.
* @param parser the parser with the buffers to use. *MUST* have allocated up to at least len capacity.
* @param streaming whether this is being called by document::parser::parse_many.
* @param streaming whether this is being called by parser::parse_many.
* @return the error code, or SUCCESS if there was no error.
*/
WARN_UNUSED virtual error_code stage1(const uint8_t *buf, size_t len, document::parser &parser, bool streaming) const noexcept = 0;
WARN_UNUSED virtual error_code stage1(const uint8_t *buf, size_t len, dom::parser &parser, bool streaming) const noexcept = 0;
/**
* Stage 2 of the document parser.
@ -92,10 +92,10 @@ public:
* @param parser the parser with the buffers to use. *MUST* have allocated up to at least len capacity.
* @return the error code, or SUCCESS if there was no error.
*/
WARN_UNUSED virtual error_code stage2(const uint8_t *buf, size_t len, document::parser &parser) const noexcept = 0;
WARN_UNUSED virtual error_code stage2(const uint8_t *buf, size_t len, dom::parser &parser) const noexcept = 0;
/**
* Stage 2 of the document parser for document::parser::parse_many.
* Stage 2 of the document parser for parser::parse_many.
*
* Overridden by each implementation.
*
@ -105,7 +105,7 @@ public:
* @param next_json the next structural index. Start this at 0 the first time, and it will be updated to the next value to pass each time.
* @return the error code, SUCCESS if there was no error, or SUCCESS_AND_HAS_MORE if there was no error and stage2 can be called again.
*/
WARN_UNUSED virtual error_code stage2(const uint8_t *buf, size_t len, document::parser &parser, size_t &next_json) const noexcept = 0;
WARN_UNUSED virtual error_code stage2(const uint8_t *buf, size_t len, dom::parser &parser, size_t &next_json) const noexcept = 0;
protected:
really_inline implementation(
@ -192,19 +192,19 @@ public:
const std::string& name() const noexcept final { return set_best()->name(); }
const std::string& description() const noexcept final { return set_best()->description(); }
uint32_t required_instruction_sets() const noexcept final { return set_best()->required_instruction_sets(); }
WARN_UNUSED error_code parse(const uint8_t *buf, size_t len, document::parser &parser) const noexcept final {
WARN_UNUSED error_code parse(const uint8_t *buf, size_t len, dom::parser &parser) const noexcept final {
return set_best()->parse(buf, len, parser);
}
WARN_UNUSED error_code minify(const uint8_t *buf, size_t len, uint8_t *dst, size_t &dst_len) const noexcept final {
return set_best()->minify(buf, len, dst, dst_len);
}
WARN_UNUSED error_code stage1(const uint8_t *buf, size_t len, document::parser &parser, bool streaming) const noexcept final {
WARN_UNUSED error_code stage1(const uint8_t *buf, size_t len, dom::parser &parser, bool streaming) const noexcept final {
return set_best()->stage1(buf, len, parser, streaming);
}
WARN_UNUSED error_code stage2(const uint8_t *buf, size_t len, document::parser &parser) const noexcept final {
WARN_UNUSED error_code stage2(const uint8_t *buf, size_t len, dom::parser &parser) const noexcept final {
return set_best()->stage2(buf, len, parser);
}
WARN_UNUSED error_code stage2(const uint8_t *buf, size_t len, document::parser &parser, size_t &next_json) const noexcept final {
WARN_UNUSED error_code stage2(const uint8_t *buf, size_t len, dom::parser &parser, size_t &next_json) const noexcept final {
return set_best()->stage2(buf, len, parser, next_json);
}

View File

@ -15,193 +15,197 @@
namespace simdjson {
//
// simdjson_result<document::element> inline implementation
// simdjson_result<dom::element> inline implementation
//
really_inline simdjson_result<document::element>::simdjson_result() noexcept
: internal::simdjson_result_base<document::element>() {}
really_inline simdjson_result<document::element>::simdjson_result(document::element &&value) noexcept
: internal::simdjson_result_base<document::element>(std::forward<document::element>(value)) {}
really_inline simdjson_result<document::element>::simdjson_result(error_code error) noexcept
: internal::simdjson_result_base<document::element>(error) {}
inline simdjson_result<bool> simdjson_result<document::element>::is_null() const noexcept {
really_inline simdjson_result<dom::element>::simdjson_result() noexcept
: internal::simdjson_result_base<dom::element>() {}
really_inline simdjson_result<dom::element>::simdjson_result(dom::element &&value) noexcept
: internal::simdjson_result_base<dom::element>(std::forward<dom::element>(value)) {}
really_inline simdjson_result<dom::element>::simdjson_result(error_code error) noexcept
: internal::simdjson_result_base<dom::element>(error) {}
inline simdjson_result<bool> simdjson_result<dom::element>::is_null() const noexcept {
if (error()) { return error(); }
return first.is_null();
}
inline simdjson_result<bool> simdjson_result<document::element>::as_bool() const noexcept {
inline simdjson_result<bool> simdjson_result<dom::element>::as_bool() const noexcept {
if (error()) { return error(); }
return first.as_bool();
}
inline simdjson_result<const char*> simdjson_result<document::element>::as_c_str() const noexcept {
inline simdjson_result<const char*> simdjson_result<dom::element>::as_c_str() const noexcept {
if (error()) { return error(); }
return first.as_c_str();
}
inline simdjson_result<std::string_view> simdjson_result<document::element>::as_string() const noexcept {
inline simdjson_result<std::string_view> simdjson_result<dom::element>::as_string() const noexcept {
if (error()) { return error(); }
return first.as_string();
}
inline simdjson_result<uint64_t> simdjson_result<document::element>::as_uint64_t() const noexcept {
inline simdjson_result<uint64_t> simdjson_result<dom::element>::as_uint64_t() const noexcept {
if (error()) { return error(); }
return first.as_uint64_t();
}
inline simdjson_result<int64_t> simdjson_result<document::element>::as_int64_t() const noexcept {
inline simdjson_result<int64_t> simdjson_result<dom::element>::as_int64_t() const noexcept {
if (error()) { return error(); }
return first.as_int64_t();
}
inline simdjson_result<double> simdjson_result<document::element>::as_double() const noexcept {
inline simdjson_result<double> simdjson_result<dom::element>::as_double() const noexcept {
if (error()) { return error(); }
return first.as_double();
}
inline simdjson_result<document::array> simdjson_result<document::element>::as_array() const noexcept {
inline simdjson_result<dom::array> simdjson_result<dom::element>::as_array() const noexcept {
if (error()) { return error(); }
return first.as_array();
}
inline simdjson_result<document::object> simdjson_result<document::element>::as_object() const noexcept {
inline simdjson_result<dom::object> simdjson_result<dom::element>::as_object() const noexcept {
if (error()) { return error(); }
return first.as_object();
}
inline simdjson_result<document::element> simdjson_result<document::element>::operator[](const std::string_view &json_pointer) const noexcept {
inline simdjson_result<dom::element> simdjson_result<dom::element>::operator[](const std::string_view &json_pointer) const noexcept {
if (error()) { return *this; }
return first[json_pointer];
}
inline simdjson_result<document::element> simdjson_result<document::element>::operator[](const char *json_pointer) const noexcept {
inline simdjson_result<dom::element> simdjson_result<dom::element>::operator[](const char *json_pointer) const noexcept {
if (error()) { return *this; }
return first[json_pointer];
}
inline simdjson_result<document::element> simdjson_result<document::element>::at(const std::string_view &json_pointer) const noexcept {
inline simdjson_result<dom::element> simdjson_result<dom::element>::at(const std::string_view &json_pointer) const noexcept {
if (error()) { return *this; }
return first.at(json_pointer);
}
inline simdjson_result<document::element> simdjson_result<document::element>::at(size_t index) const noexcept {
inline simdjson_result<dom::element> simdjson_result<dom::element>::at(size_t index) const noexcept {
if (error()) { return *this; }
return first.at(index);
}
inline simdjson_result<document::element> simdjson_result<document::element>::at_key(const std::string_view &key) const noexcept {
inline simdjson_result<dom::element> simdjson_result<dom::element>::at_key(const std::string_view &key) const noexcept {
if (error()) { return *this; }
return first.at_key(key);
}
inline simdjson_result<document::element> simdjson_result<document::element>::at_key_case_insensitive(const std::string_view &key) const noexcept {
inline simdjson_result<dom::element> simdjson_result<dom::element>::at_key_case_insensitive(const std::string_view &key) const noexcept {
if (error()) { return *this; }
return first.at_key_case_insensitive(key);
}
#if SIMDJSON_EXCEPTIONS
inline simdjson_result<document::element>::operator bool() const noexcept(false) {
inline simdjson_result<dom::element>::operator bool() const noexcept(false) {
return as_bool();
}
inline simdjson_result<document::element>::operator const char *() const noexcept(false) {
inline simdjson_result<dom::element>::operator const char *() const noexcept(false) {
return as_c_str();
}
inline simdjson_result<document::element>::operator std::string_view() const noexcept(false) {
inline simdjson_result<dom::element>::operator std::string_view() const noexcept(false) {
return as_string();
}
inline simdjson_result<document::element>::operator uint64_t() const noexcept(false) {
inline simdjson_result<dom::element>::operator uint64_t() const noexcept(false) {
return as_uint64_t();
}
inline simdjson_result<document::element>::operator int64_t() const noexcept(false) {
inline simdjson_result<dom::element>::operator int64_t() const noexcept(false) {
return as_int64_t();
}
inline simdjson_result<document::element>::operator double() const noexcept(false) {
inline simdjson_result<dom::element>::operator double() const noexcept(false) {
return as_double();
}
inline simdjson_result<document::element>::operator document::array() const noexcept(false) {
inline simdjson_result<dom::element>::operator dom::array() const noexcept(false) {
return as_array();
}
inline simdjson_result<document::element>::operator document::object() const noexcept(false) {
inline simdjson_result<dom::element>::operator dom::object() const noexcept(false) {
return as_object();
}
#endif
//
// simdjson_result<document::array> inline implementation
// simdjson_result<dom::array> inline implementation
//
really_inline simdjson_result<document::array>::simdjson_result() noexcept
: internal::simdjson_result_base<document::array>() {}
really_inline simdjson_result<document::array>::simdjson_result(document::array value) noexcept
: internal::simdjson_result_base<document::array>(std::forward<document::array>(value)) {}
really_inline simdjson_result<document::array>::simdjson_result(error_code error) noexcept
: internal::simdjson_result_base<document::array>(error) {}
really_inline simdjson_result<dom::array>::simdjson_result() noexcept
: internal::simdjson_result_base<dom::array>() {}
really_inline simdjson_result<dom::array>::simdjson_result(dom::array value) noexcept
: internal::simdjson_result_base<dom::array>(std::forward<dom::array>(value)) {}
really_inline simdjson_result<dom::array>::simdjson_result(error_code error) noexcept
: internal::simdjson_result_base<dom::array>(error) {}
#if SIMDJSON_EXCEPTIONS
inline document::array::iterator simdjson_result<document::array>::begin() const noexcept(false) {
inline dom::array::iterator simdjson_result<dom::array>::begin() const noexcept(false) {
if (error()) { throw simdjson_error(error()); }
return first.begin();
}
inline document::array::iterator simdjson_result<document::array>::end() const noexcept(false) {
inline dom::array::iterator simdjson_result<dom::array>::end() const noexcept(false) {
if (error()) { throw simdjson_error(error()); }
return first.end();
}
#endif // SIMDJSON_EXCEPTIONS
inline simdjson_result<document::element> simdjson_result<document::array>::operator[](const std::string_view &json_pointer) const noexcept {
inline simdjson_result<dom::element> simdjson_result<dom::array>::operator[](const std::string_view &json_pointer) const noexcept {
if (error()) { return error(); }
return first.at(json_pointer);
}
inline simdjson_result<document::element> simdjson_result<document::array>::operator[](const char *json_pointer) const noexcept {
inline simdjson_result<dom::element> simdjson_result<dom::array>::operator[](const char *json_pointer) const noexcept {
if (error()) { return error(); }
return first.at(json_pointer);
}
inline simdjson_result<document::element> simdjson_result<document::array>::at(const std::string_view &json_pointer) const noexcept {
inline simdjson_result<dom::element> simdjson_result<dom::array>::at(const std::string_view &json_pointer) const noexcept {
if (error()) { return error(); }
return first.at(json_pointer);
}
inline simdjson_result<document::element> simdjson_result<document::array>::at(size_t index) const noexcept {
inline simdjson_result<dom::element> simdjson_result<dom::array>::at(size_t index) const noexcept {
if (error()) { return error(); }
return first.at(index);
}
//
// simdjson_result<document::object> inline implementation
// simdjson_result<dom::object> inline implementation
//
really_inline simdjson_result<document::object>::simdjson_result() noexcept
: internal::simdjson_result_base<document::object>() {}
really_inline simdjson_result<document::object>::simdjson_result(document::object value) noexcept
: internal::simdjson_result_base<document::object>(std::forward<document::object>(value)) {}
really_inline simdjson_result<document::object>::simdjson_result(error_code error) noexcept
: internal::simdjson_result_base<document::object>(error) {}
really_inline simdjson_result<dom::object>::simdjson_result() noexcept
: internal::simdjson_result_base<dom::object>() {}
really_inline simdjson_result<dom::object>::simdjson_result(dom::object value) noexcept
: internal::simdjson_result_base<dom::object>(std::forward<dom::object>(value)) {}
really_inline simdjson_result<dom::object>::simdjson_result(error_code error) noexcept
: internal::simdjson_result_base<dom::object>(error) {}
inline simdjson_result<document::element> simdjson_result<document::object>::operator[](const std::string_view &json_pointer) const noexcept {
inline simdjson_result<dom::element> simdjson_result<dom::object>::operator[](const std::string_view &json_pointer) const noexcept {
if (error()) { return error(); }
return first[json_pointer];
}
inline simdjson_result<document::element> simdjson_result<document::object>::operator[](const char *json_pointer) const noexcept {
inline simdjson_result<dom::element> simdjson_result<dom::object>::operator[](const char *json_pointer) const noexcept {
if (error()) { return error(); }
return first[json_pointer];
}
inline simdjson_result<document::element> simdjson_result<document::object>::at(const std::string_view &json_pointer) const noexcept {
inline simdjson_result<dom::element> simdjson_result<dom::object>::at(const std::string_view &json_pointer) const noexcept {
if (error()) { return error(); }
return first.at(json_pointer);
}
inline simdjson_result<document::element> simdjson_result<document::object>::at_key(const std::string_view &key) const noexcept {
inline simdjson_result<dom::element> simdjson_result<dom::object>::at_key(const std::string_view &key) const noexcept {
if (error()) { return error(); }
return first.at_key(key);
}
inline simdjson_result<document::element> simdjson_result<document::object>::at_key_case_insensitive(const std::string_view &key) const noexcept {
inline simdjson_result<dom::element> simdjson_result<dom::object>::at_key_case_insensitive(const std::string_view &key) const noexcept {
if (error()) { return error(); }
return first.at_key_case_insensitive(key);
}
#if SIMDJSON_EXCEPTIONS
inline document::object::iterator simdjson_result<document::object>::begin() const noexcept(false) {
inline dom::object::iterator simdjson_result<dom::object>::begin() const noexcept(false) {
if (error()) { throw simdjson_error(error()); }
return first.begin();
}
inline document::object::iterator simdjson_result<document::object>::end() const noexcept(false) {
inline dom::object::iterator simdjson_result<dom::object>::end() const noexcept(false) {
if (error()) { throw simdjson_error(error()); }
return first.end();
}
#endif // SIMDJSON_EXCEPTIONS
} // namespace simdjson
namespace simdjson::dom {
//
// document inline implementation
//
inline document::element document::root() const noexcept {
inline element document::root() const noexcept {
return element(this, 1);
}
@ -325,23 +329,23 @@ inline bool document::dump_raw_tape(std::ostream &os) const noexcept {
}
//
// document::parser inline implementation
// parser inline implementation
//
really_inline document::parser::parser(size_t max_capacity, size_t max_depth) noexcept
really_inline parser::parser(size_t max_capacity, size_t max_depth) noexcept
: _max_capacity{max_capacity}, _max_depth{max_depth}, loaded_bytes(nullptr, &aligned_free_char) {}
inline bool document::parser::is_valid() const noexcept { return valid; }
inline int document::parser::get_error_code() const noexcept { return error; }
inline std::string document::parser::get_error_message() const noexcept { return error_message(int(error)); }
inline bool document::parser::print_json(std::ostream &os) const noexcept {
inline bool parser::is_valid() const noexcept { return valid; }
inline int parser::get_error_code() const noexcept { return error; }
inline std::string parser::get_error_message() const noexcept { return error_message(int(error)); }
inline bool parser::print_json(std::ostream &os) const noexcept {
if (!valid) { return false; }
os << doc.root();
return true;
}
inline bool document::parser::dump_raw_tape(std::ostream &os) const noexcept {
inline bool parser::dump_raw_tape(std::ostream &os) const noexcept {
return valid ? doc.dump_raw_tape(os) : false;
}
inline simdjson_result<size_t> document::parser::read_file(const std::string &path) noexcept {
inline simdjson_result<size_t> parser::read_file(const std::string &path) noexcept {
// Open the file
std::FILE *fp = std::fopen(path.c_str(), "rb");
if (fp == nullptr) {
@ -379,19 +383,19 @@ inline simdjson_result<size_t> document::parser::read_file(const std::string &pa
return bytes_read;
}
inline simdjson_result<document::element> document::parser::load(const std::string &path) noexcept {
inline simdjson_result<element> parser::load(const std::string &path) noexcept {
auto [len, code] = read_file(path);
if (code) { return code; }
return parse(loaded_bytes.get(), len, false);
}
inline document::stream document::parser::load_many(const std::string &path, size_t batch_size) noexcept {
inline stream parser::load_many(const std::string &path, size_t batch_size) noexcept {
auto [len, code] = read_file(path);
return stream(*this, (const uint8_t*)loaded_bytes.get(), len, batch_size, code);
}
inline simdjson_result<document::element> document::parser::parse(const uint8_t *buf, size_t len, bool realloc_if_needed) noexcept {
inline simdjson_result<element> parser::parse(const uint8_t *buf, size_t len, bool realloc_if_needed) noexcept {
error_code code = ensure_capacity(len);
if (code) { return code; }
@ -414,41 +418,41 @@ inline simdjson_result<document::element> document::parser::parse(const uint8_t
error = UNINITIALIZED;
return doc.root();
}
really_inline simdjson_result<document::element> document::parser::parse(const char *buf, size_t len, bool realloc_if_needed) noexcept {
really_inline simdjson_result<element> 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 simdjson_result<document::element> document::parser::parse(const std::string &s) noexcept {
really_inline simdjson_result<element> parser::parse(const std::string &s) noexcept {
return parse(s.data(), s.length(), s.capacity() - s.length() < SIMDJSON_PADDING);
}
really_inline simdjson_result<document::element> document::parser::parse(const padded_string &s) noexcept {
really_inline simdjson_result<element> parser::parse(const padded_string &s) noexcept {
return parse(s.data(), s.length(), false);
}
inline document::stream document::parser::parse_many(const uint8_t *buf, size_t len, size_t batch_size) noexcept {
inline stream parser::parse_many(const uint8_t *buf, size_t len, size_t batch_size) noexcept {
return stream(*this, buf, len, batch_size);
}
inline document::stream document::parser::parse_many(const char *buf, size_t len, size_t batch_size) noexcept {
inline stream parser::parse_many(const char *buf, size_t len, size_t batch_size) noexcept {
return parse_many((const uint8_t *)buf, len, batch_size);
}
inline document::stream document::parser::parse_many(const std::string &s, size_t batch_size) noexcept {
inline stream parser::parse_many(const std::string &s, size_t batch_size) noexcept {
return parse_many(s.data(), s.length(), batch_size);
}
inline document::stream document::parser::parse_many(const padded_string &s, size_t batch_size) noexcept {
inline stream parser::parse_many(const padded_string &s, size_t batch_size) noexcept {
return parse_many(s.data(), s.length(), batch_size);
}
really_inline size_t document::parser::capacity() const noexcept {
really_inline size_t parser::capacity() const noexcept {
return _capacity;
}
really_inline size_t document::parser::max_capacity() const noexcept {
really_inline size_t parser::max_capacity() const noexcept {
return _max_capacity;
}
really_inline size_t document::parser::max_depth() const noexcept {
really_inline size_t parser::max_depth() const noexcept {
return _max_depth;
}
WARN_UNUSED
inline error_code document::parser::set_capacity(size_t capacity) noexcept {
inline error_code parser::set_capacity(size_t capacity) noexcept {
if (_capacity == capacity) {
return SUCCESS;
}
@ -483,11 +487,11 @@ inline error_code document::parser::set_capacity(size_t capacity) noexcept {
return SUCCESS;
}
really_inline void document::parser::set_max_capacity(size_t max_capacity) noexcept {
really_inline void parser::set_max_capacity(size_t max_capacity) noexcept {
_max_capacity = max_capacity;
}
WARN_UNUSED inline error_code document::parser::set_max_depth(size_t max_depth) noexcept {
WARN_UNUSED inline error_code parser::set_max_depth(size_t max_depth) noexcept {
if (max_depth == _max_depth && ret_address) { return SUCCESS; }
_max_depth = 0;
@ -517,11 +521,11 @@ WARN_UNUSED inline error_code document::parser::set_max_depth(size_t max_depth)
return SUCCESS;
}
WARN_UNUSED inline bool document::parser::allocate_capacity(size_t capacity, size_t max_depth) noexcept {
WARN_UNUSED inline bool parser::allocate_capacity(size_t capacity, size_t max_depth) noexcept {
return !set_capacity(capacity) && !set_max_depth(max_depth);
}
inline error_code document::parser::ensure_capacity(size_t desired_capacity) noexcept {
inline error_code parser::ensure_capacity(size_t desired_capacity) noexcept {
// If we don't have enough capacity, (try to) automatically bump it.
if (unlikely(desired_capacity > capacity())) {
if (desired_capacity > max_capacity()) {
@ -545,59 +549,19 @@ inline error_code document::parser::ensure_capacity(size_t desired_capacity) noe
return SUCCESS;
}
//
// tape_ref inline implementation
//
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 internal::tape_ref::after_element() const noexcept {
switch (type()) {
case tape_type::START_ARRAY:
case tape_type::START_OBJECT:
return tape_value();
case tape_type::UINT64:
case tape_type::INT64:
case tape_type::DOUBLE:
return json_index + 2;
default:
return json_index + 1;
}
}
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 internal::tape_ref::tape_value() const noexcept {
return doc->tape[json_index] & internal::JSON_VALUE_MASK;
}
template<typename T>
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 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));
return std::string_view(
reinterpret_cast<const char *>(&doc->string_buf[string_buf_index + sizeof(uint32_t)]),
len
);
}
//
// array inline implementation
//
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 {
really_inline array::array() noexcept : internal::tape_ref() {}
really_inline array::array(const document *_doc, size_t _json_index) noexcept : internal::tape_ref(_doc, _json_index) {}
inline array::iterator array::begin() const noexcept {
return iterator(doc, json_index + 1);
}
inline document::array::iterator document::array::end() const noexcept {
inline array::iterator array::end() const noexcept {
return iterator(doc, after_element() - 1);
}
inline simdjson_result<document::element> document::array::at(const std::string_view &json_pointer) const noexcept {
inline simdjson_result<element> array::at(const std::string_view &json_pointer) const noexcept {
// - means "the append position" or "the element after the end of the array"
// We don't support this, because we're returning a real element, not a position.
if (json_pointer == "-") { return INDEX_OUT_OF_BOUNDS; }
@ -626,7 +590,7 @@ inline simdjson_result<document::element> document::array::at(const std::string_
}
return child;
}
inline simdjson_result<document::element> document::array::at(size_t index) const noexcept {
inline simdjson_result<element> array::at(size_t index) const noexcept {
size_t i=0;
for (auto element : *this) {
if (i == index) { return element; }
@ -636,43 +600,43 @@ inline simdjson_result<document::element> document::array::at(size_t index) cons
}
//
// document::array::iterator inline implementation
// array::iterator inline implementation
//
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 {
really_inline array::iterator::iterator(const document *_doc, size_t _json_index) noexcept : internal::tape_ref(_doc, _json_index) { }
inline element array::iterator::operator*() const noexcept {
return element(doc, json_index);
}
inline bool document::array::iterator::operator!=(const document::array::iterator& other) const noexcept {
inline bool array::iterator::operator!=(const array::iterator& other) const noexcept {
return json_index != other.json_index;
}
inline void document::array::iterator::operator++() noexcept {
inline void array::iterator::operator++() noexcept {
json_index = after_element();
}
//
// document::object inline implementation
// object inline implementation
//
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 {
really_inline object::object() noexcept : internal::tape_ref() {}
really_inline object::object(const document *_doc, size_t _json_index) noexcept : internal::tape_ref(_doc, _json_index) { };
inline object::iterator object::begin() const noexcept {
return iterator(doc, json_index + 1);
}
inline document::object::iterator document::object::end() const noexcept {
inline object::iterator object::end() const noexcept {
return iterator(doc, after_element() - 1);
}
inline simdjson_result<document::element> document::object::operator[](const std::string_view &json_pointer) const noexcept {
inline simdjson_result<element> object::operator[](const std::string_view &json_pointer) const noexcept {
return at(json_pointer);
}
inline simdjson_result<document::element> document::object::operator[](const char *json_pointer) const noexcept {
inline simdjson_result<element> object::operator[](const char *json_pointer) const noexcept {
return at(json_pointer);
}
inline simdjson_result<document::element> document::object::at(const std::string_view &json_pointer) const noexcept {
inline simdjson_result<element> object::at(const std::string_view &json_pointer) const noexcept {
size_t slash = json_pointer.find('/');
std::string_view key = json_pointer.substr(0, slash);
// Grab the child with the given key
simdjson_result<document::element> child;
simdjson_result<element> child;
// If there is an escape character in the key, unescape it and then get the child.
size_t escape = key.find('~');
@ -704,7 +668,7 @@ inline simdjson_result<document::element> document::object::at(const std::string
return child;
}
inline simdjson_result<document::element> document::object::at_key(const std::string_view &key) const noexcept {
inline simdjson_result<element> object::at_key(const std::string_view &key) const noexcept {
iterator end_field = end();
for (iterator field = begin(); field != end_field; ++field) {
if (key == field.key()) {
@ -716,7 +680,7 @@ inline simdjson_result<document::element> document::object::at_key(const std::st
// In case you wonder why we need this, please see
// https://github.com/simdjson/simdjson/issues/323
// People do seek keys in a case-insensitive manner.
inline simdjson_result<document::element> document::object::at_key_case_insensitive(const std::string_view &key) const noexcept {
inline simdjson_result<element> object::at_key_case_insensitive(const std::string_view &key) const noexcept {
iterator end_field = end();
for (iterator field = begin(); field != end_field; ++field) {
auto field_key = field.key();
@ -732,20 +696,20 @@ inline simdjson_result<document::element> document::object::at_key_case_insensit
}
//
// document::object::iterator inline implementation
// object::iterator inline implementation
//
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 {
really_inline object::iterator::iterator(const document *_doc, size_t _json_index) noexcept : internal::tape_ref(_doc, _json_index) { }
inline const key_value_pair object::iterator::operator*() const noexcept {
return key_value_pair(key(), value());
}
inline bool document::object::iterator::operator!=(const document::object::iterator& other) const noexcept {
inline bool object::iterator::operator!=(const object::iterator& other) const noexcept {
return json_index != other.json_index;
}
inline void document::object::iterator::operator++() noexcept {
inline void object::iterator::operator++() noexcept {
json_index++;
json_index = after_element();
}
inline std::string_view document::object::iterator::key() const noexcept {
inline std::string_view object::iterator::key() const noexcept {
size_t string_buf_index = tape_value();
uint32_t len;
memcpy(&len, &doc->string_buf[string_buf_index], sizeof(len));
@ -754,67 +718,67 @@ inline std::string_view document::object::iterator::key() const noexcept {
len
);
}
inline const char* document::object::iterator::key_c_str() const noexcept {
inline const char* object::iterator::key_c_str() const noexcept {
return reinterpret_cast<const char *>(&doc->string_buf[tape_value() + sizeof(uint32_t)]);
}
inline document::element document::object::iterator::value() const noexcept {
inline element object::iterator::value() const noexcept {
return element(doc, json_index + 1);
}
//
// document::key_value_pair inline implementation
// key_value_pair inline implementation
//
inline document::key_value_pair::key_value_pair(const std::string_view &_key, element _value) noexcept :
inline key_value_pair::key_value_pair(const std::string_view &_key, element _value) noexcept :
key(_key), value(_value) {}
//
// element inline implementation
//
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 element::element() noexcept : internal::tape_ref() {}
really_inline 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 {
really_inline bool element::is_null() const noexcept {
return type() == internal::tape_type::NULL_VALUE;
}
really_inline bool document::element::is_bool() const noexcept {
really_inline bool element::is_bool() const noexcept {
return type() == internal::tape_type::TRUE_VALUE || type() == internal::tape_type::FALSE_VALUE;
}
really_inline bool document::element::is_number() const noexcept {
really_inline bool element::is_number() const noexcept {
return type() == internal::tape_type::UINT64 || type() == internal::tape_type::INT64 || type() == internal::tape_type::DOUBLE;
}
really_inline bool document::element::is_float() const noexcept {
really_inline bool element::is_float() const noexcept {
return type() == internal::tape_type::DOUBLE;
}
really_inline bool document::element::is_integer() const noexcept {
really_inline bool element::is_integer() const noexcept {
return type() == internal::tape_type::UINT64 || type() == internal::tape_type::INT64;
}
really_inline bool document::element::is_unsigned_integer() const noexcept {
really_inline bool element::is_unsigned_integer() const noexcept {
return type() == internal::tape_type::UINT64;
}
really_inline bool document::element::is_string() const noexcept {
really_inline bool element::is_string() const noexcept {
return type() == internal::tape_type::STRING;
}
really_inline bool document::element::is_array() const noexcept {
really_inline bool element::is_array() const noexcept {
return type() == internal::tape_type::START_ARRAY;
}
really_inline bool document::element::is_object() const noexcept {
really_inline bool element::is_object() const noexcept {
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(); }
inline document::element::operator uint64_t() const noexcept(false) { return as_uint64_t(); }
inline document::element::operator int64_t() const noexcept(false) { return as_int64_t(); }
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 element::operator bool() const noexcept(false) { return as_bool(); }
inline element::operator const char*() const noexcept(false) { return as_c_str(); }
inline element::operator std::string_view() const noexcept(false) { return as_string(); }
inline element::operator uint64_t() const noexcept(false) { return as_uint64_t(); }
inline element::operator int64_t() const noexcept(false) { return as_int64_t(); }
inline element::operator double() const noexcept(false) { return as_double(); }
inline element::operator array() const noexcept(false) { return as_array(); }
inline element::operator object() const noexcept(false) { return as_object(); }
#endif
inline simdjson_result<bool> document::element::as_bool() const noexcept {
inline simdjson_result<bool> element::as_bool() const noexcept {
switch (type()) {
case internal::tape_type::TRUE_VALUE:
return true;
@ -824,7 +788,7 @@ inline simdjson_result<bool> document::element::as_bool() const noexcept {
return INCORRECT_TYPE;
}
}
inline simdjson_result<const char *> document::element::as_c_str() const noexcept {
inline simdjson_result<const char *> element::as_c_str() const noexcept {
switch (type()) {
case internal::tape_type::STRING: {
size_t string_buf_index = tape_value();
@ -834,7 +798,7 @@ inline simdjson_result<const char *> document::element::as_c_str() const noexcep
return INCORRECT_TYPE;
}
}
inline simdjson_result<std::string_view> document::element::as_string() const noexcept {
inline simdjson_result<std::string_view> element::as_string() const noexcept {
switch (type()) {
case internal::tape_type::STRING:
return get_string_view();
@ -842,7 +806,7 @@ inline simdjson_result<std::string_view> document::element::as_string() const no
return INCORRECT_TYPE;
}
}
inline simdjson_result<uint64_t> document::element::as_uint64_t() const noexcept {
inline simdjson_result<uint64_t> element::as_uint64_t() const noexcept {
switch (type()) {
case internal::tape_type::UINT64:
return next_tape_value<uint64_t>();
@ -857,7 +821,7 @@ inline simdjson_result<uint64_t> document::element::as_uint64_t() const noexcept
return INCORRECT_TYPE;
}
}
inline simdjson_result<int64_t> document::element::as_int64_t() const noexcept {
inline simdjson_result<int64_t> element::as_int64_t() const noexcept {
switch (type()) {
case internal::tape_type::UINT64: {
uint64_t result = next_tape_value<uint64_t>();
@ -873,7 +837,7 @@ inline simdjson_result<int64_t> document::element::as_int64_t() const noexcept {
return INCORRECT_TYPE;
}
}
inline simdjson_result<double> document::element::as_double() const noexcept {
inline simdjson_result<double> element::as_double() const noexcept {
switch (type()) {
case internal::tape_type::UINT64:
return next_tape_value<uint64_t>();
@ -891,7 +855,7 @@ inline simdjson_result<double> document::element::as_double() const noexcept {
return INCORRECT_TYPE;
}
}
inline simdjson_result<document::array> document::element::as_array() const noexcept {
inline simdjson_result<array> element::as_array() const noexcept {
switch (type()) {
case internal::tape_type::START_ARRAY:
return array(doc, json_index);
@ -899,7 +863,7 @@ inline simdjson_result<document::array> document::element::as_array() const noex
return INCORRECT_TYPE;
}
}
inline simdjson_result<document::object> document::element::as_object() const noexcept {
inline simdjson_result<object> element::as_object() const noexcept {
switch (type()) {
case internal::tape_type::START_OBJECT:
return object(doc, json_index);
@ -907,13 +871,13 @@ inline simdjson_result<document::object> document::element::as_object() const no
return INCORRECT_TYPE;
}
}
inline simdjson_result<document::element> document::element::operator[](const std::string_view &json_pointer) const noexcept {
inline simdjson_result<element> element::operator[](const std::string_view &json_pointer) const noexcept {
return at(json_pointer);
}
inline simdjson_result<document::element> document::element::operator[](const char *json_pointer) const noexcept {
inline simdjson_result<element> element::operator[](const char *json_pointer) const noexcept {
return at(json_pointer);
}
inline simdjson_result<document::element> document::element::at(const std::string_view &json_pointer) const noexcept {
inline simdjson_result<element> element::at(const std::string_view &json_pointer) const noexcept {
switch (type()) {
case internal::tape_type::START_OBJECT:
return object(doc, json_index).at(json_pointer);
@ -923,26 +887,30 @@ inline simdjson_result<document::element> document::element::at(const std::strin
return INCORRECT_TYPE;
}
}
inline simdjson_result<document::element> document::element::at(size_t index) const noexcept {
inline simdjson_result<element> element::at(size_t index) const noexcept {
return as_array().at(index);
}
inline simdjson_result<document::element> document::element::at_key(const std::string_view &key) const noexcept {
inline simdjson_result<element> element::at_key(const std::string_view &key) const noexcept {
return as_object().at_key(key);
}
inline simdjson_result<document::element> document::element::at_key_case_insensitive(const std::string_view &key) const noexcept {
inline simdjson_result<element> element::at_key_case_insensitive(const std::string_view &key) const noexcept {
return as_object().at_key_case_insensitive(key);
}
inline bool document::element::dump_raw_tape(std::ostream &out) const noexcept {
inline bool element::dump_raw_tape(std::ostream &out) const noexcept {
return doc->dump_raw_tape(out);
}
} // namespace simdjson::dom
namespace simdjson {
//
// minify inline implementation
//
template<>
inline std::ostream& minify<document::element>::print(std::ostream& out) {
inline std::ostream& minify<dom::element>::print(std::ostream& out) {
using tape_type=internal::tape_type;
size_t depth = 0;
constexpr size_t MAX_DEPTH = 16;
@ -950,7 +918,7 @@ inline std::ostream& minify<document::element>::print(std::ostream& out) {
is_object[0] = false;
bool after_value = false;
internal::tape_ref iter(value.doc, value.json_index);
internal::tape_ref iter(value);
do {
// print commas after each value
if (after_value) {
@ -968,7 +936,7 @@ inline std::ostream& minify<document::element>::print(std::ostream& out) {
// If we're too deep, we need to recurse to go deeper.
depth++;
if (unlikely(depth >= MAX_DEPTH)) {
out << minify<document::array>(document::array(iter.doc, iter.json_index));
out << minify<dom::array>(dom::array(iter.doc, iter.json_index));
iter.json_index = iter.tape_value() - 1; // Jump to the ]
depth--;
break;
@ -995,7 +963,7 @@ inline std::ostream& minify<document::element>::print(std::ostream& out) {
// If we're too deep, we need to recurse to go deeper.
depth++;
if (unlikely(depth >= MAX_DEPTH)) {
out << minify<document::object>(document::object(iter.doc, iter.json_index));
out << minify<dom::object>(dom::object(iter.doc, iter.json_index));
iter.json_index = iter.tape_value() - 1; // Jump to the }
depth--;
break;
@ -1065,56 +1033,101 @@ inline std::ostream& minify<document::element>::print(std::ostream& out) {
return out;
}
template<>
inline std::ostream& minify<document::object>::print(std::ostream& out) {
inline std::ostream& minify<dom::object>::print(std::ostream& out) {
out << '{';
auto pair = value.begin();
auto end = value.end();
if (pair != end) {
out << minify<document::key_value_pair>(*pair);
out << minify<dom::key_value_pair>(*pair);
for (++pair; pair != end; ++pair) {
out << "," << minify<document::key_value_pair>(*pair);
out << "," << minify<dom::key_value_pair>(*pair);
}
}
return out << '}';
}
template<>
inline std::ostream& minify<document::array>::print(std::ostream& out) {
inline std::ostream& minify<dom::array>::print(std::ostream& out) {
out << '[';
auto element = value.begin();
auto iter = value.begin();
auto end = value.end();
if (element != end) {
out << minify<document::element>(*element);
for (++element; element != end; ++element) {
out << "," << minify<document::element>(*element);
if (iter != end) {
out << minify<dom::element>(*iter);
for (++iter; iter != end; ++iter) {
out << "," << minify<dom::element>(*iter);
}
}
return out << ']';
}
template<>
inline std::ostream& minify<document::key_value_pair>::print(std::ostream& out) {
inline std::ostream& minify<dom::key_value_pair>::print(std::ostream& out) {
return out << '"' << internal::escape_json_string(value.key) << "\":" << value.value;
}
#if SIMDJSON_EXCEPTIONS
template<>
inline std::ostream& minify<simdjson_result<document::element>>::print(std::ostream& out) {
inline std::ostream& minify<simdjson_result<dom::element>>::print(std::ostream& out) {
if (value.error()) { throw simdjson_error(value.error()); }
return out << minify<document::element>(value.first);
return out << minify<dom::element>(value.first);
}
template<>
inline std::ostream& minify<simdjson_result<document::array>>::print(std::ostream& out) {
inline std::ostream& minify<simdjson_result<dom::array>>::print(std::ostream& out) {
if (value.error()) { throw simdjson_error(value.error()); }
return out << minify<document::array>(value.first);
return out << minify<dom::array>(value.first);
}
template<>
inline std::ostream& minify<simdjson_result<document::object>>::print(std::ostream& out) {
inline std::ostream& minify<simdjson_result<dom::object>>::print(std::ostream& out) {
if (value.error()) { throw simdjson_error(value.error()); }
return out << minify<document::object>(value.first);
return out << minify<dom::object>(value.first);
}
#endif
} // namespace simdjson
namespace simdjson::internal {
//
// tape_ref inline implementation
//
really_inline tape_ref::tape_ref() noexcept : doc{nullptr}, json_index{0} {}
really_inline tape_ref::tape_ref(const document *_doc, size_t _json_index) noexcept : doc{_doc}, json_index{_json_index} {}
inline size_t tape_ref::after_element() const noexcept {
switch (type()) {
case tape_type::START_ARRAY:
case tape_type::START_OBJECT:
return tape_value();
case tape_type::UINT64:
case tape_type::INT64:
case tape_type::DOUBLE:
return json_index + 2;
default:
return json_index + 1;
}
}
really_inline tape_type tape_ref::type() const noexcept {
return static_cast<tape_type>(doc->tape[json_index] >> 56);
}
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 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 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));
return std::string_view(
reinterpret_cast<const char *>(&doc->string_buf[string_buf_index + sizeof(uint32_t)]),
len
);
}
} // namespace simdjson::internal
#endif // SIMDJSON_INLINE_DOCUMENT_H

View File

@ -32,7 +32,7 @@ namespace simdjson::internal {
* complete
* document, therefore the last json buffer location is the end of the batch
* */
inline size_t find_last_json_buf_idx(const uint8_t *buf, size_t size, const document::parser &parser) {
inline size_t find_last_json_buf_idx(const uint8_t *buf, size_t size, const dom::parser &parser) {
// this function can be generally useful
if (parser.n_structural_indexes == 0)
return 0;
@ -95,10 +95,10 @@ static inline size_t trimmed_length_safe_utf8(const char * c, size_t len) {
} // namespace simdjson::internal
namespace simdjson {
namespace simdjson::dom {
really_inline document::stream::stream(
document::parser &_parser,
really_inline stream::stream(
dom::parser &_parser,
const uint8_t *buf,
size_t len,
size_t batch_size,
@ -107,7 +107,7 @@ really_inline document::stream::stream(
if (!error) { error = json_parse(); }
}
inline document::stream::~stream() noexcept {
inline stream::~stream() noexcept {
#ifdef SIMDJSON_THREADS_ENABLED
if (stage_1_thread.joinable()) {
stage_1_thread.join();
@ -115,25 +115,25 @@ inline document::stream::~stream() noexcept {
#endif
}
really_inline document::stream::iterator document::stream::begin() noexcept {
really_inline stream::iterator stream::begin() noexcept {
return iterator(*this, false);
}
really_inline document::stream::iterator document::stream::end() noexcept {
really_inline stream::iterator stream::end() noexcept {
return iterator(*this, true);
}
really_inline document::stream::iterator::iterator(stream& stream, bool _is_end) noexcept
really_inline stream::iterator::iterator(stream& stream, bool _is_end) noexcept
: _stream{stream}, finished{_is_end} {
}
really_inline simdjson_result<document::element> document::stream::iterator::operator*() noexcept {
really_inline simdjson_result<element> stream::iterator::operator*() noexcept {
error_code error = _stream.error == SUCCESS_AND_HAS_MORE ? SUCCESS : _stream.error;
if (error) { return error; }
return _stream.parser.doc.root();
}
really_inline document::stream::iterator& document::stream::iterator::operator++() noexcept {
really_inline stream::iterator& stream::iterator::operator++() noexcept {
if (_stream.error == SUCCESS_AND_HAS_MORE) {
_stream.error = _stream.json_parse();
} else {
@ -142,7 +142,7 @@ really_inline document::stream::iterator& document::stream::iterator::operator++
return *this;
}
really_inline bool document::stream::iterator::operator!=(const document::stream::iterator &other) const noexcept {
really_inline bool stream::iterator::operator!=(const stream::iterator &other) const noexcept {
return finished != other.finished;
}
@ -150,7 +150,7 @@ really_inline bool document::stream::iterator::operator!=(const document::stream
// threaded version of json_parse
// todo: simplify this code further
inline error_code document::stream::json_parse() noexcept {
inline error_code stream::json_parse() noexcept {
error = parser.ensure_capacity(_batch_size);
if (error) { return error; }
error = parser_thread.ensure_capacity(_batch_size);
@ -232,7 +232,7 @@ inline error_code document::stream::json_parse() noexcept {
#else // SIMDJSON_THREADS_ENABLED
// single-threaded version of json_parse
inline error_code document::stream::json_parse() noexcept {
inline error_code stream::json_parse() noexcept {
error = parser.ensure_capacity(_batch_size);
if (error) { return error; }
@ -272,5 +272,5 @@ inline error_code document::stream::json_parse() noexcept {
}
#endif // SIMDJSON_THREADS_ENABLED
} // end of namespace simdjson
} // namespace simdjson::dom
#endif // SIMDJSON_INLINE_DOCUMENT_STREAM_H

View File

@ -13,8 +13,8 @@ namespace simdjson {
// C API (json_parse and build_parsed_json) declarations
//
[[deprecated("Use document::parser.parse() instead")]]
inline int json_parse(const uint8_t *buf, size_t len, document::parser &parser, bool realloc_if_needed = true) noexcept {
[[deprecated("Use parser.parse() instead")]]
inline int json_parse(const uint8_t *buf, size_t len, dom::parser &parser, bool realloc_if_needed = true) noexcept {
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
@ -24,8 +24,8 @@ inline int json_parse(const uint8_t *buf, size_t len, document::parser &parser,
parser.error = code;
return code;
}
[[deprecated("Use document::parser.parse() instead")]]
inline int json_parse(const char *buf, size_t len, document::parser &parser, bool realloc_if_needed = true) noexcept {
[[deprecated("Use parser.parse() instead")]]
inline int json_parse(const char *buf, size_t len, dom::parser &parser, bool realloc_if_needed = true) noexcept {
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
@ -35,8 +35,8 @@ inline int json_parse(const char *buf, size_t len, document::parser &parser, boo
parser.error = code;
return code;
}
[[deprecated("Use document::parser.parse() instead")]]
inline int json_parse(const std::string &s, document::parser &parser, bool realloc_if_needed = true) noexcept {
[[deprecated("Use parser.parse() instead")]]
inline int json_parse(const std::string &s, dom::parser &parser, bool realloc_if_needed = true) noexcept {
error_code code = parser.parse(s.data(), s.length(), 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
@ -46,8 +46,8 @@ inline int json_parse(const std::string &s, document::parser &parser, bool reall
parser.error = code;
return code;
}
[[deprecated("Use document::parser.parse() instead")]]
inline int json_parse(const padded_string &s, document::parser &parser) noexcept {
[[deprecated("Use parser.parse() instead")]]
inline int json_parse(const padded_string &s, dom::parser &parser) noexcept {
error_code code = parser.parse(s).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
@ -58,9 +58,9 @@ inline int json_parse(const padded_string &s, document::parser &parser) noexcept
return code;
}
[[deprecated("Use document::parser.parse() instead")]]
WARN_UNUSED inline document::parser build_parsed_json(const uint8_t *buf, size_t len, bool realloc_if_needed = true) noexcept {
document::parser parser;
[[deprecated("Use parser.parse() instead")]]
WARN_UNUSED inline dom::parser build_parsed_json(const uint8_t *buf, size_t len, bool realloc_if_needed = true) noexcept {
dom::parser parser;
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
@ -70,9 +70,9 @@ WARN_UNUSED inline document::parser build_parsed_json(const uint8_t *buf, size_t
parser.error = code;
return parser;
}
[[deprecated("Use document::parser.parse() instead")]]
WARN_UNUSED inline document::parser build_parsed_json(const char *buf, size_t len, bool realloc_if_needed = true) noexcept {
document::parser parser;
[[deprecated("Use parser.parse() instead")]]
WARN_UNUSED inline dom::parser build_parsed_json(const char *buf, size_t len, bool realloc_if_needed = true) noexcept {
dom::parser parser;
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
@ -82,9 +82,9 @@ WARN_UNUSED inline document::parser build_parsed_json(const char *buf, size_t le
parser.error = code;
return parser;
}
[[deprecated("Use document::parser.parse() instead")]]
WARN_UNUSED inline document::parser build_parsed_json(const std::string &s, bool realloc_if_needed = true) noexcept {
document::parser parser;
[[deprecated("Use parser.parse() instead")]]
WARN_UNUSED inline dom::parser build_parsed_json(const std::string &s, bool realloc_if_needed = true) noexcept {
dom::parser parser;
error_code code = parser.parse(s.data(), s.length(), 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
@ -94,9 +94,9 @@ WARN_UNUSED inline document::parser build_parsed_json(const std::string &s, bool
parser.error = code;
return parser;
}
[[deprecated("Use document::parser.parse() instead")]]
WARN_UNUSED inline document::parser build_parsed_json(const padded_string &s) noexcept {
document::parser parser;
[[deprecated("Use parser.parse() instead")]]
WARN_UNUSED inline dom::parser build_parsed_json(const padded_string &s) noexcept {
dom::parser parser;
error_code code = parser.parse(s).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
@ -108,8 +108,8 @@ WARN_UNUSED inline document::parser build_parsed_json(const padded_string &s) no
}
// We do not want to allow implicit conversion from C string to std::string.
int json_parse(const char *buf, document::parser &parser) noexcept = delete;
document::parser build_parsed_json(const char *buf) noexcept = delete;
int json_parse(const char *buf, dom::parser &parser) noexcept = delete;
dom::parser build_parsed_json(const char *buf) noexcept = delete;
} // namespace simdjson

View File

@ -11,7 +11,7 @@
namespace simdjson {
/**
* String with extra allocation for ease of use with document::parser::parse()
* String with extra allocation for ease of use with parser::parse()
*
* This is a move-only class, it cannot be copied.
*/

View File

@ -7,7 +7,7 @@
namespace simdjson {
using ParsedJson = document::parser;
using ParsedJson = dom::parser;
} // namespace simdjson
#endif

View File

@ -6,14 +6,16 @@
namespace simdjson::arm64 {
using namespace simdjson::dom;
class implementation final : public simdjson::implementation {
public:
really_inline implementation() : simdjson::implementation("arm64", "ARM NEON", instruction_set::NEON) {}
WARN_UNUSED error_code parse(const uint8_t *buf, size_t len, document::parser &parser) const noexcept final;
WARN_UNUSED error_code parse(const uint8_t *buf, size_t len, parser &parser) const noexcept final;
WARN_UNUSED error_code minify(const uint8_t *buf, size_t len, uint8_t *dst, size_t &dst_len) const noexcept final;
WARN_UNUSED error_code stage1(const uint8_t *buf, size_t len, document::parser &parser, bool streaming) const noexcept final;
WARN_UNUSED error_code stage2(const uint8_t *buf, size_t len, document::parser &parser) const noexcept final;
WARN_UNUSED error_code stage2(const uint8_t *buf, size_t len, document::parser &parser, size_t &next_json) const noexcept final;
WARN_UNUSED error_code stage1(const uint8_t *buf, size_t len, parser &parser, bool streaming) const noexcept final;
WARN_UNUSED error_code stage2(const uint8_t *buf, size_t len, parser &parser) const noexcept final;
WARN_UNUSED error_code stage2(const uint8_t *buf, size_t len, parser &parser, size_t &next_json) const noexcept final;
};
} // namespace simdjson::arm64

View File

@ -81,7 +81,7 @@ WARN_UNUSED error_code implementation::minify(const uint8_t *buf, size_t len, ui
#include "generic/utf8_lookup2_algorithm.h"
#include "generic/json_structural_indexer.h"
WARN_UNUSED error_code implementation::stage1(const uint8_t *buf, size_t len, document::parser &parser, bool streaming) const noexcept {
WARN_UNUSED error_code implementation::stage1(const uint8_t *buf, size_t len, parser &parser, bool streaming) const noexcept {
return arm64::stage1::json_structural_indexer::index<64>(buf, len, parser, streaming);
}

View File

@ -3,85 +3,85 @@
#include "simdjson.h"
namespace simdjson {
namespace simdjson::dom {
//
// Parser callbacks
//
inline void document::parser::init_stage2() noexcept {
inline void parser::init_stage2() noexcept {
current_string_buf_loc = doc.string_buf.get();
current_loc = 0;
valid = false;
error = UNINITIALIZED;
}
really_inline error_code document::parser::on_error(error_code new_error_code) noexcept {
really_inline error_code parser::on_error(error_code new_error_code) noexcept {
error = new_error_code;
return new_error_code;
}
really_inline error_code document::parser::on_success(error_code success_code) noexcept {
really_inline error_code parser::on_success(error_code success_code) noexcept {
error = success_code;
valid = true;
return success_code;
}
really_inline bool document::parser::on_start_document(uint32_t depth) noexcept {
really_inline bool parser::on_start_document(uint32_t depth) noexcept {
containing_scope_offset[depth] = current_loc;
write_tape(0, internal::tape_type::ROOT);
return true;
}
really_inline bool document::parser::on_start_object(uint32_t depth) noexcept {
really_inline bool parser::on_start_object(uint32_t depth) noexcept {
containing_scope_offset[depth] = current_loc;
write_tape(0, internal::tape_type::START_OBJECT);
return true;
}
really_inline bool document::parser::on_start_array(uint32_t depth) noexcept {
really_inline bool parser::on_start_array(uint32_t depth) noexcept {
containing_scope_offset[depth] = current_loc;
write_tape(0, internal::tape_type::START_ARRAY);
return true;
}
// TODO we're not checking this bool
really_inline bool document::parser::on_end_document(uint32_t depth) noexcept {
really_inline bool 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], internal::tape_type::ROOT);
return true;
}
really_inline bool document::parser::on_end_object(uint32_t depth) noexcept {
really_inline bool parser::on_end_object(uint32_t depth) noexcept {
// write our doc.tape location to the header scope
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 {
really_inline bool parser::on_end_array(uint32_t depth) noexcept {
// write our doc.tape location to the header scope
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 {
really_inline bool parser::on_true_atom() noexcept {
write_tape(0, internal::tape_type::TRUE_VALUE);
return true;
}
really_inline bool document::parser::on_false_atom() noexcept {
really_inline bool parser::on_false_atom() noexcept {
write_tape(0, internal::tape_type::FALSE_VALUE);
return true;
}
really_inline bool document::parser::on_null_atom() noexcept {
really_inline bool parser::on_null_atom() noexcept {
write_tape(0, internal::tape_type::NULL_VALUE);
return true;
}
really_inline uint8_t *document::parser::on_start_string() noexcept {
really_inline uint8_t *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(), internal::tape_type::STRING);
return current_string_buf_loc + sizeof(uint32_t);
}
really_inline bool document::parser::on_end_string(uint8_t *dst) noexcept {
really_inline bool parser::on_end_string(uint8_t *dst) noexcept {
uint32_t str_length = dst - (current_string_buf_loc + sizeof(uint32_t));
// TODO check for overflow in case someone has a crazy string (>=4GB?)
// But only add the overflow check when the document itself exceeds 4GB
@ -94,18 +94,18 @@ really_inline bool document::parser::on_end_string(uint8_t *dst) noexcept {
return true;
}
really_inline bool document::parser::on_number_s64(int64_t value) noexcept {
really_inline bool parser::on_number_s64(int64_t value) noexcept {
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 {
really_inline bool parser::on_number_u64(uint64_t value) noexcept {
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 {
really_inline bool parser::on_number_double(double value) noexcept {
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));
@ -113,14 +113,14 @@ really_inline bool document::parser::on_number_double(double value) noexcept {
return true;
}
really_inline void document::parser::write_tape(uint64_t val, internal::tape_type t) noexcept {
really_inline void 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);
}
really_inline void document::parser::annotate_previous_loc(uint32_t saved_loc, uint64_t val) noexcept {
really_inline void parser::annotate_previous_loc(uint32_t saved_loc, uint64_t val) noexcept {
doc.tape[saved_loc] |= val;
}
} // namespace simdjson
} // namespace simdjson::dom
#endif // SIMDJSON_DOCUMENT_PARSER_CALLBACKS_H

View File

@ -6,6 +6,8 @@
namespace simdjson::fallback {
using namespace simdjson::dom;
class implementation final : public simdjson::implementation {
public:
really_inline implementation() : simdjson::implementation(
@ -13,11 +15,11 @@ public:
"Generic fallback implementation",
0
) {}
WARN_UNUSED error_code parse(const uint8_t *buf, size_t len, document::parser &parser) const noexcept final;
WARN_UNUSED error_code parse(const uint8_t *buf, size_t len, parser &parser) const noexcept final;
WARN_UNUSED error_code minify(const uint8_t *buf, size_t len, uint8_t *dst, size_t &dst_len) const noexcept final;
WARN_UNUSED error_code stage1(const uint8_t *buf, size_t len, document::parser &parser, bool streaming) const noexcept final;
WARN_UNUSED error_code stage2(const uint8_t *buf, size_t len, document::parser &parser) const noexcept final;
WARN_UNUSED error_code stage2(const uint8_t *buf, size_t len, document::parser &parser, size_t &next_json) const noexcept final;
WARN_UNUSED error_code stage1(const uint8_t *buf, size_t len, parser &parser, bool streaming) const noexcept final;
WARN_UNUSED error_code stage2(const uint8_t *buf, size_t len, parser &parser) const noexcept final;
WARN_UNUSED error_code stage2(const uint8_t *buf, size_t len, parser &parser, size_t &next_json) const noexcept final;
};
} // namespace simdjson::fallback

View File

@ -9,7 +9,7 @@ namespace simdjson::fallback::stage1 {
class structural_scanner {
public:
really_inline structural_scanner(const uint8_t *_buf, uint32_t _len, document::parser &_doc_parser, bool _streaming)
really_inline structural_scanner(const uint8_t *_buf, uint32_t _len, parser &_doc_parser, bool _streaming)
: buf{_buf}, next_structural_index{_doc_parser.structural_indexes.get()}, doc_parser{_doc_parser}, idx{0}, len{_len}, error{SUCCESS}, streaming{_streaming} {}
really_inline void add_structural() {
@ -132,7 +132,7 @@ really_inline error_code scan() {
private:
const uint8_t *buf;
uint32_t *next_structural_index;
document::parser &doc_parser;
parser &doc_parser;
uint32_t idx;
uint32_t len;
error_code error;
@ -143,7 +143,7 @@ private:
namespace simdjson::fallback {
WARN_UNUSED error_code implementation::stage1(const uint8_t *buf, size_t len, document::parser &parser, bool streaming) const noexcept {
WARN_UNUSED error_code implementation::stage1(const uint8_t *buf, size_t len, parser &parser, bool streaming) const noexcept {
if (unlikely(len > parser.capacity())) {
return CAPACITY;
}

View File

@ -58,14 +58,14 @@ public:
class json_structural_indexer {
public:
template<size_t STEP_SIZE>
static error_code index(const uint8_t *buf, size_t len, document::parser &parser, bool streaming) noexcept;
static error_code index(const uint8_t *buf, size_t len, parser &parser, bool streaming) noexcept;
private:
really_inline json_structural_indexer(uint32_t *structural_indexes) : indexer{structural_indexes} {}
template<size_t STEP_SIZE>
really_inline void step(const uint8_t *block, buf_block_reader<STEP_SIZE> &reader) noexcept;
really_inline void next(simd::simd8x64<uint8_t> in, json_block block, size_t idx);
really_inline error_code finish(document::parser &parser, size_t idx, size_t len, bool streaming);
really_inline error_code finish(parser &parser, size_t idx, size_t len, bool streaming);
json_scanner scanner;
utf8_checker checker{};
@ -82,7 +82,7 @@ really_inline void json_structural_indexer::next(simd::simd8x64<uint8_t> in, jso
unescaped_chars_error |= block.non_quote_inside_string(unescaped);
}
really_inline error_code json_structural_indexer::finish(document::parser &parser, size_t idx, size_t len, bool streaming) {
really_inline error_code json_structural_indexer::finish(parser &parser, size_t idx, size_t len, bool streaming) {
// Write out the final iteration's structurals
indexer.write(idx-64, prev_structurals);
@ -154,7 +154,7 @@ really_inline void json_structural_indexer::step<64>(const uint8_t *block, buf_b
// The caller should still ensure that the input is valid UTF-8. If you are processing substrings,
// you may want to call on a function like trimmed_length_safe_utf8.
template<size_t STEP_SIZE>
error_code json_structural_indexer::index(const uint8_t *buf, size_t len, document::parser &parser, bool streaming) noexcept {
error_code json_structural_indexer::index(const uint8_t *buf, size_t len, parser &parser, bool streaming) noexcept {
if (unlikely(len > parser.capacity())) { return CAPACITY; }
buf_block_reader<STEP_SIZE> reader(buf, len);

View File

@ -262,7 +262,7 @@ really_inline bool is_made_of_eight_digits_fast(const char *chars) {
// This function will almost never be called!!!
//
never_inline bool parse_large_integer(const uint8_t *const src,
document::parser &parser,
parser &parser,
bool found_minus) {
const char *p = reinterpret_cast<const char *>(src);
@ -341,7 +341,7 @@ never_inline bool parse_large_integer(const uint8_t *const src,
return is_structural_or_whitespace(*p);
}
bool slow_float_parsing(UNUSED const char * src, document::parser &parser) {
bool slow_float_parsing(UNUSED const char * src, parser &parser) {
double d;
if (parse_float_strtod(src, &d)) {
parser.on_number_double(d);
@ -367,7 +367,7 @@ bool slow_float_parsing(UNUSED const char * src, document::parser &parser) {
// Our objective is accurate parsing (ULP of 0) at high speed.
really_inline bool parse_number(UNUSED const uint8_t *const src,
UNUSED bool found_minus,
document::parser &parser) {
parser &parser) {
#ifdef SIMDJSON_SKIPNUMBERPARSING // for performance analysis, it is sometimes
// useful to skip parsing
parser.on_number_s64(0); // always write zero

View File

@ -111,13 +111,13 @@ public:
struct structural_parser {
structural_iterator structurals;
document::parser &doc_parser;
parser &doc_parser;
uint32_t depth;
really_inline structural_parser(
const uint8_t *buf,
size_t len,
document::parser &_doc_parser,
parser &_doc_parser,
uint32_t next_structural = 0
) : structurals(buf, len, _doc_parser.structural_indexes.get(), next_structural), doc_parser{_doc_parser}, depth{0} {}
@ -325,7 +325,7 @@ struct structural_parser {
* The JSON is parsed to a tape, see the accompanying tape.md file
* for documentation.
***********/
WARN_UNUSED error_code implementation::stage2(const uint8_t *buf, size_t len, document::parser &doc_parser) const noexcept {
WARN_UNUSED error_code implementation::stage2(const uint8_t *buf, size_t len, parser &doc_parser) const noexcept {
static constexpr stage2::unified_machine_addresses addresses = INIT_ADDRESSES();
stage2::structural_parser parser(buf, len, doc_parser);
error_code result = parser.start(len, addresses.finish);
@ -436,7 +436,7 @@ error:
return parser.error();
}
WARN_UNUSED error_code implementation::parse(const uint8_t *buf, size_t len, document::parser &doc_parser) const noexcept {
WARN_UNUSED error_code implementation::parse(const uint8_t *buf, size_t len, parser &doc_parser) const noexcept {
error_code code = stage1(buf, len, doc_parser, false);
if (!code) {
code = stage2(buf, len, doc_parser);

View File

@ -1,7 +1,7 @@
namespace stage2 {
struct streaming_structural_parser: structural_parser {
really_inline streaming_structural_parser(const uint8_t *_buf, size_t _len, document::parser &_doc_parser, size_t _i) : structural_parser(_buf, _len, _doc_parser, _i) {}
really_inline streaming_structural_parser(const uint8_t *_buf, size_t _len, parser &_doc_parser, size_t _i) : structural_parser(_buf, _len, _doc_parser, _i) {}
// override to add streaming
WARN_UNUSED really_inline error_code start(UNUSED size_t len, ret_address finish_parser) {
@ -39,7 +39,7 @@ struct streaming_structural_parser: structural_parser {
* The JSON is parsed to a tape, see the accompanying tape.md file
* for documentation.
***********/
WARN_UNUSED error_code implementation::stage2(const uint8_t *buf, size_t len, document::parser &doc_parser, size_t &next_json) const noexcept {
WARN_UNUSED error_code implementation::stage2(const uint8_t *buf, size_t len, parser &doc_parser, size_t &next_json) const noexcept {
static constexpr stage2::unified_machine_addresses addresses = INIT_ADDRESSES();
stage2::streaming_structural_parser parser(buf, len, doc_parser, next_json);
error_code result = parser.start(len, addresses.finish);

View File

@ -6,6 +6,8 @@
namespace simdjson::haswell {
using namespace simdjson::dom;
class implementation final : public simdjson::implementation {
public:
really_inline implementation() : simdjson::implementation(
@ -13,11 +15,11 @@ public:
"Intel/AMD AVX2",
instruction_set::AVX2 | instruction_set::PCLMULQDQ | instruction_set::BMI1 | instruction_set::BMI2
) {}
WARN_UNUSED error_code parse(const uint8_t *buf, size_t len, document::parser &parser) const noexcept final;
WARN_UNUSED error_code parse(const uint8_t *buf, size_t len, parser &parser) const noexcept final;
WARN_UNUSED error_code minify(const uint8_t *buf, size_t len, uint8_t *dst, size_t &dst_len) const noexcept final;
WARN_UNUSED error_code stage1(const uint8_t *buf, size_t len, document::parser &parser, bool streaming) const noexcept final;
WARN_UNUSED error_code stage2(const uint8_t *buf, size_t len, document::parser &parser) const noexcept final;
WARN_UNUSED error_code stage2(const uint8_t *buf, size_t len, document::parser &parser, size_t &next_json) const noexcept final;
WARN_UNUSED error_code stage1(const uint8_t *buf, size_t len, parser &parser, bool streaming) const noexcept final;
WARN_UNUSED error_code stage2(const uint8_t *buf, size_t len, parser &parser) const noexcept final;
WARN_UNUSED error_code stage2(const uint8_t *buf, size_t len, parser &parser, size_t &next_json) const noexcept final;
};
} // namespace simdjson::haswell

View File

@ -70,7 +70,7 @@ WARN_UNUSED error_code implementation::minify(const uint8_t *buf, size_t len, ui
#include "generic/utf8_lookup2_algorithm.h"
#include "generic/json_structural_indexer.h"
WARN_UNUSED error_code implementation::stage1(const uint8_t *buf, size_t len, document::parser &parser, bool streaming) const noexcept {
WARN_UNUSED error_code implementation::stage1(const uint8_t *buf, size_t len, parser &parser, bool streaming) const noexcept {
return haswell::stage1::json_structural_indexer::index<128>(buf, len, parser, streaming);
}

View File

@ -47,19 +47,19 @@ constexpr const std::initializer_list<const implementation *> available_implemen
// So we can return UNSUPPORTED_ARCHITECTURE from the parser when there is no support
class unsupported_implementation final : public implementation {
public:
WARN_UNUSED error_code parse(const uint8_t *, size_t, document::parser &) const noexcept final {
WARN_UNUSED error_code parse(const uint8_t *, size_t, parser &) const noexcept final {
return UNSUPPORTED_ARCHITECTURE;
}
WARN_UNUSED error_code minify(const uint8_t *, size_t, uint8_t *, size_t &) const noexcept final {
return UNSUPPORTED_ARCHITECTURE;
}
WARN_UNUSED error_code stage1(const uint8_t *, size_t, document::parser &, bool) const noexcept final {
WARN_UNUSED error_code stage1(const uint8_t *, size_t, parser &, bool) const noexcept final {
return UNSUPPORTED_ARCHITECTURE;
}
WARN_UNUSED error_code stage2(const uint8_t *, size_t, document::parser &) const noexcept final {
WARN_UNUSED error_code stage2(const uint8_t *, size_t, parser &) const noexcept final {
return UNSUPPORTED_ARCHITECTURE;
}
WARN_UNUSED error_code stage2(const uint8_t *, size_t, document::parser &, size_t &) const noexcept final {
WARN_UNUSED error_code stage2(const uint8_t *, size_t, parser &, size_t &) const noexcept final {
return UNSUPPORTED_ARCHITECTURE;
}

View File

@ -7,14 +7,16 @@
namespace simdjson::westmere {
using namespace simdjson::dom;
class implementation final : public simdjson::implementation {
public:
really_inline implementation() : simdjson::implementation("westmere", "Intel/AMD SSE4.2", instruction_set::SSE42 | instruction_set::PCLMULQDQ) {}
WARN_UNUSED error_code parse(const uint8_t *buf, size_t len, document::parser &parser) const noexcept final;
WARN_UNUSED error_code parse(const uint8_t *buf, size_t len, parser &parser) const noexcept final;
WARN_UNUSED error_code minify(const uint8_t *buf, size_t len, uint8_t *dst, size_t &dst_len) const noexcept final;
WARN_UNUSED error_code stage1(const uint8_t *buf, size_t len, document::parser &parser, bool streaming) const noexcept final;
WARN_UNUSED error_code stage2(const uint8_t *buf, size_t len, document::parser &parser) const noexcept final;
WARN_UNUSED error_code stage2(const uint8_t *buf, size_t len, document::parser &parser, size_t &next_json) const noexcept final;
WARN_UNUSED error_code stage1(const uint8_t *buf, size_t len, parser &parser, bool streaming) const noexcept final;
WARN_UNUSED error_code stage2(const uint8_t *buf, size_t len, parser &parser) const noexcept final;
WARN_UNUSED error_code stage2(const uint8_t *buf, size_t len, parser &parser, size_t &next_json) const noexcept final;
};
} // namespace simdjson::westmere

View File

@ -69,7 +69,7 @@ WARN_UNUSED error_code implementation::minify(const uint8_t *buf, size_t len, ui
#include "generic/utf8_lookup2_algorithm.h"
#include "generic/json_structural_indexer.h"
WARN_UNUSED error_code implementation::stage1(const uint8_t *buf, size_t len, document::parser &parser, bool streaming) const noexcept {
WARN_UNUSED error_code implementation::stage1(const uint8_t *buf, size_t len, parser &parser, bool streaming) const noexcept {
return westmere::stage1::json_structural_indexer::index<64>(buf, len, parser, streaming);
}

View File

@ -78,7 +78,7 @@ int main(int argc, char *argv[]) {
std::cout << p.size() << " B ";
std::cout << std::endl;
}
simdjson::document::parser parser;
simdjson::dom::parser parser;
auto [doc, err] = parser.parse(p);
rapidjson::Document d;

View File

@ -42,7 +42,7 @@ namespace number_tests {
bool small_integers() {
std::cout << __func__ << std::endl;
char buf[1024];
simdjson::document::parser parser;
simdjson::dom::parser parser;
for (int m = 10; m < 20; m++) {
for (int i = -1024; i < 1024; i++) {
auto n = sprintf(buf, "%*d", m, i);
@ -63,7 +63,7 @@ namespace number_tests {
bool powers_of_two() {
std::cout << __func__ << std::endl;
char buf[1024];
simdjson::document::parser parser;
simdjson::dom::parser parser;
int maxulp = 0;
for (int i = -1075; i < 1024; ++i) {// large negative values should be zero.
double expected = pow(2, i);
@ -158,7 +158,7 @@ namespace number_tests {
bool powers_of_ten() {
std::cout << __func__ << std::endl;
char buf[1024];
simdjson::document::parser parser;
simdjson::dom::parser parser;
for (int i = -1000000; i <= 308; ++i) {// large negative values should be zero.
auto n = sprintf(buf,"1e%d", i);
buf[n] = '\0';
@ -188,7 +188,7 @@ namespace document_tests {
bool bad_example() {
std::cout << __func__ << std::endl;
simdjson::padded_string badjson = "[7,7,7,7,6,7,7,7,6,7,7,6,[7,7,7,7,6,7,7,7,6,7,7,6,7,7,7,7,7,7,6"_padded;
simdjson::document::parser parser;
simdjson::dom::parser parser;
auto [doc, error] = parser.parse(badjson);
if (!error) {
printf("This json should not be valid %s.\n", badjson.data());
@ -213,7 +213,7 @@ namespace document_tests {
"\"IDs\":[116,943.3,234,38793]"
"}"
"}"_padded;
simdjson::document::parser parser;
simdjson::dom::parser parser;
std::ostringstream myStream;
myStream << parser.parse(json);
std::string newjson = myStream.str();
@ -255,7 +255,7 @@ namespace document_tests {
if (maxsize < s.size())
maxsize = s.size();
}
simdjson::document::parser parser;
simdjson::dom::parser parser;
size_t counter = 0;
for (auto &rec : data) {
if ((counter % 10000) == 0) {
@ -287,7 +287,7 @@ namespace document_tests {
for(size_t i = 0; i < 200; i++) {
input += "]";
}
simdjson::document::parser parser;
simdjson::dom::parser parser;
auto [doc, error] = parser.parse(input);
if (error) { std::cerr << "Error: " << simdjson::error_message(error) << std::endl; return false; }
return true;
@ -302,18 +302,18 @@ namespace document_tests {
namespace document_stream_tests {
static simdjson::document::stream parse_many_stream_return(simdjson::document::parser &parser, simdjson::padded_string &str) {
static simdjson::dom::stream parse_many_stream_return(simdjson::dom::parser &parser, simdjson::padded_string &str) {
return parser.parse_many(str);
}
// this is a compilation test
UNUSED static void parse_many_stream_assign() {
simdjson::document::parser parser;
simdjson::dom::parser parser;
simdjson::padded_string str("{}",2);
simdjson::document::stream s1 = parse_many_stream_return(parser, str);
simdjson::dom::stream s1 = parse_many_stream_return(parser, str);
}
static bool parse_json_message_issue467(simdjson::padded_string &json, size_t expectedcount) {
simdjson::document::parser parser;
simdjson::dom::parser parser;
size_t count = 0;
for (auto [doc, error] : parser.parse_many(json)) {
if (error) {
@ -361,7 +361,7 @@ namespace document_stream_tests {
printf(".");
fflush(NULL);
simdjson::padded_string str(data);
simdjson::document::parser parser;
simdjson::dom::parser parser;
size_t count = 0;
for (auto [doc, error] : parser.parse_many(str, batch_size)) {
if (error) {
@ -409,7 +409,7 @@ namespace document_stream_tests {
printf(".");
fflush(NULL);
simdjson::padded_string str(data);
simdjson::document::parser parser;
simdjson::dom::parser parser;
size_t count = 0;
for (auto [doc, error] : parser.parse_many(str, batch_size)) {
if (error) {
@ -448,6 +448,7 @@ namespace document_stream_tests {
namespace parse_api_tests {
using namespace std;
using namespace simdjson;
using namespace simdjson::dom;
const padded_string BASIC_JSON = string("[1,2,3]");
const padded_string BASIC_NDJSON = string("[1,2,3]\n[4,5,6]");
@ -455,7 +456,7 @@ namespace parse_api_tests {
bool parser_parse() {
std::cout << "Running " << __func__ << std::endl;
document::parser parser;
dom::parser parser;
auto [doc, error] = parser.parse(BASIC_JSON);
if (error) { cerr << error << endl; return false; }
if (!doc.is_array()) { cerr << "Document did not parse as an array" << endl; return false; }
@ -463,7 +464,7 @@ namespace parse_api_tests {
}
bool parser_parse_many() {
std::cout << "Running " << __func__ << std::endl;
document::parser parser;
dom::parser parser;
int count = 0;
for (auto [doc, error] : parser.parse_many(BASIC_NDJSON)) {
if (error) { cerr << error << endl; return false; }
@ -475,7 +476,7 @@ namespace parse_api_tests {
}
// bool parser_parse_many_empty() {
// std::cout << "Running " << __func__ << std::endl;
// document::parser parser;
// dom::parser parser;
// int count = 0;
// for (auto [doc, error] : parser.parse_many(EMPTY_NDJSON)) {
// if (error) { cerr << error << endl; return false; }
@ -487,7 +488,7 @@ namespace parse_api_tests {
bool parser_load() {
std::cout << "Running " << __func__ << std::endl;
document::parser parser;
dom::parser parser;
auto [doc, error] = parser.load(JSON_TEST_PATH);
if (error) { cerr << error << endl; return false; }
if (!doc.is_object()) { cerr << "Document did not parse as an object" << endl; return false; }
@ -495,7 +496,7 @@ namespace parse_api_tests {
}
bool parser_load_many() {
std::cout << "Running " << __func__ << std::endl;
document::parser parser;
dom::parser parser;
int count = 0;
for (auto [doc, error] : parser.load_many(NDJSON_TEST_PATH)) {
if (error) { cerr << error << endl; return false; }
@ -510,16 +511,16 @@ namespace parse_api_tests {
bool parser_parse_exception() {
std::cout << "Running " << __func__ << std::endl;
document::parser parser;
document::element doc = parser.parse(BASIC_JSON);
dom::parser parser;
element doc = parser.parse(BASIC_JSON);
if (!doc.is_array()) { cerr << "Document did not parse as an array" << endl; return false; }
return true;
}
bool parser_parse_many_exception() {
std::cout << "Running " << __func__ << std::endl;
document::parser parser;
dom::parser parser;
int count = 0;
for (const document::element doc : parser.parse_many(BASIC_NDJSON)) {
for (const element doc : parser.parse_many(BASIC_NDJSON)) {
if (!doc.is_array()) { cerr << "Document did not parse as an array" << endl; return false; }
count++;
}
@ -529,16 +530,16 @@ namespace parse_api_tests {
bool parser_load_exception() {
std::cout << "Running " << __func__ << std::endl;
document::parser parser;
const document::element doc = parser.load(JSON_TEST_PATH);
dom::parser parser;
const element doc = parser.load(JSON_TEST_PATH);
if (!doc.is_object()) { cerr << "Document did not parse as an object" << endl; return false; }
return true;
}
bool parser_load_many_exception() {
std::cout << "Running " << __func__ << std::endl;
document::parser parser;
dom::parser parser;
int count = 0;
for (const document::element doc : parser.load_many(NDJSON_TEST_PATH)) {
for (const element doc : parser.load_many(NDJSON_TEST_PATH)) {
if (!doc.is_array()) { cerr << "Document did not parse as an array" << endl; return false; }
count++;
}
@ -566,6 +567,7 @@ namespace parse_api_tests {
namespace dom_api_tests {
using namespace std;
using namespace simdjson;
using namespace simdjson::dom;
SIMDJSON_PUSH_DISABLE_WARNINGS
SIMDJSON_DISABLE_DEPRECATED_WARNING
@ -679,7 +681,7 @@ namespace dom_api_tests {
uint64_t expected_value[] = { 1, 2, 3 };
int i = 0;
document::parser parser;
dom::parser parser;
auto [object, error] = parser.parse(json).as_object();
if (error) { cerr << "Error: " << error << endl; return false; }
for (auto [key, value] : object) {
@ -696,7 +698,7 @@ namespace dom_api_tests {
uint64_t expected_value[] = { 1, 10, 100 };
int i=0;
document::parser parser;
dom::parser parser;
auto [array, error] = parser.parse(json).as_array();
if (error) { cerr << "Error: " << error << endl; return false; }
for (auto value : array) {
@ -712,7 +714,7 @@ namespace dom_api_tests {
string json(R"({})");
int i = 0;
document::parser parser;
dom::parser parser;
auto [object, error] = parser.parse(json).as_object();
if (error) { cerr << "Error: " << error << endl; return false; }
for (auto [key, value] : object) {
@ -728,7 +730,7 @@ namespace dom_api_tests {
string json(R"([])");
int i=0;
document::parser parser;
dom::parser parser;
auto [array, error] = parser.parse(json).as_array();
if (error) { cerr << "Error: " << error << endl; return false; }
for (auto value : array) {
@ -742,7 +744,7 @@ namespace dom_api_tests {
bool string_value() {
std::cout << "Running " << __func__ << std::endl;
string json(R"([ "hi", "has backslash\\" ])");
document::parser parser;
dom::parser parser;
auto [array, error] = parser.parse(json).as_array();
if (error) { cerr << "Error: " << error << endl; return false; }
auto val = array.begin();
@ -756,7 +758,7 @@ namespace dom_api_tests {
bool numeric_values() {
std::cout << "Running " << __func__ << std::endl;
string json(R"([ 0, 1, -1, 1.1 ])");
document::parser parser;
dom::parser parser;
auto [array, error] = parser.parse(json).as_array();
if (error) { cerr << "Error: " << error << endl; return false; }
auto val = array.begin();
@ -779,7 +781,7 @@ namespace dom_api_tests {
bool boolean_values() {
std::cout << "Running " << __func__ << std::endl;
string json(R"([ true, false ])");
document::parser parser;
dom::parser parser;
auto [array, error] = parser.parse(json).as_array();
if (error) { cerr << "Error: " << error << endl; return false; }
auto val = array.begin();
@ -793,7 +795,7 @@ namespace dom_api_tests {
bool null_value() {
std::cout << "Running " << __func__ << std::endl;
string json(R"([ null ])");
document::parser parser;
dom::parser parser;
auto [array, error] = parser.parse(json).as_array();
if (error) { cerr << "Error: " << error << endl; return false; }
auto val = array.begin();
@ -804,7 +806,7 @@ namespace dom_api_tests {
bool document_object_index() {
std::cout << "Running " << __func__ << std::endl;
string json(R"({ "a": 1, "b": 2, "c": 3})");
document::parser parser;
dom::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"].first << endl; return false; }
if (doc["b"].as_uint64_t().first != 2) { cerr << "Expected uint64_t(doc[\"b\"]) to be 2, was " << doc["b"].first << endl; return false; }
@ -814,7 +816,7 @@ namespace dom_api_tests {
if (doc["b"].as_uint64_t().first != 2) { cerr << "Expected uint64_t(doc[\"b\"]) to be 2, was " << doc["b"].first << endl; return false; }
if (doc["a"].as_uint64_t().first != 1) { cerr << "Expected uint64_t(doc[\"a\"]) to be 1, was " << doc["a"].first << endl; return false; }
UNUSED document::element val;
UNUSED element val;
// tie(val, error) = doc["d"]; fails with "no viable overloaded '='" on Apple clang version 11.0.0 tie(val, error) = doc["d"];
doc["d"].tie(val, error);
if (error != simdjson::NO_SUCH_FIELD) { cerr << "Expected NO_SUCH_FIELD error for uint64_t(doc[\"d\"]), got " << error << endl; return false; }
@ -824,12 +826,12 @@ namespace dom_api_tests {
bool object_index() {
std::cout << "Running " << __func__ << std::endl;
string json(R"({ "obj": { "a": 1, "b": 2, "c": 3 } })");
document::parser parser;
dom::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;
object obj;
doc.as_object().tie(obj, error); // tie(...) = fails with "no viable overloaded '='" on Apple clang version 11.0.0
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; }
@ -843,7 +845,7 @@ namespace dom_api_tests {
if (obj["b"].as_uint64_t().first != 2) { cerr << "Expected uint64_t(obj[\"b\"]) to be 2, was " << obj["b"].first << endl; return false; }
if (obj["a"].as_uint64_t().first != 1) { cerr << "Expected uint64_t(obj[\"a\"]) to be 1, was " << obj["a"].first << endl; return false; }
UNUSED document::element val;
UNUSED element val;
doc["d"].tie(val, error); // tie(...) = fails with "no viable overloaded '='" on Apple clang version 11.0.0;
if (error != simdjson::NO_SUCH_FIELD) { cerr << "Expected NO_SUCH_FIELD error for uint64_t(obj[\"d\"]), got " << error << endl; return false; }
return true;
@ -852,7 +854,7 @@ namespace dom_api_tests {
bool twitter_count() {
std::cout << "Running " << __func__ << std::endl;
// Prints the number of results in twitter.json
document::parser parser;
dom::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; }
@ -863,11 +865,11 @@ namespace dom_api_tests {
std::cout << "Running " << __func__ << std::endl;
// Print users with a default profile.
set<string_view> default_users;
document::parser parser;
dom::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;
object user;
tweet["user"].as_object().tie(user, error); // tie(...) = fails with "no viable overloaded '='" on Apple clang version 11.0.0;
if (error) { cerr << "Error: " << error << endl; return false; }
bool default_profile;
@ -888,14 +890,14 @@ namespace dom_api_tests {
std::cout << "Running " << __func__ << std::endl;
// Print image names and sizes
set<pair<uint64_t, uint64_t>> image_sizes;
document::parser parser;
dom::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;
object sizes;
image["sizes"].as_object().tie(sizes, error); // tie(...) = fails with "no viable overloaded '='" on Apple clang version 11.0.0;
if (error) { cerr << "Error: " << error << endl; return false; }
for (auto [key, size] : sizes) {
@ -922,8 +924,8 @@ namespace dom_api_tests {
uint64_t expected_value[] = { 1, 2, 3 };
int i = 0;
document::parser parser;
document::element doc = parser.parse(json);
dom::parser parser;
element doc = parser.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++;
@ -938,8 +940,8 @@ namespace dom_api_tests {
uint64_t expected_value[] = { 1, 10, 100 };
int i=0;
document::parser parser;
document::element doc = parser.parse(json);
dom::parser parser;
element doc = parser.parse(json);
for (uint64_t value : doc.as_array()) {
if (value != expected_value[i]) { cerr << "Expected " << expected_value[i] << ", got " << value << endl; return false; }
i++;
@ -951,9 +953,8 @@ namespace dom_api_tests {
bool string_value_exception() {
std::cout << "Running " << __func__ << std::endl;
string json(R"([ "hi", "has backslash\\" ])");
document::parser parser;
document::array array = parser.parse(json).as_array();
auto val = array.begin();
dom::parser parser;
auto val = parser.parse(json).as_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; }
@ -966,9 +967,8 @@ namespace dom_api_tests {
bool numeric_values_exception() {
std::cout << "Running " << __func__ << std::endl;
string json(R"([ 0, 1, -1, 1.1 ])");
document::parser parser;
document::array array = parser.parse(json).as_array();
auto val = array.begin();
dom::parser parser;
auto val = parser.parse(json).as_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; }
@ -988,9 +988,8 @@ namespace dom_api_tests {
bool boolean_values_exception() {
std::cout << "Running " << __func__ << std::endl;
string json(R"([ true, false ])");
document::parser parser;
document::array array = parser.parse(json).as_array();
auto val = array.begin();
dom::parser parser;
auto val = parser.parse(json).as_array().begin();
if (bool(*val) != true) { cerr << "Expected bool(true) to be true, was " << bool(*val) << endl; return false; }
++val;
@ -1001,9 +1000,8 @@ namespace dom_api_tests {
bool null_value_exception() {
std::cout << "Running " << __func__ << std::endl;
string json(R"([ null ])");
document::parser parser;
document::array array = parser.parse(json).as_array();
auto val = array.begin();
dom::parser parser;
auto val = parser.parse(json).as_array().begin();
if (!(*val).is_null()) { cerr << "Expected null to be null!" << endl; return false; }
return true;
@ -1012,8 +1010,8 @@ namespace dom_api_tests {
bool document_object_index_exception() {
std::cout << "Running " << __func__ << std::endl;
string json(R"({ "a": 1, "b": 2, "c": 3})");
document::parser parser;
document::element doc = parser.parse(json);
dom::parser parser;
element doc = parser.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; }
return true;
}
@ -1021,8 +1019,8 @@ namespace dom_api_tests {
bool object_index_exception() {
std::cout << "Running " << __func__ << std::endl;
string json(R"({ "obj": { "a": 1, "b": 2, "c": 3 } })");
document::parser parser;
document::object obj = parser.parse(json)["obj"];
dom::parser parser;
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;
}
@ -1030,8 +1028,8 @@ namespace dom_api_tests {
bool twitter_count_exception() {
std::cout << "Running " << __func__ << std::endl;
// Prints the number of results in twitter.json
document::parser parser;
document::element doc = parser.load(JSON_TEST_PATH);
dom::parser parser;
element doc = parser.load(JSON_TEST_PATH);
uint64_t result_count = doc["search_metadata"]["count"];
if (result_count != 100) { cerr << "Expected twitter.json[metadata_count][count] = 100, got " << result_count << endl; return false; }
return true;
@ -1041,10 +1039,10 @@ namespace dom_api_tests {
std::cout << "Running " << __func__ << std::endl;
// Print users with a default profile.
set<string_view> default_users;
document::parser parser;
document::element doc = parser.load(JSON_TEST_PATH);
for (document::object tweet : doc["statuses"].as_array()) {
document::object user = tweet["user"];
dom::parser parser;
element doc = parser.load(JSON_TEST_PATH);
for (object tweet : doc["statuses"].as_array()) {
object user = tweet["user"];
if (user["default_profile"]) {
default_users.insert(user["screen_name"]);
}
@ -1057,12 +1055,12 @@ namespace dom_api_tests {
std::cout << "Running " << __func__ << std::endl;
// Print image names and sizes
set<pair<uint64_t, uint64_t>> image_sizes;
document::parser parser;
document::element doc = parser.load(JSON_TEST_PATH);
for (document::object tweet : doc["statuses"].as_array()) {
dom::parser parser;
element doc = parser.load(JSON_TEST_PATH);
for (object tweet : doc["statuses"].as_array()) {
auto [media, not_found] = tweet["entities"]["media"];
if (!not_found) {
for (document::object image : media.as_array()) {
for (object image : media.as_array()) {
for (auto [key, size] : image["sizes"].as_object()) {
image_sizes.insert(make_pair(size["w"], size["h"]));
}
@ -1108,8 +1106,9 @@ namespace dom_api_tests {
namespace format_tests {
using namespace simdjson;
using namespace simdjson::dom;
using namespace std;
const padded_string DOCUMENT(string(R"({ "foo" : 1, "bar" : [ 1, 2, 3 ], "baz": { "a": 1, "b": 2, "c": 3 } })"));
const padded_string DOCUMENT = R"({ "foo" : 1, "bar" : [ 1, 2, 3 ], "baz": { "a": 1, "b": 2, "c": 3 } })"_padded;
const string MINIFIED(R"({"foo":1,"bar":[1,2,3],"baz":{"a":1,"b":2,"c":3}})");
bool assert_minified(ostringstream &actual, const std::string &expected=MINIFIED) {
if (actual.str() != expected) {
@ -1123,7 +1122,7 @@ namespace format_tests {
bool print_parser_parse() {
std::cout << "Running " << __func__ << std::endl;
document::parser parser;
dom::parser parser;
auto [doc, error] = parser.parse(DOCUMENT);
if (error) { cerr << error << endl; return false; }
ostringstream s;
@ -1132,7 +1131,7 @@ namespace format_tests {
}
bool print_minify_parser_parse() {
std::cout << "Running " << __func__ << std::endl;
document::parser parser;
dom::parser parser;
auto [doc, error] = parser.parse(DOCUMENT);
if (error) { cerr << error << endl; return false; }
ostringstream s;
@ -1142,7 +1141,7 @@ namespace format_tests {
bool print_element() {
std::cout << "Running " << __func__ << std::endl;
document::parser parser;
dom::parser parser;
auto [value, error] = parser.parse(DOCUMENT)["foo"];
ostringstream s;
s << value;
@ -1150,7 +1149,7 @@ namespace format_tests {
}
bool print_minify_element() {
std::cout << "Running " << __func__ << std::endl;
document::parser parser;
dom::parser parser;
auto [value, error] = parser.parse(DOCUMENT)["foo"];
ostringstream s;
s << minify(value);
@ -1159,7 +1158,7 @@ namespace format_tests {
bool print_array() {
std::cout << "Running " << __func__ << std::endl;
document::parser parser;
dom::parser parser;
auto [value, error] = parser.parse(DOCUMENT)["bar"].as_array();
ostringstream s;
s << value;
@ -1167,7 +1166,7 @@ namespace format_tests {
}
bool print_minify_array() {
std::cout << "Running " << __func__ << std::endl;
document::parser parser;
dom::parser parser;
auto [value, error] = parser.parse(DOCUMENT)["bar"].as_array();
ostringstream s;
s << minify(value);
@ -1176,7 +1175,7 @@ namespace format_tests {
bool print_object() {
std::cout << "Running " << __func__ << std::endl;
document::parser parser;
dom::parser parser;
auto [value, error] = parser.parse(DOCUMENT)["baz"].as_object();
ostringstream s;
s << value;
@ -1184,7 +1183,7 @@ namespace format_tests {
}
bool print_minify_object() {
std::cout << "Running " << __func__ << std::endl;
document::parser parser;
dom::parser parser;
auto [value, error] = parser.parse(DOCUMENT)["baz"].as_object();
ostringstream s;
s << minify(value);
@ -1195,7 +1194,7 @@ namespace format_tests {
bool print_parser_parse_exception() {
std::cout << "Running " << __func__ << std::endl;
document::parser parser;
dom::parser parser;
if (!parser.allocate_capacity(DOCUMENT.length())) { cerr << "Couldn't allocate!" << endl; return false; }
ostringstream s;
s << parser.parse(DOCUMENT);
@ -1203,7 +1202,7 @@ namespace format_tests {
}
bool print_minify_parser_parse_exception() {
std::cout << "Running " << __func__ << std::endl;
document::parser parser;
dom::parser parser;
if (!parser.allocate_capacity(DOCUMENT.length())) { cerr << "Couldn't allocate!" << endl; return false; }
ostringstream s;
s << minify(parser.parse(DOCUMENT));
@ -1212,16 +1211,16 @@ namespace format_tests {
bool print_element_result_exception() {
std::cout << "Running " << __func__ << std::endl;
document::parser parser;
document::element doc = parser.parse(DOCUMENT);
dom::parser parser;
element doc = parser.parse(DOCUMENT);
ostringstream s;
s << doc["foo"];
return assert_minified(s, "1");
}
bool print_minify_element_result_exception() {
std::cout << "Running " << __func__ << std::endl;
document::parser parser;
document::element doc = parser.parse(DOCUMENT);
dom::parser parser;
element doc = parser.parse(DOCUMENT);
ostringstream s;
s << minify(doc["foo"]);
return assert_minified(s, "1");
@ -1229,18 +1228,18 @@ namespace format_tests {
bool print_element_exception() {
std::cout << "Running " << __func__ << std::endl;
document::parser parser;
document::element doc = parser.parse(DOCUMENT);
document::element value = doc["foo"];
dom::parser parser;
element doc = parser.parse(DOCUMENT);
element value = doc["foo"];
ostringstream s;
s << value;
return assert_minified(s, "1");
}
bool print_minify_element_exception() {
std::cout << "Running " << __func__ << std::endl;
document::parser parser;
document::element doc = parser.parse(DOCUMENT);
document::element value = doc["foo"];
dom::parser parser;
element doc = parser.parse(DOCUMENT);
element value = doc["foo"];
ostringstream s;
s << minify(value);
return assert_minified(s, "1");
@ -1248,16 +1247,16 @@ namespace format_tests {
bool print_array_result_exception() {
std::cout << "Running " << __func__ << std::endl;
document::parser parser;
document::element doc = parser.parse(DOCUMENT);
dom::parser parser;
element doc = parser.parse(DOCUMENT);
ostringstream s;
s << doc["bar"].as_array();
return assert_minified(s, "[1,2,3]");
}
bool print_minify_array_result_exception() {
std::cout << "Running " << __func__ << std::endl;
document::parser parser;
document::element doc = parser.parse(DOCUMENT);
dom::parser parser;
element doc = parser.parse(DOCUMENT);
ostringstream s;
s << minify(doc["bar"].as_array());
return assert_minified(s, "[1,2,3]");
@ -1265,16 +1264,16 @@ namespace format_tests {
bool print_object_result_exception() {
std::cout << "Running " << __func__ << std::endl;
document::parser parser;
document::element doc = parser.parse(DOCUMENT);
dom::parser parser;
element doc = parser.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_exception() {
std::cout << "Running " << __func__ << std::endl;
document::parser parser;
document::element doc = parser.parse(DOCUMENT);
dom::parser parser;
element doc = parser.parse(DOCUMENT);
ostringstream s;
s << minify(doc["baz"].as_object());
return assert_minified(s, R"({"a":1,"b":2,"c":3})");
@ -1282,37 +1281,31 @@ namespace format_tests {
bool print_array_exception() {
std::cout << "Running " << __func__ << std::endl;
document::parser parser;
document::element doc = parser.parse(DOCUMENT);
document::array value = doc["bar"];
dom::parser parser;
ostringstream s;
s << value;
s << parser.parse(DOCUMENT)["bar"];
return assert_minified(s, "[1,2,3]");
}
bool print_minify_array_exception() {
std::cout << "Running " << __func__ << std::endl;
document::parser parser;
document::element doc = parser.parse(DOCUMENT);
document::array value = doc["bar"];
dom::parser parser;
ostringstream s;
s << minify(value);
s << minify(parser.parse(DOCUMENT)["bar"]);
return assert_minified(s, "[1,2,3]");
}
bool print_object_exception() {
std::cout << "Running " << __func__ << std::endl;
document::parser parser;
document::element doc = parser.parse(DOCUMENT);
document::object value = doc["baz"];
dom::parser parser;
ostringstream s;
s << value;
s << parser.parse(DOCUMENT)["baz"];
return assert_minified(s, R"({"a":1,"b":2,"c":3})");
}
bool print_minify_object_exception() {
std::cout << "Running " << __func__ << std::endl;
document::parser parser;
document::element doc = parser.parse(DOCUMENT);
document::object value = doc["baz"];
dom::parser parser;
element doc = parser.parse(DOCUMENT);
object value = doc["baz"];
ostringstream s;
s << minify(value);
return assert_minified(s, R"({"a":1,"b":2,"c":3})");

View File

@ -26,14 +26,14 @@ namespace parser_load {
const char * NONEXISTENT_FILE = "this_file_does_not_exit.json";
bool parser_load_capacity() {
TEST_START();
document::parser parser(1); // 1 byte max capacity
dom::parser parser(1); // 1 byte max capacity
auto [doc, error] = parser.load(JSON_TEST_PATH);
ASSERT_ERROR(error, CAPACITY);
TEST_SUCCEED();
}
bool parser_load_many_capacity() {
TEST_START();
document::parser parser(1); // 1 byte max capacity
dom::parser parser(1); // 1 byte max capacity
for (auto [doc, error] : parser.load_many(JSON_TEST_PATH)) {
ASSERT_ERROR(error, CAPACITY);
TEST_SUCCEED();
@ -43,14 +43,14 @@ namespace parser_load {
bool parser_load_nonexistent() {
TEST_START();
document::parser parser;
dom::parser parser;
auto [doc, error] = parser.load(NONEXISTENT_FILE);
ASSERT_ERROR(error, IO_ERROR);
TEST_SUCCEED();
}
bool parser_load_many_nonexistent() {
TEST_START();
document::parser parser;
dom::parser parser;
for (auto [doc, error] : parser.load_many(NONEXISTENT_FILE)) {
ASSERT_ERROR(error, IO_ERROR);
TEST_SUCCEED();
@ -66,14 +66,14 @@ namespace parser_load {
bool parser_load_chain() {
TEST_START();
document::parser parser;
dom::parser parser;
auto [val, error] = parser.load(NONEXISTENT_FILE)["foo"].as_uint64_t();
ASSERT_ERROR(error, IO_ERROR);
TEST_SUCCEED();
}
bool parser_load_many_chain() {
TEST_START();
document::parser parser;
dom::parser parser;
for (auto doc : parser.load_many(NONEXISTENT_FILE)) {
auto [val, error] = doc["foo"].as_uint64_t();
ASSERT_ERROR(error, IO_ERROR);

View File

@ -32,7 +32,7 @@ template <typename T>
static void parse_and_validate(const std::string src, T expected) {
std::cout << "src: " << src << ", ";
const padded_string pstr{src};
simdjson::document::parser parser;
simdjson::dom::parser parser;
bool result;
if constexpr (std::is_same<int64_t, T>::value) {
@ -54,7 +54,7 @@ static void parse_and_validate(const std::string src, T expected) {
static bool parse_and_check_signed(const std::string src) {
std::cout << "src: " << src << ", expecting signed" << std::endl;
const padded_string pstr{src};
simdjson::document::parser parser;
simdjson::dom::parser parser;
auto [value, error] = parser.parse(pstr).as_object()["key"];
if (error) { std::cerr << error << std::endl; abort(); }
return value.is_integer() && value.is_number();
@ -63,7 +63,7 @@ static bool parse_and_check_signed(const std::string src) {
static bool parse_and_check_unsigned(const std::string src) {
std::cout << "src: " << src << ", expecting signed" << std::endl;
const padded_string pstr{src};
simdjson::document::parser parser;
simdjson::dom::parser parser;
auto [value, error] = parser.parse(pstr).as_object()["key"];
if (error) { std::cerr << error << std::endl; abort(); }
return value.is_unsigned_integer() && value.is_number();

View File

@ -69,7 +69,7 @@ bool validate(const char *dirname) {
std::cerr << "Could not load the file " << fullpath << std::endl;
return EXIT_FAILURE;
}
simdjson::document::parser parser;
simdjson::dom::parser parser;
auto [doc, errorcode] = parser.parse(p);
++how_many;
printf("%s\n", errorcode == simdjson::error_code::SUCCESS ? "ok" : "invalid");

View File

@ -178,7 +178,7 @@ bool validate(const char *dirname) {
int_count = 0;
invalid_count = 0;
total_count += float_count + int_count + invalid_count;
simdjson::document::parser parser;
simdjson::dom::parser parser;
auto [doc, err] = parser.parse(p);
bool isok = (err == simdjson::error_code::SUCCESS);
if (int_count + float_count + invalid_count > 0) {

View File

@ -77,7 +77,7 @@ bool validate(const char *dirname) {
/* The actual test*/
auto [json, error] = simdjson::padded_string::load(fullpath);
if (!error) {
simdjson::document::parser parser;
simdjson::dom::parser parser;
++how_many;
for (auto result : parser.parse_many(json)) {

View File

@ -34,7 +34,7 @@ const padded_string TEST_JSON = R"(
bool json_pointer_success_test(const char *json_pointer, std::string_view expected_value) {
std::cout << "Running successful JSON pointer test '" << json_pointer << "' ..." << std::endl;
document::parser parser;
dom::parser parser;
auto [value, error] = parser.parse(TEST_JSON)[json_pointer].as_string();
if (error) { std::cerr << "Unexpected Error: " << error << std::endl; return false; }
ASSERT(value == expected_value);
@ -43,7 +43,7 @@ bool json_pointer_success_test(const char *json_pointer, std::string_view expect
bool json_pointer_success_test(const char *json_pointer) {
std::cout << "Running successful JSON pointer test '" << json_pointer << "' ..." << std::endl;
document::parser parser;
dom::parser parser;
auto [value, error] = parser.parse(TEST_JSON)[json_pointer];
if (error) { std::cerr << "Unexpected Error: " << error << std::endl; return false; }
return true;
@ -52,7 +52,7 @@ bool json_pointer_success_test(const char *json_pointer) {
bool json_pointer_failure_test(const char *json_pointer, error_code expected_failure_test) {
std::cout << "Running invalid JSON pointer test '" << json_pointer << "' ..." << std::endl;
document::parser parser;
dom::parser parser;
auto [value, error] = parser.parse(TEST_JSON)[json_pointer];
ASSERT(error == expected_failure_test);
return true;

View File

@ -7,7 +7,7 @@ void parser_parse_error_code() {
cout << __func__ << endl;
// Allocate a parser big enough for all files
document::parser parser;
dom::parser parser;
// Read files with the parser, one by one
for (padded_string json : { string("[1, 2, 3]"), string("true"), string("[ true, false ]") }) {
@ -24,7 +24,7 @@ void parser_parse_many_error_code() {
// Read files with the parser
auto json = "[1, 2, 3] true [ true, false ]"_padded;
cout << "Parsing " << json.data() << " ..." << endl;
document::parser parser;
dom::parser parser;
for (auto [doc, error] : parser.parse_many(json)) {
if (error) { cerr << "Error: " << error << endl; exit(1); }
cout << doc << endl;
@ -36,7 +36,7 @@ void parser_parse_max_capacity() {
int argc = 2;
padded_string argv[] { string("[1,2,3]"), string("true") };
document::parser parser(1024*1024); // Set max capacity to 1MB
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); }
@ -50,7 +50,7 @@ void parser_parse_fixed_capacity() {
int argc = 2;
padded_string argv[] { string("[1,2,3]"), string("true") };
document::parser parser(0); // This parser is not allowed to auto-allocate
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++) {
@ -67,7 +67,7 @@ void parser_parse_padded_string() {
cout << __func__ << endl;
auto json = "[ 1, 2, 3 ]"_padded;
document::parser parser;
dom::parser parser;
cout << parser.parse(json) << endl;
}
@ -75,7 +75,7 @@ void parser_parse_get_corpus() {
cout << __func__ << endl;
auto json = get_corpus("jsonexamples/small/demo.json");
document::parser parser;
dom::parser parser;
cout << parser.parse(json) << endl;
}
@ -83,7 +83,7 @@ void parser_parse_exception() {
cout << __func__ << endl;
// Allocate a parser big enough for all files
document::parser parser;
dom::parser parser;
// Read files with the parser, one by one
for (padded_string json : { string("[1, 2, 3]"), string("true"), string("[ true, false ]") }) {
@ -98,8 +98,8 @@ void parser_parse_many_exception() {
// Read files with the parser
auto json = "[1, 2, 3] true [ true, false ]"_padded;
cout << "Parsing " << json.data() << " ..." << endl;
document::parser parser;
for (const document::element doc : parser.parse_many(json)) {
dom::parser parser;
for (const dom::element doc : parser.parse_many(json)) {
cout << doc << endl;
}
}

View File

@ -7,7 +7,7 @@ using namespace simdjson;
int main() {
const char *filename = JSON_TEST_PATH;
padded_string p = get_corpus(filename);
document::parser parser;
dom::parser parser;
auto [doc, error] = parser.parse(p);
if(error) {
std::cerr << error << std::endl;

View File

@ -347,7 +347,7 @@ bool validate(const char *dirname) {
good_string = 0;
total_string_length = 0;
empty_string = 0;
simdjson::document::parser parser;
simdjson::dom::parser parser;
auto [doc, err] = parser.parse(p);
bool isok = (err == simdjson::error_code::SUCCESS);
free(big_buffer);

View File

@ -34,7 +34,7 @@ int main(int argc, char *argv[]) {
std::cerr << "warning: ignoring everything after " << argv[optind + 1]
<< std::endl;
}
simdjson::document::parser parser;
simdjson::dom::parser parser;
auto [doc, error] = parser.load(filename); // do the parsing, return false on error
if (error != simdjson::SUCCESS) {
std::cerr << " Parsing failed. Error is '" << simdjson::error_message(error)

View File

@ -19,7 +19,7 @@ int main(int argc, char *argv[]) {
}
const char *filename = argv[1];
simdjson::document::parser parser;
simdjson::dom::parser parser;
auto [doc, error] = parser.load(filename);
if (error) { std::cerr << "Error parsing " << filename << ": " << error << std::endl; }

View File

@ -53,7 +53,7 @@ bool is_ascii(const std::string_view &v) {
return true;
}
void recurse(simdjson::document::element element, stat_t &s, size_t depth) {
void recurse(simdjson::dom::element element, stat_t &s, size_t depth) {
if (depth > s.maximum_depth) {
s.maximum_depth = depth;
}
@ -125,7 +125,7 @@ void recurse(simdjson::document::element element, stat_t &s, size_t depth) {
stat_t simdjson_compute_stats(const simdjson::padded_string &p) {
stat_t s{};
simdjson::document::parser parser;
simdjson::dom::parser parser;
auto [doc, error] = parser.parse(p);
if (error) {
s.valid = false;