From 03746b966b045389f9656787ecbdd8cb84970302 Mon Sep 17 00:00:00 2001 From: John Keiser Date: Sat, 28 Mar 2020 11:43:41 -0700 Subject: [PATCH 1/2] Move document/element/etc. under dom --- README.md | 4 +- amalgamation.sh | 2 +- benchmark/bench_dom_api.cpp | 48 +-- benchmark/bench_parse_call.cpp | 16 +- benchmark/benchfeatures.cpp | 2 +- benchmark/benchmarker.h | 6 +- benchmark/distinctuseridcompetition.cpp | 16 +- benchmark/minifiercompetition.cpp | 2 +- benchmark/parse_stream.cpp | 6 +- benchmark/parseandstatcompetition.cpp | 6 +- benchmark/parsingcompetition.cpp | 4 +- benchmark/statisticalmodel.cpp | 8 +- doc/basics.md | 44 +-- doc/performance.md | 14 +- include/simdjson/common_defs.h | 2 +- include/simdjson/document.h | 450 ++++++++++++---------- include/simdjson/document_stream.h | 23 +- include/simdjson/error.h | 2 +- include/simdjson/implementation.h | 20 +- include/simdjson/inline/document.h | 433 +++++++++++---------- include/simdjson/inline/document_stream.h | 28 +- include/simdjson/jsonparser.h | 44 +-- include/simdjson/padded_string.h | 2 +- include/simdjson/parsedjson.h | 2 +- src/arm64/implementation.h | 10 +- src/arm64/stage1_find_marks.h | 2 +- src/document_parser_callbacks.h | 42 +- src/fallback/implementation.h | 10 +- src/fallback/stage1_find_marks.h | 6 +- src/generic/json_structural_indexer.h | 8 +- src/generic/numberparsing.h | 6 +- src/generic/stage2_build_tape.h | 8 +- src/generic/stage2_streaming_build_tape.h | 4 +- src/haswell/implementation.h | 10 +- src/haswell/stage1_find_marks.h | 2 +- src/implementation.cpp | 8 +- src/westmere/implementation.h | 10 +- src/westmere/stage1_find_marks.h | 2 +- tests/allparserscheckfile.cpp | 2 +- tests/basictests.cpp | 229 ++++++----- tests/errortests.cpp | 12 +- tests/integer_tests.cpp | 6 +- tests/jsoncheck.cpp | 2 +- tests/numberparsingcheck.cpp | 2 +- tests/parse_many_test.cpp | 2 +- tests/pointercheck.cpp | 6 +- tests/readme_examples.cpp | 18 +- tests/singleheadertest.cpp | 2 +- tests/stringparsingcheck.cpp | 2 +- tools/json2json.cpp | 2 +- tools/jsonpointer.cpp | 2 +- tools/jsonstats.cpp | 4 +- 52 files changed, 820 insertions(+), 783 deletions(-) diff --git a/README.md b/README.md index c86eca8ed..f8a4914b1 100644 --- a/README.md +++ b/README.md @@ -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; } ``` diff --git a/amalgamation.sh b/amalgamation.sh index 6146c9a5c..cb6d403c4 100755 --- a/amalgamation.sh +++ b/amalgamation.sh @@ -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; diff --git a/benchmark/bench_dom_api.cpp b/benchmark/bench_dom_api.cpp index 81c04e6f3..5f32a0b8a 100644 --- a/benchmark/bench_dom_api.cpp +++ b/benchmark/bench_dom_api.cpp @@ -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 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> 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 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 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> 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> 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) { diff --git a/benchmark/bench_parse_call.cpp b/benchmark/bench_parse_call.cpp index 2fa5ab801..2f1b702cd 100644 --- a/benchmark/bench_parse_call.cpp +++ b/benchmark/bench_parse_call.cpp @@ -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; } diff --git a/benchmark/benchfeatures.cpp b/benchmark/benchfeatures.cpp index c99a601fa..10bbac654 100644 --- a/benchmark/benchfeatures.cpp +++ b/benchmark/benchfeatures.cpp @@ -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 diff --git a/benchmark/benchmarker.h b/benchmark/benchmarker.h index bd25665ac..aca40ca70 100644 --- a/benchmark/benchmarker.h +++ b/benchmark/benchmarker.h @@ -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; diff --git a/benchmark/distinctuseridcompetition.cpp b/benchmark/distinctuseridcompetition.cpp index a748de7af..7e85d18ea 100644 --- a/benchmark/distinctuseridcompetition.cpp +++ b/benchmark/distinctuseridcompetition.cpp @@ -38,7 +38,7 @@ void print_vec(const std::vector &v) { // clang-format off // simdjson_recurse below come be implemented like so but it is slow: -/*void simdjson_recurse(std::vector & v, simdjson::document::element element) { +/*void simdjson_recurse(std::vector & 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 &v) { // clang-format on -void simdjson_recurse(std::vector & v, simdjson::document::element element) { +void simdjson_recurse(std::vector & 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 & v, simdjson::document::element elem } __attribute__((noinline)) std::vector -simdjson_just_dom(simdjson::document::element doc) { +simdjson_just_dom(simdjson::dom::element doc) { std::vector answer; simdjson_recurse(answer, doc); remove_duplicates(answer); @@ -110,8 +110,8 @@ simdjson_just_dom(simdjson::document::element doc) { __attribute__((noinline)) std::vector simdjson_compute_stats(const simdjson::padded_string &p) { std::vector 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); diff --git a/benchmark/minifiercompetition.cpp b/benchmark/minifiercompetition.cpp index c7b3c9787..25c54017d 100644 --- a/benchmark/minifiercompetition.cpp +++ b/benchmark/minifiercompetition.cpp @@ -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(), diff --git a/benchmark/parse_stream.cpp b/benchmark/parse_stream.cpp index ddc691dae..3153d8e79 100755 --- a/benchmark/parse_stream.cpp +++ b/benchmark/parse_stream.cpp @@ -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(); diff --git a/benchmark/parseandstatcompetition.cpp b/benchmark/parseandstatcompetition.cpp index b4a58be29..50adb92f9 100644 --- a/benchmark/parseandstatcompetition.cpp +++ b/benchmark/parseandstatcompetition.cpp @@ -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; diff --git a/benchmark/parsingcompetition.cpp b/benchmark/parsingcompetition.cpp index 1a1437156..c14da9c3f 100644 --- a/benchmark/parsingcompetition.cpp +++ b/benchmark/parsingcompetition.cpp @@ -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); diff --git a/benchmark/statisticalmodel.cpp b/benchmark/statisticalmodel.cpp index 6c21b092c..69dcfe2ad 100644 --- a/benchmark/statisticalmodel.cpp +++ b/benchmark/statisticalmodel.cpp @@ -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) { diff --git a/doc/basics.md b/doc/basics.md index bce35b3d7..f315109a1 100644 --- a/doc/basics.md +++ b/doc/basics.md @@ -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`, which is a <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` 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. diff --git a/doc/performance.md b/doc/performance.md index 3a2900a23..15e6133d3 100644 --- a/doc/performance.md +++ b/doc/performance.md @@ -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); diff --git a/include/simdjson/common_defs.h b/include/simdjson/common_defs.h index 2d367782b..02b0f0abc 100644 --- a/include/simdjson/common_defs.h +++ b/include/simdjson/common_defs.h @@ -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; diff --git a/include/simdjson/document.h b/include/simdjson/document.h index 814dc2182..b1492594b 100644 --- a/include/simdjson/document.h +++ b/include/simdjson/document.h @@ -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; +template<> struct simdjson_result; +template<> struct simdjson_result; + +template +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 + 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 - friend class minify; + friend class simdjson::minify; + friend class parser; }; // class document -template -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 - 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 - 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; + friend class object; + friend class array; + friend struct simdjson_result; template 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 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; template @@ -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 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; template @@ -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 : public internal::simdjson_result_base { -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 is_null() const noexcept; - inline simdjson_result as_bool() const noexcept; - inline simdjson_result as_string() const noexcept; - inline simdjson_result as_c_str() const noexcept; - inline simdjson_result as_uint64_t() const noexcept; - inline simdjson_result as_int64_t() const noexcept; - inline simdjson_result as_double() const noexcept; - inline simdjson_result as_array() const noexcept; - inline simdjson_result as_object() const noexcept; - - inline simdjson_result operator[](const std::string_view &json_pointer) const noexcept; - inline simdjson_result operator[](const char *json_pointer) const noexcept; - inline simdjson_result at(const std::string_view &json_pointer) const noexcept; - inline simdjson_result at(size_t index) const noexcept; - inline simdjson_result at_key(const std::string_view &key) const noexcept; - inline simdjson_result at_key_case_insensitive(const std::string_view &key) const noexcept; - -#if SIMDJSON_EXCEPTIONS - inline operator bool() const noexcept(false); - 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 : public internal::simdjson_result_base { -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 operator[](const std::string_view &json_pointer) const noexcept; - inline simdjson_result operator[](const char *json_pointer) const noexcept; - inline simdjson_result at(const std::string_view &json_pointer) const noexcept; - inline simdjson_result at(size_t index) const noexcept; - -#if SIMDJSON_EXCEPTIONS - inline 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 : public internal::simdjson_result_base { -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 operator[](const std::string_view &json_pointer) const noexcept; - inline simdjson_result operator[](const char *json_pointer) const noexcept; - inline simdjson_result at(const std::string_view &json_pointer) const noexcept; - inline simdjson_result at_key(const std::string_view &key) const noexcept; - inline simdjson_result at_key_case_insensitive(const std::string_view &key) const noexcept; - -#if SIMDJSON_EXCEPTIONS - inline 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 inline std::ostream& operator<<(std::ostream& out, minify 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 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 &value) noexcept(false) { return out << minify(value); } +inline std::ostream& operator<<(std::ostream& out, const simdjson_result &value) noexcept(false) { return out << minify(value); } /** * Print JSON to an output stream. * @@ -1556,7 +1501,7 @@ inline std::ostream& operator<<(std::ostream& out, const simdjson_result &value) noexcept(false) { return out << minify(value); } +inline std::ostream& operator<<(std::ostream& out, const simdjson_result &value) noexcept(false) { return out << minify(value); } /** * Print JSON to an output stream. * @@ -1568,10 +1513,87 @@ inline std::ostream& operator<<(std::ostream& out, const simdjson_result &value) noexcept(false) { return out << minify(value); } +inline std::ostream& operator<<(std::ostream& out, const simdjson_result &value) noexcept(false) { return out << minify(value); } #endif +/** The result of a JSON navigation that may fail. */ +template<> +struct simdjson_result : public internal::simdjson_result_base { +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 is_null() const noexcept; + inline simdjson_result as_bool() const noexcept; + inline simdjson_result as_string() const noexcept; + inline simdjson_result as_c_str() const noexcept; + inline simdjson_result as_uint64_t() const noexcept; + inline simdjson_result as_int64_t() const noexcept; + inline simdjson_result as_double() const noexcept; + inline simdjson_result as_array() const noexcept; + inline simdjson_result as_object() const noexcept; + + inline simdjson_result operator[](const std::string_view &json_pointer) const noexcept; + inline simdjson_result operator[](const char *json_pointer) const noexcept; + inline simdjson_result at(const std::string_view &json_pointer) const noexcept; + inline simdjson_result at(size_t index) const noexcept; + inline simdjson_result at_key(const std::string_view &key) const noexcept; + inline simdjson_result at_key_case_insensitive(const std::string_view &key) const noexcept; + +#if SIMDJSON_EXCEPTIONS + inline operator bool() const noexcept(false); + 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 : public internal::simdjson_result_base { +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 operator[](const std::string_view &json_pointer) const noexcept; + inline simdjson_result operator[](const char *json_pointer) const noexcept; + inline simdjson_result at(const std::string_view &json_pointer) const noexcept; + inline simdjson_result at(size_t index) const noexcept; + +#if SIMDJSON_EXCEPTIONS + inline 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 : public internal::simdjson_result_base { +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 operator[](const std::string_view &json_pointer) const noexcept; + inline simdjson_result operator[](const char *json_pointer) const noexcept; + inline simdjson_result at(const std::string_view &json_pointer) const noexcept; + inline simdjson_result at_key(const std::string_view &key) const noexcept; + inline simdjson_result at_key_case_insensitive(const std::string_view &key) const noexcept; + +#if SIMDJSON_EXCEPTIONS + inline dom::object::iterator begin() const noexcept(false); + inline dom::object::iterator end() const noexcept(false); +#endif // SIMDJSON_EXCEPTIONS +}; + } // namespace simdjson #endif // SIMDJSON_DOCUMENT_H \ No newline at end of file diff --git a/include/simdjson/document_stream.h b/include/simdjson/document_stream.h index e5281b3d4..91e7c3ff2 100644 --- a/include/simdjson/document_stream.h +++ b/include/simdjson/document_stream.h @@ -4,15 +4,15 @@ #include #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 diff --git a/include/simdjson/error.h b/include/simdjson/error.h index be311287f..69d053f9b 100644 --- a/include/simdjson/error.h +++ b/include/simdjson/error.h @@ -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)); } * diff --git a/include/simdjson/implementation.h b/include/simdjson/implementation.h index 11c933a7f..36bb87864 100644 --- a/include/simdjson/implementation.h +++ b/include/simdjson/implementation.h @@ -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); } diff --git a/include/simdjson/inline/document.h b/include/simdjson/inline/document.h index 349453c15..b8cfc1226 100644 --- a/include/simdjson/inline/document.h +++ b/include/simdjson/inline/document.h @@ -15,193 +15,197 @@ namespace simdjson { // -// simdjson_result inline implementation +// simdjson_result inline implementation // -really_inline simdjson_result::simdjson_result() noexcept - : internal::simdjson_result_base() {} -really_inline simdjson_result::simdjson_result(document::element &&value) noexcept - : internal::simdjson_result_base(std::forward(value)) {} -really_inline simdjson_result::simdjson_result(error_code error) noexcept - : internal::simdjson_result_base(error) {} -inline simdjson_result simdjson_result::is_null() const noexcept { +really_inline simdjson_result::simdjson_result() noexcept + : internal::simdjson_result_base() {} +really_inline simdjson_result::simdjson_result(dom::element &&value) noexcept + : internal::simdjson_result_base(std::forward(value)) {} +really_inline simdjson_result::simdjson_result(error_code error) noexcept + : internal::simdjson_result_base(error) {} +inline simdjson_result simdjson_result::is_null() const noexcept { if (error()) { return error(); } return first.is_null(); } -inline simdjson_result simdjson_result::as_bool() const noexcept { +inline simdjson_result simdjson_result::as_bool() const noexcept { if (error()) { return error(); } return first.as_bool(); } -inline simdjson_result simdjson_result::as_c_str() const noexcept { +inline simdjson_result simdjson_result::as_c_str() const noexcept { if (error()) { return error(); } return first.as_c_str(); } -inline simdjson_result simdjson_result::as_string() const noexcept { +inline simdjson_result simdjson_result::as_string() const noexcept { if (error()) { return error(); } return first.as_string(); } -inline simdjson_result simdjson_result::as_uint64_t() const noexcept { +inline simdjson_result simdjson_result::as_uint64_t() const noexcept { if (error()) { return error(); } return first.as_uint64_t(); } -inline simdjson_result simdjson_result::as_int64_t() const noexcept { +inline simdjson_result simdjson_result::as_int64_t() const noexcept { if (error()) { return error(); } return first.as_int64_t(); } -inline simdjson_result simdjson_result::as_double() const noexcept { +inline simdjson_result simdjson_result::as_double() const noexcept { if (error()) { return error(); } return first.as_double(); } -inline simdjson_result simdjson_result::as_array() const noexcept { +inline simdjson_result simdjson_result::as_array() const noexcept { if (error()) { return error(); } return first.as_array(); } -inline simdjson_result simdjson_result::as_object() const noexcept { +inline simdjson_result simdjson_result::as_object() const noexcept { if (error()) { return error(); } return first.as_object(); } -inline simdjson_result simdjson_result::operator[](const std::string_view &json_pointer) const noexcept { +inline simdjson_result simdjson_result::operator[](const std::string_view &json_pointer) const noexcept { if (error()) { return *this; } return first[json_pointer]; } -inline simdjson_result simdjson_result::operator[](const char *json_pointer) const noexcept { +inline simdjson_result simdjson_result::operator[](const char *json_pointer) const noexcept { if (error()) { return *this; } return first[json_pointer]; } -inline simdjson_result simdjson_result::at(const std::string_view &json_pointer) const noexcept { +inline simdjson_result simdjson_result::at(const std::string_view &json_pointer) const noexcept { if (error()) { return *this; } return first.at(json_pointer); } -inline simdjson_result simdjson_result::at(size_t index) const noexcept { +inline simdjson_result simdjson_result::at(size_t index) const noexcept { if (error()) { return *this; } return first.at(index); } -inline simdjson_result simdjson_result::at_key(const std::string_view &key) const noexcept { +inline simdjson_result simdjson_result::at_key(const std::string_view &key) const noexcept { if (error()) { return *this; } return first.at_key(key); } -inline simdjson_result simdjson_result::at_key_case_insensitive(const std::string_view &key) const noexcept { +inline simdjson_result simdjson_result::at_key_case_insensitive(const std::string_view &key) const noexcept { if (error()) { return *this; } return first.at_key_case_insensitive(key); } #if SIMDJSON_EXCEPTIONS -inline simdjson_result::operator bool() const noexcept(false) { +inline simdjson_result::operator bool() const noexcept(false) { return as_bool(); } -inline simdjson_result::operator const char *() const noexcept(false) { +inline simdjson_result::operator const char *() const noexcept(false) { return as_c_str(); } -inline simdjson_result::operator std::string_view() const noexcept(false) { +inline simdjson_result::operator std::string_view() const noexcept(false) { return as_string(); } -inline simdjson_result::operator uint64_t() const noexcept(false) { +inline simdjson_result::operator uint64_t() const noexcept(false) { return as_uint64_t(); } -inline simdjson_result::operator int64_t() const noexcept(false) { +inline simdjson_result::operator int64_t() const noexcept(false) { return as_int64_t(); } -inline simdjson_result::operator double() const noexcept(false) { +inline simdjson_result::operator double() const noexcept(false) { return as_double(); } -inline simdjson_result::operator document::array() const noexcept(false) { +inline simdjson_result::operator dom::array() const noexcept(false) { return as_array(); } -inline simdjson_result::operator document::object() const noexcept(false) { +inline simdjson_result::operator dom::object() const noexcept(false) { return as_object(); } #endif // -// simdjson_result inline implementation +// simdjson_result inline implementation // -really_inline simdjson_result::simdjson_result() noexcept - : internal::simdjson_result_base() {} -really_inline simdjson_result::simdjson_result(document::array value) noexcept - : internal::simdjson_result_base(std::forward(value)) {} -really_inline simdjson_result::simdjson_result(error_code error) noexcept - : internal::simdjson_result_base(error) {} +really_inline simdjson_result::simdjson_result() noexcept + : internal::simdjson_result_base() {} +really_inline simdjson_result::simdjson_result(dom::array value) noexcept + : internal::simdjson_result_base(std::forward(value)) {} +really_inline simdjson_result::simdjson_result(error_code error) noexcept + : internal::simdjson_result_base(error) {} #if SIMDJSON_EXCEPTIONS -inline document::array::iterator simdjson_result::begin() const noexcept(false) { +inline dom::array::iterator simdjson_result::begin() const noexcept(false) { if (error()) { throw simdjson_error(error()); } return first.begin(); } -inline document::array::iterator simdjson_result::end() const noexcept(false) { +inline dom::array::iterator simdjson_result::end() const noexcept(false) { if (error()) { throw simdjson_error(error()); } return first.end(); } #endif // SIMDJSON_EXCEPTIONS -inline simdjson_result simdjson_result::operator[](const std::string_view &json_pointer) const noexcept { +inline simdjson_result simdjson_result::operator[](const std::string_view &json_pointer) const noexcept { if (error()) { return error(); } return first.at(json_pointer); } -inline simdjson_result simdjson_result::operator[](const char *json_pointer) const noexcept { +inline simdjson_result simdjson_result::operator[](const char *json_pointer) const noexcept { if (error()) { return error(); } return first.at(json_pointer); } -inline simdjson_result simdjson_result::at(const std::string_view &json_pointer) const noexcept { +inline simdjson_result simdjson_result::at(const std::string_view &json_pointer) const noexcept { if (error()) { return error(); } return first.at(json_pointer); } -inline simdjson_result simdjson_result::at(size_t index) const noexcept { +inline simdjson_result simdjson_result::at(size_t index) const noexcept { if (error()) { return error(); } return first.at(index); } // -// simdjson_result inline implementation +// simdjson_result inline implementation // -really_inline simdjson_result::simdjson_result() noexcept - : internal::simdjson_result_base() {} -really_inline simdjson_result::simdjson_result(document::object value) noexcept - : internal::simdjson_result_base(std::forward(value)) {} -really_inline simdjson_result::simdjson_result(error_code error) noexcept - : internal::simdjson_result_base(error) {} +really_inline simdjson_result::simdjson_result() noexcept + : internal::simdjson_result_base() {} +really_inline simdjson_result::simdjson_result(dom::object value) noexcept + : internal::simdjson_result_base(std::forward(value)) {} +really_inline simdjson_result::simdjson_result(error_code error) noexcept + : internal::simdjson_result_base(error) {} -inline simdjson_result simdjson_result::operator[](const std::string_view &json_pointer) const noexcept { +inline simdjson_result simdjson_result::operator[](const std::string_view &json_pointer) const noexcept { if (error()) { return error(); } return first[json_pointer]; } -inline simdjson_result simdjson_result::operator[](const char *json_pointer) const noexcept { +inline simdjson_result simdjson_result::operator[](const char *json_pointer) const noexcept { if (error()) { return error(); } return first[json_pointer]; } -inline simdjson_result simdjson_result::at(const std::string_view &json_pointer) const noexcept { +inline simdjson_result simdjson_result::at(const std::string_view &json_pointer) const noexcept { if (error()) { return error(); } return first.at(json_pointer); } -inline simdjson_result simdjson_result::at_key(const std::string_view &key) const noexcept { +inline simdjson_result simdjson_result::at_key(const std::string_view &key) const noexcept { if (error()) { return error(); } return first.at_key(key); } -inline simdjson_result simdjson_result::at_key_case_insensitive(const std::string_view &key) const noexcept { +inline simdjson_result simdjson_result::at_key_case_insensitive(const std::string_view &key) const noexcept { if (error()) { return error(); } return first.at_key_case_insensitive(key); } #if SIMDJSON_EXCEPTIONS -inline document::object::iterator simdjson_result::begin() const noexcept(false) { +inline dom::object::iterator simdjson_result::begin() const noexcept(false) { if (error()) { throw simdjson_error(error()); } return first.begin(); } -inline document::object::iterator simdjson_result::end() const noexcept(false) { +inline dom::object::iterator simdjson_result::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 document::parser::read_file(const std::string &path) noexcept { +inline simdjson_result 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 document::parser::read_file(const std::string &pa return bytes_read; } -inline simdjson_result document::parser::load(const std::string &path) noexcept { +inline simdjson_result 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::parser::parse(const uint8_t *buf, size_t len, bool realloc_if_needed) noexcept { +inline simdjson_result 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::parser::parse(const uint8_t error = UNINITIALIZED; return doc.root(); } -really_inline simdjson_result document::parser::parse(const char *buf, size_t len, bool realloc_if_needed) noexcept { +really_inline simdjson_result 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::parser::parse(const std::string &s) noexcept { +really_inline simdjson_result parser::parse(const std::string &s) noexcept { return parse(s.data(), s.length(), s.capacity() - s.length() < SIMDJSON_PADDING); } -really_inline simdjson_result document::parser::parse(const padded_string &s) noexcept { +really_inline simdjson_result 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(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 -really_inline T internal::tape_ref::next_tape_value() const noexcept { - static_assert(sizeof(T) == sizeof(uint64_t)); - return *reinterpret_cast(&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(&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::array::at(const std::string_view &json_pointer) const noexcept { +inline simdjson_result 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::array::at(const std::string_ } return child; } -inline simdjson_result document::array::at(size_t index) const noexcept { +inline simdjson_result 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::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::object::operator[](const std::string_view &json_pointer) const noexcept { +inline simdjson_result object::operator[](const std::string_view &json_pointer) const noexcept { return at(json_pointer); } -inline simdjson_result document::object::operator[](const char *json_pointer) const noexcept { +inline simdjson_result object::operator[](const char *json_pointer) const noexcept { return at(json_pointer); } -inline simdjson_result document::object::at(const std::string_view &json_pointer) const noexcept { +inline simdjson_result 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 child; + simdjson_result child; // If there is an escape character in the key, unescape it and then get the child. size_t escape = key.find('~'); @@ -704,7 +668,7 @@ inline simdjson_result document::object::at(const std::string return child; } -inline simdjson_result document::object::at_key(const std::string_view &key) const noexcept { +inline simdjson_result 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::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::object::at_key_case_insensitive(const std::string_view &key) const noexcept { +inline simdjson_result 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::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(&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 document::element::as_bool() const noexcept { +inline simdjson_result element::as_bool() const noexcept { switch (type()) { case internal::tape_type::TRUE_VALUE: return true; @@ -824,7 +788,7 @@ inline simdjson_result document::element::as_bool() const noexcept { return INCORRECT_TYPE; } } -inline simdjson_result document::element::as_c_str() const noexcept { +inline simdjson_result 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 document::element::as_c_str() const noexcep return INCORRECT_TYPE; } } -inline simdjson_result document::element::as_string() const noexcept { +inline simdjson_result element::as_string() const noexcept { switch (type()) { case internal::tape_type::STRING: return get_string_view(); @@ -842,7 +806,7 @@ inline simdjson_result document::element::as_string() const no return INCORRECT_TYPE; } } -inline simdjson_result document::element::as_uint64_t() const noexcept { +inline simdjson_result element::as_uint64_t() const noexcept { switch (type()) { case internal::tape_type::UINT64: return next_tape_value(); @@ -857,7 +821,7 @@ inline simdjson_result document::element::as_uint64_t() const noexcept return INCORRECT_TYPE; } } -inline simdjson_result document::element::as_int64_t() const noexcept { +inline simdjson_result element::as_int64_t() const noexcept { switch (type()) { case internal::tape_type::UINT64: { uint64_t result = next_tape_value(); @@ -873,7 +837,7 @@ inline simdjson_result document::element::as_int64_t() const noexcept { return INCORRECT_TYPE; } } -inline simdjson_result document::element::as_double() const noexcept { +inline simdjson_result element::as_double() const noexcept { switch (type()) { case internal::tape_type::UINT64: return next_tape_value(); @@ -891,7 +855,7 @@ inline simdjson_result document::element::as_double() const noexcept { return INCORRECT_TYPE; } } -inline simdjson_result document::element::as_array() const noexcept { +inline simdjson_result 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::element::as_array() const noex return INCORRECT_TYPE; } } -inline simdjson_result document::element::as_object() const noexcept { +inline simdjson_result 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::element::as_object() const no return INCORRECT_TYPE; } } -inline simdjson_result document::element::operator[](const std::string_view &json_pointer) const noexcept { +inline simdjson_result element::operator[](const std::string_view &json_pointer) const noexcept { return at(json_pointer); } -inline simdjson_result document::element::operator[](const char *json_pointer) const noexcept { +inline simdjson_result element::operator[](const char *json_pointer) const noexcept { return at(json_pointer); } -inline simdjson_result document::element::at(const std::string_view &json_pointer) const noexcept { +inline simdjson_result 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::at(const std::strin return INCORRECT_TYPE; } } -inline simdjson_result document::element::at(size_t index) const noexcept { +inline simdjson_result element::at(size_t index) const noexcept { return as_array().at(index); } -inline simdjson_result document::element::at_key(const std::string_view &key) const noexcept { +inline simdjson_result element::at_key(const std::string_view &key) const noexcept { return as_object().at_key(key); } -inline simdjson_result document::element::at_key_case_insensitive(const std::string_view &key) const noexcept { +inline simdjson_result element::at_key_case_insensitive(const std::string_view &key) const noexcept { 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::print(std::ostream& out) { +inline std::ostream& minify::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::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::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(iter.doc, iter.json_index)); + out << minify(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::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(iter.doc, iter.json_index)); + out << minify(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::print(std::ostream& out) { return out; } template<> -inline std::ostream& minify::print(std::ostream& out) { +inline std::ostream& minify::print(std::ostream& out) { out << '{'; auto pair = value.begin(); auto end = value.end(); if (pair != end) { - out << minify(*pair); + out << minify(*pair); for (++pair; pair != end; ++pair) { - out << "," << minify(*pair); + out << "," << minify(*pair); } } return out << '}'; } template<> -inline std::ostream& minify::print(std::ostream& out) { +inline std::ostream& minify::print(std::ostream& out) { out << '['; - auto element = value.begin(); + auto iter = value.begin(); auto end = value.end(); - if (element != end) { - out << minify(*element); - for (++element; element != end; ++element) { - out << "," << minify(*element); + if (iter != end) { + out << minify(*iter); + for (++iter; iter != end; ++iter) { + out << "," << minify(*iter); } } return out << ']'; } template<> -inline std::ostream& minify::print(std::ostream& out) { +inline std::ostream& minify::print(std::ostream& out) { return out << '"' << internal::escape_json_string(value.key) << "\":" << value.value; } #if SIMDJSON_EXCEPTIONS template<> -inline std::ostream& minify>::print(std::ostream& out) { +inline std::ostream& minify>::print(std::ostream& out) { if (value.error()) { throw simdjson_error(value.error()); } - return out << minify(value.first); + return out << minify(value.first); } template<> -inline std::ostream& minify>::print(std::ostream& out) { +inline std::ostream& minify>::print(std::ostream& out) { if (value.error()) { throw simdjson_error(value.error()); } - return out << minify(value.first); + return out << minify(value.first); } template<> -inline std::ostream& minify>::print(std::ostream& out) { +inline std::ostream& minify>::print(std::ostream& out) { if (value.error()) { throw simdjson_error(value.error()); } - return out << minify(value.first); + return out << minify(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(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 +really_inline T tape_ref::next_tape_value() const noexcept { + static_assert(sizeof(T) == sizeof(uint64_t)); + return *reinterpret_cast(&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(&doc->string_buf[string_buf_index + sizeof(uint32_t)]), + len + ); +} + + +} // namespace simdjson::internal + #endif // SIMDJSON_INLINE_DOCUMENT_H diff --git a/include/simdjson/inline/document_stream.h b/include/simdjson/inline/document_stream.h index 912e38190..9740c0ceb 100644 --- a/include/simdjson/inline/document_stream.h +++ b/include/simdjson/inline/document_stream.h @@ -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::stream::iterator::operator*() noexcept { +really_inline simdjson_result 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 diff --git a/include/simdjson/jsonparser.h b/include/simdjson/jsonparser.h index de4515eb6..cd4a78e4c 100644 --- a/include/simdjson/jsonparser.h +++ b/include/simdjson/jsonparser.h @@ -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 diff --git a/include/simdjson/padded_string.h b/include/simdjson/padded_string.h index 8872460c8..780be3db4 100644 --- a/include/simdjson/padded_string.h +++ b/include/simdjson/padded_string.h @@ -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. */ diff --git a/include/simdjson/parsedjson.h b/include/simdjson/parsedjson.h index 73488242e..464b83749 100644 --- a/include/simdjson/parsedjson.h +++ b/include/simdjson/parsedjson.h @@ -7,7 +7,7 @@ namespace simdjson { -using ParsedJson = document::parser; +using ParsedJson = dom::parser; } // namespace simdjson #endif diff --git a/src/arm64/implementation.h b/src/arm64/implementation.h index a3be4b69e..29d42d29c 100644 --- a/src/arm64/implementation.h +++ b/src/arm64/implementation.h @@ -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 diff --git a/src/arm64/stage1_find_marks.h b/src/arm64/stage1_find_marks.h index b21400b56..d58e30c77 100644 --- a/src/arm64/stage1_find_marks.h +++ b/src/arm64/stage1_find_marks.h @@ -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); } diff --git a/src/document_parser_callbacks.h b/src/document_parser_callbacks.h index 6b5829467..9afc07399 100644 --- a/src/document_parser_callbacks.h +++ b/src/document_parser_callbacks.h @@ -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(static_cast(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 diff --git a/src/fallback/implementation.h b/src/fallback/implementation.h index 372fde7ce..b184120a2 100644 --- a/src/fallback/implementation.h +++ b/src/fallback/implementation.h @@ -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 diff --git a/src/fallback/stage1_find_marks.h b/src/fallback/stage1_find_marks.h index dfc54a9e4..d04e4ed53 100644 --- a/src/fallback/stage1_find_marks.h +++ b/src/fallback/stage1_find_marks.h @@ -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; } diff --git a/src/generic/json_structural_indexer.h b/src/generic/json_structural_indexer.h index d15cb09ad..f49ad2fab 100644 --- a/src/generic/json_structural_indexer.h +++ b/src/generic/json_structural_indexer.h @@ -58,14 +58,14 @@ public: class json_structural_indexer { public: template - 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 really_inline void step(const uint8_t *block, buf_block_reader &reader) noexcept; really_inline void next(simd::simd8x64 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 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 -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 reader(buf, len); diff --git a/src/generic/numberparsing.h b/src/generic/numberparsing.h index 0d659fb67..d0d9196f3 100644 --- a/src/generic/numberparsing.h +++ b/src/generic/numberparsing.h @@ -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(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 diff --git a/src/generic/stage2_build_tape.h b/src/generic/stage2_build_tape.h index 18e29b72b..db0101299 100644 --- a/src/generic/stage2_build_tape.h +++ b/src/generic/stage2_build_tape.h @@ -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); diff --git a/src/generic/stage2_streaming_build_tape.h b/src/generic/stage2_streaming_build_tape.h index 90a193e37..dcd12929e 100755 --- a/src/generic/stage2_streaming_build_tape.h +++ b/src/generic/stage2_streaming_build_tape.h @@ -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); diff --git a/src/haswell/implementation.h b/src/haswell/implementation.h index fb1ff71c4..fa2bda69c 100644 --- a/src/haswell/implementation.h +++ b/src/haswell/implementation.h @@ -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 diff --git a/src/haswell/stage1_find_marks.h b/src/haswell/stage1_find_marks.h index 40fcf6b00..53eb580f3 100644 --- a/src/haswell/stage1_find_marks.h +++ b/src/haswell/stage1_find_marks.h @@ -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); } diff --git a/src/implementation.cpp b/src/implementation.cpp index 9831ee462..35b855c4d 100644 --- a/src/implementation.cpp +++ b/src/implementation.cpp @@ -47,19 +47,19 @@ constexpr const std::initializer_list 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; } diff --git a/src/westmere/implementation.h b/src/westmere/implementation.h index 2a8957f19..478782f39 100644 --- a/src/westmere/implementation.h +++ b/src/westmere/implementation.h @@ -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 diff --git a/src/westmere/stage1_find_marks.h b/src/westmere/stage1_find_marks.h index 1b578d186..e3eb303ff 100644 --- a/src/westmere/stage1_find_marks.h +++ b/src/westmere/stage1_find_marks.h @@ -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); } diff --git a/tests/allparserscheckfile.cpp b/tests/allparserscheckfile.cpp index 942073933..30cec7968 100644 --- a/tests/allparserscheckfile.cpp +++ b/tests/allparserscheckfile.cpp @@ -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; diff --git a/tests/basictests.cpp b/tests/basictests.cpp index 3df408a36..0169f68af 100644 --- a/tests/basictests.cpp +++ b/tests/basictests.cpp @@ -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 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> 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 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> 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})"); diff --git a/tests/errortests.cpp b/tests/errortests.cpp index 9cd013c04..6812d1c82 100644 --- a/tests/errortests.cpp +++ b/tests/errortests.cpp @@ -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); diff --git a/tests/integer_tests.cpp b/tests/integer_tests.cpp index 113f8b945..003801ca3 100644 --- a/tests/integer_tests.cpp +++ b/tests/integer_tests.cpp @@ -32,7 +32,7 @@ template 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::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(); diff --git a/tests/jsoncheck.cpp b/tests/jsoncheck.cpp index a0196f6be..5ab4b06ca 100644 --- a/tests/jsoncheck.cpp +++ b/tests/jsoncheck.cpp @@ -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"); diff --git a/tests/numberparsingcheck.cpp b/tests/numberparsingcheck.cpp index 4c50e54e3..98f313fa4 100644 --- a/tests/numberparsingcheck.cpp +++ b/tests/numberparsingcheck.cpp @@ -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) { diff --git a/tests/parse_many_test.cpp b/tests/parse_many_test.cpp index 80f239cc7..643d76c22 100644 --- a/tests/parse_many_test.cpp +++ b/tests/parse_many_test.cpp @@ -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)) { diff --git a/tests/pointercheck.cpp b/tests/pointercheck.cpp index 74da00876..0c192d741 100644 --- a/tests/pointercheck.cpp +++ b/tests/pointercheck.cpp @@ -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; diff --git a/tests/readme_examples.cpp b/tests/readme_examples.cpp index 24d79da1a..52143f9c7 100644 --- a/tests/readme_examples.cpp +++ b/tests/readme_examples.cpp @@ -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 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; From 62da98aef6a8bb8828579086dfad268bab793714 Mon Sep 17 00:00:00 2001 From: John Keiser Date: Sat, 28 Mar 2020 12:31:05 -0700 Subject: [PATCH 2/2] Rename dom::stream to dom::document_stream --- include/simdjson/document.h | 14 +++++------ include/simdjson/document_stream.h | 28 ++++++++++----------- include/simdjson/inline/document.h | 14 +++++------ include/simdjson/inline/document_stream.h | 30 +++++++++++------------ tests/basictests.cpp | 4 +-- 5 files changed, 45 insertions(+), 45 deletions(-) diff --git a/include/simdjson/document.h b/include/simdjson/document.h index b1492594b..427eed948 100644 --- a/include/simdjson/document.h +++ b/include/simdjson/document.h @@ -17,8 +17,8 @@ class element; class array; class object; class key_value_pair; -class stream; class document; +class document_stream; /** The default batch size for parser.parse_many() and parser.load_many() */ static constexpr size_t DEFAULT_BATCH_SIZE = 1000000; @@ -792,7 +792,7 @@ public: * - CAPACITY if the parser does not have enough capacity and batch_size > max_capacity. * - other json errors if parsing fails. */ - inline stream load_many(const std::string &path, size_t batch_size = DEFAULT_BATCH_SIZE) noexcept; + inline document_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. @@ -991,7 +991,7 @@ public: * - CAPACITY if the parser does not have enough capacity and batch_size > max_capacity. * - other json errors if parsing fails. */ - inline stream parse_many(const uint8_t *buf, size_t len, size_t batch_size = DEFAULT_BATCH_SIZE) noexcept; + inline document_stream parse_many(const uint8_t *buf, size_t len, size_t batch_size = DEFAULT_BATCH_SIZE) noexcept; /** * Parse a buffer containing many JSON documents. @@ -1053,7 +1053,7 @@ public: * - CAPACITY if the parser does not have enough capacity and batch_size > max_capacity. * - other json errors if parsing fails */ - inline stream parse_many(const char *buf, size_t len, size_t batch_size = DEFAULT_BATCH_SIZE) noexcept; + inline document_stream parse_many(const char *buf, size_t len, size_t batch_size = DEFAULT_BATCH_SIZE) noexcept; /** * Parse a buffer containing many JSON documents. @@ -1114,7 +1114,7 @@ public: * - CAPACITY if the parser does not have enough capacity and batch_size > max_capacity. * - other json errors if parsing fails */ - inline stream parse_many(const std::string &s, size_t batch_size = DEFAULT_BATCH_SIZE) noexcept; + inline document_stream parse_many(const std::string &s, size_t batch_size = DEFAULT_BATCH_SIZE) noexcept; /** * Parse a buffer containing many JSON documents. @@ -1170,7 +1170,7 @@ public: * - CAPACITY if the parser does not have enough capacity and batch_size > max_capacity. * - other json errors if parsing fails */ - inline stream parse_many(const padded_string &s, size_t batch_size = DEFAULT_BATCH_SIZE) noexcept; + inline document_stream parse_many(const padded_string &s, size_t batch_size = DEFAULT_BATCH_SIZE) noexcept; // We do not want to allow implicit conversion from C string to std::string. really_inline simdjson_result parse_many(const char *buf, size_t batch_size = DEFAULT_BATCH_SIZE) noexcept = delete; @@ -1380,7 +1380,7 @@ private: inline simdjson_result read_file(const std::string &path) noexcept; friend class parser::Iterator; - friend class stream; + friend class document_stream; }; // class parser } // namespace simdjson::dom diff --git a/include/simdjson/document_stream.h b/include/simdjson/document_stream.h index 91e7c3ff2..926fcfc5d 100644 --- a/include/simdjson/document_stream.h +++ b/include/simdjson/document_stream.h @@ -12,9 +12,9 @@ namespace simdjson::dom { * Produced by parser::parse_many. * */ -class stream { +class document_stream { public: - really_inline ~stream() noexcept; + really_inline ~document_stream() noexcept; /** * An iterator through a forward-only stream of documents. @@ -36,12 +36,12 @@ public: really_inline bool operator!=(const iterator &other) const noexcept; private: - iterator(stream& stream, bool finished) noexcept; - /** The stream parser we're iterating through. */ - stream& _stream; + iterator(document_stream& stream, bool finished) noexcept; + /** The document_stream we're iterating through. */ + document_stream& stream; /** Whether we're finished or not. */ bool finished; - friend class stream; + friend class document_stream; }; /** @@ -55,14 +55,14 @@ public: private: - stream &operator=(const stream &) = delete; // Disallow copying + document_stream &operator=(const document_stream &) = delete; // Disallow copying - stream(stream &other) = delete; // Disallow copying + document_stream(document_stream &other) = delete; // Disallow copying - really_inline stream(dom::parser &parser, const uint8_t *buf, size_t len, size_t batch_size, error_code error = SUCCESS) noexcept; + really_inline document_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. + * Parse the next document found in the buffer previously given to document_stream. * * The content should be a valid JSON document encoded as UTF-8. If there is a * UTF-8 BOM, the caller is responsible for omitting it, UTF-8 BOM are @@ -70,7 +70,7 @@ private: * * You do NOT need to pre-allocate a parser. This function takes care of * pre-allocating a capacity defined by the batch_size defined when creating the - * stream object. + * document_stream object. * * The function returns simdjson::SUCCESS_AND_HAS_MORE (an integer = 1) in case * of success and indicates that the buffer still contains more data to be parsed, @@ -99,13 +99,13 @@ private: inline size_t get_current_buffer_loc() const { return current_buffer_loc; } /** - * Returns the total amount of complete documents parsed by the stream, + * Returns the total amount of complete documents parsed by the document_stream, * in the current buffer, at the given time. */ inline size_t get_n_parsed_docs() const { return n_parsed_docs; } /** - * Returns the total amount of data (in bytes) parsed by the stream, + * Returns the total amount of data (in bytes) parsed by the document_stream, * in the current buffer, at the given time. */ inline size_t get_n_bytes_parsed() const { return n_bytes_parsed; } @@ -136,7 +136,7 @@ private: dom::parser parser_thread; #endif friend class dom::parser; -}; // class stream +}; // class document_stream } // end of namespace simdjson::dom diff --git a/include/simdjson/inline/document.h b/include/simdjson/inline/document.h index b8cfc1226..afea941ed 100644 --- a/include/simdjson/inline/document.h +++ b/include/simdjson/inline/document.h @@ -390,9 +390,9 @@ inline simdjson_result parser::load(const std::string &path) noexcept { return parse(loaded_bytes.get(), len, false); } -inline stream parser::load_many(const std::string &path, size_t batch_size) noexcept { +inline document_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); + return document_stream(*this, (const uint8_t*)loaded_bytes.get(), len, batch_size, code); } inline simdjson_result parser::parse(const uint8_t *buf, size_t len, bool realloc_if_needed) noexcept { @@ -428,16 +428,16 @@ really_inline simdjson_result parser::parse(const padded_string &s) noe return parse(s.data(), s.length(), false); } -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 parser::parse_many(const uint8_t *buf, size_t len, size_t batch_size) noexcept { + return document_stream(*this, buf, len, batch_size); } -inline stream parser::parse_many(const char *buf, size_t len, size_t batch_size) noexcept { +inline document_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 stream parser::parse_many(const std::string &s, size_t batch_size) noexcept { +inline document_stream parser::parse_many(const std::string &s, size_t batch_size) noexcept { return parse_many(s.data(), s.length(), batch_size); } -inline stream parser::parse_many(const padded_string &s, size_t batch_size) noexcept { +inline document_stream parser::parse_many(const padded_string &s, size_t batch_size) noexcept { return parse_many(s.data(), s.length(), batch_size); } diff --git a/include/simdjson/inline/document_stream.h b/include/simdjson/inline/document_stream.h index 9740c0ceb..f0b7e3696 100644 --- a/include/simdjson/inline/document_stream.h +++ b/include/simdjson/inline/document_stream.h @@ -97,7 +97,7 @@ static inline size_t trimmed_length_safe_utf8(const char * c, size_t len) { namespace simdjson::dom { -really_inline stream::stream( +really_inline document_stream::document_stream( dom::parser &_parser, const uint8_t *buf, size_t len, @@ -107,7 +107,7 @@ really_inline stream::stream( if (!error) { error = json_parse(); } } -inline stream::~stream() noexcept { +inline document_stream::~document_stream() noexcept { #ifdef SIMDJSON_THREADS_ENABLED if (stage_1_thread.joinable()) { stage_1_thread.join(); @@ -115,34 +115,34 @@ inline stream::~stream() noexcept { #endif } -really_inline stream::iterator stream::begin() noexcept { +really_inline document_stream::iterator document_stream::begin() noexcept { return iterator(*this, false); } -really_inline stream::iterator stream::end() noexcept { +really_inline document_stream::iterator document_stream::end() noexcept { return iterator(*this, true); } -really_inline stream::iterator::iterator(stream& stream, bool _is_end) noexcept - : _stream{stream}, finished{_is_end} { +really_inline document_stream::iterator::iterator(document_stream& _stream, bool is_end) noexcept + : stream{_stream}, finished{is_end} { } -really_inline simdjson_result stream::iterator::operator*() noexcept { - error_code error = _stream.error == SUCCESS_AND_HAS_MORE ? SUCCESS : _stream.error; +really_inline simdjson_result document_stream::iterator::operator*() noexcept { + error_code error = stream.error == SUCCESS_AND_HAS_MORE ? SUCCESS : stream.error; if (error) { return error; } - return _stream.parser.doc.root(); + return stream.parser.doc.root(); } -really_inline stream::iterator& stream::iterator::operator++() noexcept { - if (_stream.error == SUCCESS_AND_HAS_MORE) { - _stream.error = _stream.json_parse(); +really_inline document_stream::iterator& document_stream::iterator::operator++() noexcept { + if (stream.error == SUCCESS_AND_HAS_MORE) { + stream.error = stream.json_parse(); } else { finished = true; } return *this; } -really_inline bool stream::iterator::operator!=(const stream::iterator &other) const noexcept { +really_inline bool document_stream::iterator::operator!=(const document_stream::iterator &other) const noexcept { return finished != other.finished; } @@ -150,7 +150,7 @@ really_inline bool stream::iterator::operator!=(const stream::iterator &other) c // threaded version of json_parse // todo: simplify this code further -inline error_code stream::json_parse() noexcept { +inline error_code document_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 stream::json_parse() noexcept { #else // SIMDJSON_THREADS_ENABLED // single-threaded version of json_parse -inline error_code stream::json_parse() noexcept { +inline error_code document_stream::json_parse() noexcept { error = parser.ensure_capacity(_batch_size); if (error) { return error; } diff --git a/tests/basictests.cpp b/tests/basictests.cpp index 0169f68af..5dd76ae1f 100644 --- a/tests/basictests.cpp +++ b/tests/basictests.cpp @@ -302,14 +302,14 @@ namespace document_tests { namespace document_stream_tests { - static simdjson::dom::stream parse_many_stream_return(simdjson::dom::parser &parser, simdjson::padded_string &str) { + static simdjson::dom::document_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::dom::parser parser; simdjson::padded_string str("{}",2); - simdjson::dom::stream s1 = parse_many_stream_return(parser, str); + simdjson::dom::document_stream s1 = parse_many_stream_return(parser, str); } static bool parse_json_message_issue467(simdjson::padded_string &json, size_t expectedcount) {