mirror of
https://github.com/simdjson/simdjson
synced 2026-06-08 17:27:07 +00:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0d2455029d | |||
| e94f027310 | |||
| 2b766e4c09 | |||
| a5db75e1a6 | |||
| 4bd66cb891 | |||
| 960a7ebba1 |
+1
-1
@@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.14)
|
||||
project(
|
||||
simdjson
|
||||
# The version number is modified by tools/release.py
|
||||
VERSION 3.0.0
|
||||
VERSION 3.0.1
|
||||
DESCRIPTION "Parsing gigabytes of JSON per second"
|
||||
HOMEPAGE_URL "https://simdjson.org/"
|
||||
LANGUAGES CXX C
|
||||
|
||||
@@ -38,7 +38,7 @@ PROJECT_NAME = simdjson
|
||||
# could be handy for archiving the generated documentation or if some version
|
||||
# control system is used.
|
||||
|
||||
PROJECT_NUMBER = "3.0.0"
|
||||
PROJECT_NUMBER = "3.0.1"
|
||||
|
||||
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
||||
# for a project that appears at the top of each page and should give viewer a
|
||||
|
||||
@@ -51,6 +51,7 @@ private:
|
||||
simdjson_inline void
|
||||
write_raw_string(simdjson::ondemand::raw_json_string rjs);
|
||||
inline void recursive_processor(simdjson::ondemand::value element);
|
||||
inline void recursive_processor_ref(simdjson::ondemand::value& element);
|
||||
|
||||
simdjson::ondemand::parser parser;
|
||||
uint8_t *buff{};
|
||||
@@ -88,7 +89,16 @@ simdjson2msgpack::to_msgpack(const simdjson::padded_string &json,
|
||||
}
|
||||
} else {
|
||||
simdjson::ondemand::value val = doc;
|
||||
#define SIMDJSON_GCC_COMPILER ((__GNUC__) && !(__clang__) && !(__INTEL_COMPILER))
|
||||
#if SIMDJSON_GCC_COMPILER
|
||||
// the GCC compiler does well with by-value passing.
|
||||
// GCC has superior recursive inlining:
|
||||
// https://stackoverflow.com/questions/29186186/why-does-gcc-generate-a-faster-program-than-clang-in-this-recursive-fibonacci-co
|
||||
// https://godbolt.org/z/TeK4doE51
|
||||
recursive_processor(val);
|
||||
#else
|
||||
recursive_processor_ref(val);
|
||||
#endif
|
||||
}
|
||||
if (doc.current_location().error() == simdjson::SUCCESS) {
|
||||
// Example of error detection - this won't be reached on twitter.json in the benchmark.
|
||||
@@ -175,6 +185,53 @@ void simdjson2msgpack::recursive_processor(simdjson::ondemand::value element) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void simdjson2msgpack::recursive_processor_ref(simdjson::ondemand::value& element) {
|
||||
switch (element.type()) {
|
||||
case simdjson::ondemand::json_type::array: {
|
||||
uint32_t counter = 0;
|
||||
write_byte(0xdd);
|
||||
uint8_t *location = skip_uint32();
|
||||
for (auto child : element.get_array()) {
|
||||
counter++;
|
||||
simdjson::ondemand::value v = child.value();
|
||||
recursive_processor_ref(v);
|
||||
}
|
||||
write_uint32_at(counter, location);
|
||||
} break;
|
||||
case simdjson::ondemand::json_type::object: {
|
||||
uint32_t counter = 0;
|
||||
write_byte(0xdf);
|
||||
uint8_t *location = skip_uint32();
|
||||
for (auto field : element.get_object()) {
|
||||
counter++;
|
||||
write_raw_string(field.key());
|
||||
simdjson::ondemand::value v = field.value();
|
||||
recursive_processor_ref(v);
|
||||
}
|
||||
write_uint32_at(counter, location);
|
||||
} break;
|
||||
case simdjson::ondemand::json_type::number:
|
||||
write_double(element.get_double());
|
||||
break;
|
||||
case simdjson::ondemand::json_type::string:
|
||||
write_raw_string(element.get_raw_json_string());
|
||||
break;
|
||||
case simdjson::ondemand::json_type::boolean:
|
||||
write_byte(0xc2 + element.get_bool());
|
||||
break;
|
||||
case simdjson::ondemand::json_type::null:
|
||||
// We check that the value is indeed null
|
||||
// otherwise: an error is thrown.
|
||||
if(element.is_null()) {
|
||||
write_byte(0xc0);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
SIMDJSON_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
struct simdjson_ondemand {
|
||||
using StringType = std::string_view;
|
||||
|
||||
|
||||
+5
-5
@@ -947,11 +947,11 @@ bool parse() {
|
||||
// Iterating through an array of objects
|
||||
auto error = parser.iterate(cars_json).get(doc);
|
||||
if(error) { std::cerr << error << std::endl; return false; }
|
||||
ondemand::array cars;
|
||||
ondemand::array cars; // invalid until the get() succeeds
|
||||
error = doc.get_array().get(cars);
|
||||
|
||||
for (auto car_value : cars) {
|
||||
ondemand::object car;
|
||||
ondemand::object car; // invalid until the get() succeeds
|
||||
error = car_value.get_object().get(car);
|
||||
if(error) { std::cerr << error << std::endl; return false; }
|
||||
|
||||
@@ -992,7 +992,7 @@ For safety, you should only use our ondemand instances (e.g., `ondemand::object`
|
||||
after you have initialized them and checked that there is no error:
|
||||
|
||||
```c++
|
||||
ondemand::object car;
|
||||
ondemand::object car; // invalid until the get() succeeds
|
||||
// the `car` instance should not use used before it is initialized
|
||||
error = car_value.get_object().get(car);
|
||||
if(error) {
|
||||
@@ -1010,7 +1010,7 @@ having to handle exceptions.
|
||||
ondemand::document doc;
|
||||
auto error = parser.iterate(json).get(doc);
|
||||
if(error) { return false; }
|
||||
ondemand::object object;
|
||||
ondemand::object object; // invalid until the get() succeeds
|
||||
error = doc.get_object().get(object);
|
||||
if(error) { return false; }
|
||||
for(auto field : object) {
|
||||
@@ -1137,7 +1137,7 @@ auto json = R"( [[1,2,3], -23.4, {"key": "value"}, true] )"_padded;
|
||||
ondemand::parser parser;
|
||||
auto doc = parser.iterate(json);
|
||||
for (auto val : doc) {
|
||||
ondemand::object obj;
|
||||
ondemand::object obj; // invalid until the get() succeeds
|
||||
auto error = val.get_object().get(obj); // Only get objects
|
||||
if (!error) {
|
||||
std::cout << doc.current_location() << std::endl; // Prints ""key": "value"}, true] "
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
We take our documentation seriously. Please start reading the documentation before you attempt to use simdjson. We hope you will enjoy reading us.
|
||||
|
||||
* Basics: https://github.com/simdjson/simdjson/blob/master/doc/basics.md is an overview of how to use simdjson and its APIs.
|
||||
* parse_many: https://github.com/simdjson/simdjson/blob/master/doc/parse_many.md describes an interface providing features to work with files or streams containing multiple small JSON documents. As fast and convenient as possible.
|
||||
* iterate_many: https://github.com/simdjson/simdjson/blob/master/doc/iterate_many.md describes an interface providing features to work with files or streams containing multiple small JSON documents. As fast and convenient as possible.
|
||||
* Performance: https://github.com/simdjson/simdjson/blob/master/doc/performance.md shows some more advanced scenarios and how to tune for them.
|
||||
|
||||
+9
-9
@@ -47,7 +47,7 @@ dom::element doc = parser.parse("[1,2,3]"_padded); // parse a string, the _padde
|
||||
The parsed document resulting from the `parser.load` and `parser.parse` calls depends on the `parser` instance. Thus the `parser` instance must remain in scope. Furthermore, you must have at most one parsed document in play per `parser` instance.
|
||||
You cannot copy a `parser` instance, you may only move it.
|
||||
|
||||
If you need to keep a document around long term, you can keep or move the parser instance. Note that moving a parser instance, or keeping one in a movable data structure like vector or map, can cause any outstanding `element`, `object` or `array` instances to be invalidated. If you need to store a parser in a movable data structure, you should use a `std::unique_ptr` to avoid this invalidation(e.g., `std::unique_ptr<dom::parser> parser(new dom::parser{})`).
|
||||
If you need to keep a document around long term, you can keep or move the parser instance. Note that moving a parser instance, or keeping one in a movable data structure like vector or map, can cause any outstanding `element`, `object` or `array` instances to be invalidated. The `element`, `object` or `array` instances are mere thin wrappers akin to an `std::vector<int>::iterator`: they are invalid when default constructed, they must be tied to a valid document instance. If you need to store a parser in a movable data structure, you should use a `std::unique_ptr` to avoid this invalidation(e.g., `std::unique_ptr<dom::parser> parser(new dom::parser{})`).
|
||||
|
||||
During the`load` or `parse` calls, neither the input file nor the input string are ever modified. After calling `load` or `parse`, the source (either a file or a string) can be safely discarded. All of the JSON data is stored in the `parser` instance. The parsed document is also immutable in simdjson: you do not modify it by accessing it.
|
||||
|
||||
@@ -167,7 +167,7 @@ While the simdjson library can be used in any project using C++ 11 and above, fi
|
||||
```c++
|
||||
padded_string json = R"( { "foo": 1, "bar": 2 } )"_padded;
|
||||
dom::parser parser;
|
||||
dom::object object;
|
||||
dom::object object; // invalid until the get() succeeds
|
||||
auto error = parser.parse(json).get(object);
|
||||
if (error) { cerr << error << endl; return; }
|
||||
for (auto [key, value] : object) {
|
||||
@@ -181,7 +181,7 @@ For comparison, here is the C++ 11 version of the same code:
|
||||
// C++ 11 version for comparison
|
||||
padded_string json = R"( { "foo": 1, "bar": 2 } )"_padded;
|
||||
dom::parser parser;
|
||||
dom::object object;
|
||||
dom::object object; // invalid until the get() succeeds
|
||||
auto error = parser.parse(json).get(object);
|
||||
if (error) { cerr << error << endl; return; }
|
||||
for (dom::key_value_pair field : object) {
|
||||
@@ -227,7 +227,7 @@ dom::parser parser;
|
||||
dom::element cars = parser.parse(cars_json);
|
||||
cout << cars.at_pointer("/0/tire_pressure/1") << endl; // Prints 39.9
|
||||
for (dom::element car_element : cars) {
|
||||
dom::object car;
|
||||
dom::object car; // invalid until the get() succeeds
|
||||
simdjson::error_code error;
|
||||
if ((error = car_element.get(car))) { std::cerr << error << std::endl; return; }
|
||||
double x = car.at_pointer("/tire_pressure/1");
|
||||
@@ -283,11 +283,11 @@ it selects the key "count" within that object.
|
||||
|
||||
int main(void) {
|
||||
simdjson::dom::parser parser;
|
||||
simdjson::dom::element tweets;
|
||||
simdjson::dom::element tweets; // invalid until the get() succeeds
|
||||
auto error = parser.load("twitter.json").get(tweets);
|
||||
if (error) { std::cerr << error << std::endl; return EXIT_FAILURE; }
|
||||
|
||||
simdjson::dom::element res;
|
||||
simdjson::dom::element res; // invalid until the get() succeeds
|
||||
if ((error = tweets["search_metadata"]["count"].get(res))) {
|
||||
std::cerr << "could not access keys" << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
@@ -311,7 +311,7 @@ Observe how we use the `at` method when querying an index into an array, and not
|
||||
|
||||
int main(void) {
|
||||
simdjson::dom::parser parser;
|
||||
simdjson::dom::element tweets;
|
||||
simdjson::dom::element tweets; // invalid until the get() succeeds
|
||||
auto error = parser.load("twitter.json").get(tweets);
|
||||
if(error) { std::cerr << error << std::endl; return EXIT_FAILURE; }
|
||||
uint64_t identifier;
|
||||
@@ -336,7 +336,7 @@ auto cars_json = R"( [
|
||||
{ "make": "Toyota", "model": "Tercel", "year": 1999, "tire_pressure": [ 29.8, 30.0, 30.2, 30.5 ] }
|
||||
] )"_padded;
|
||||
dom::parser parser;
|
||||
dom::array cars;
|
||||
dom::array cars; // invalid until the get() succeeds
|
||||
auto error = parser.parse(cars_json).get(cars);
|
||||
if (error) { cerr << error << endl; exit(1); }
|
||||
|
||||
@@ -382,7 +382,7 @@ auto abstract_json = R"( [
|
||||
{ "12545" : {"a":11.44, "b":12.78, "c": 11111111} }
|
||||
] )"_padded;
|
||||
dom::parser parser;
|
||||
dom::array array;
|
||||
dom::array array; // invalid until after the next line
|
||||
auto error = parser.parse(abstract_json).get(array);
|
||||
if (error) { cerr << error << endl; exit(1); }
|
||||
// Iterate through an array of objects
|
||||
|
||||
@@ -322,4 +322,11 @@ namespace std {
|
||||
# define simdjson_fallthrough do {} while (0) /* fallthrough */
|
||||
#endif // simdjson_fallthrough
|
||||
|
||||
|
||||
#if SIMDJSON_DEVELOPMENT_CHECKS
|
||||
#define SIMDJSON_DEVELOPMENT_ASSERT(expr) do { assert ((expr)); } while (0)
|
||||
#else
|
||||
#define SIMDJSON_DEVELOPMENT_ASSERT(expr) do { } while (0)
|
||||
#endif
|
||||
|
||||
#endif // SIMDJSON_COMMON_DEFS_H
|
||||
|
||||
@@ -53,18 +53,23 @@ namespace dom {
|
||||
simdjson_inline array::array() noexcept : tape{} {}
|
||||
simdjson_inline array::array(const internal::tape_ref &_tape) noexcept : tape{_tape} {}
|
||||
inline array::iterator array::begin() const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
return internal::tape_ref(tape.doc, tape.json_index + 1);
|
||||
}
|
||||
inline array::iterator array::end() const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
return internal::tape_ref(tape.doc, tape.after_element() - 1);
|
||||
}
|
||||
inline size_t array::size() const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
return tape.scope_count();
|
||||
}
|
||||
inline size_t array::number_of_slots() const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
return tape.matching_brace_index() - tape.json_index;
|
||||
}
|
||||
inline simdjson_result<element> array::at_pointer(std::string_view json_pointer) const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
if(json_pointer.empty()) { // an empty string means that we return the current node
|
||||
return element(this->tape); // copy the current node
|
||||
} else if(json_pointer[0] != '/') { // otherwise there is an error
|
||||
@@ -105,6 +110,7 @@ inline simdjson_result<element> array::at_pointer(std::string_view json_pointer)
|
||||
}
|
||||
|
||||
inline simdjson_result<element> array::at(size_t index) const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
size_t i=0;
|
||||
for (auto element : *this) {
|
||||
if (i == index) { return element; }
|
||||
|
||||
@@ -186,11 +186,13 @@ simdjson_inline element::element() noexcept : tape{} {}
|
||||
simdjson_inline element::element(const internal::tape_ref &_tape) noexcept : tape{_tape} { }
|
||||
|
||||
inline element_type element::type() const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
auto tape_type = tape.tape_ref_type();
|
||||
return tape_type == internal::tape_type::FALSE_VALUE ? element_type::BOOL : static_cast<element_type>(tape_type);
|
||||
}
|
||||
|
||||
inline simdjson_result<bool> element::get_bool() const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
if(tape.is_true()) {
|
||||
return true;
|
||||
} else if(tape.is_false()) {
|
||||
@@ -199,6 +201,7 @@ inline simdjson_result<bool> element::get_bool() const noexcept {
|
||||
return INCORRECT_TYPE;
|
||||
}
|
||||
inline simdjson_result<const char *> element::get_c_str() const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
switch (tape.tape_ref_type()) {
|
||||
case internal::tape_type::STRING: {
|
||||
return tape.get_c_str();
|
||||
@@ -208,6 +211,7 @@ inline simdjson_result<const char *> element::get_c_str() const noexcept {
|
||||
}
|
||||
}
|
||||
inline simdjson_result<size_t> element::get_string_length() const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
switch (tape.tape_ref_type()) {
|
||||
case internal::tape_type::STRING: {
|
||||
return tape.get_string_length();
|
||||
@@ -217,6 +221,7 @@ inline simdjson_result<size_t> element::get_string_length() const noexcept {
|
||||
}
|
||||
}
|
||||
inline simdjson_result<std::string_view> element::get_string() const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
switch (tape.tape_ref_type()) {
|
||||
case internal::tape_type::STRING:
|
||||
return tape.get_string_view();
|
||||
@@ -225,6 +230,7 @@ inline simdjson_result<std::string_view> element::get_string() const noexcept {
|
||||
}
|
||||
}
|
||||
inline simdjson_result<uint64_t> element::get_uint64() const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
if(simdjson_unlikely(!tape.is_uint64())) { // branch rarely taken
|
||||
if(tape.is_int64()) {
|
||||
int64_t result = tape.next_tape_value<int64_t>();
|
||||
@@ -238,6 +244,7 @@ inline simdjson_result<uint64_t> element::get_uint64() const noexcept {
|
||||
return tape.next_tape_value<int64_t>();
|
||||
}
|
||||
inline simdjson_result<int64_t> element::get_int64() const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
if(simdjson_unlikely(!tape.is_int64())) { // branch rarely taken
|
||||
if(tape.is_uint64()) {
|
||||
uint64_t result = tape.next_tape_value<uint64_t>();
|
||||
@@ -252,6 +259,7 @@ inline simdjson_result<int64_t> element::get_int64() const noexcept {
|
||||
return tape.next_tape_value<int64_t>();
|
||||
}
|
||||
inline simdjson_result<double> element::get_double() const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
// Performance considerations:
|
||||
// 1. Querying tape_ref_type() implies doing a shift, it is fast to just do a straight
|
||||
// comparison.
|
||||
@@ -273,6 +281,7 @@ inline simdjson_result<double> element::get_double() const noexcept {
|
||||
return tape.next_tape_value<double>();
|
||||
}
|
||||
inline simdjson_result<array> element::get_array() const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
switch (tape.tape_ref_type()) {
|
||||
case internal::tape_type::START_ARRAY:
|
||||
return array(tape);
|
||||
@@ -281,6 +290,7 @@ inline simdjson_result<array> element::get_array() const noexcept {
|
||||
}
|
||||
}
|
||||
inline simdjson_result<object> element::get_object() const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
switch (tape.tape_ref_type()) {
|
||||
case internal::tape_type::START_OBJECT:
|
||||
return object(tape);
|
||||
@@ -360,6 +370,7 @@ inline simdjson_result<element> element::operator[](const char *key) const noexc
|
||||
}
|
||||
|
||||
inline simdjson_result<element> element::at_pointer(std::string_view json_pointer) const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
switch (tape.tape_ref_type()) {
|
||||
case internal::tape_type::START_OBJECT:
|
||||
return object(tape).at_pointer(json_pointer);
|
||||
@@ -395,6 +406,7 @@ inline simdjson_result<element> element::at_key_case_insensitive(std::string_vie
|
||||
}
|
||||
|
||||
inline bool element::dump_raw_tape(std::ostream &out) const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
return tape.doc->dump_raw_tape(out);
|
||||
}
|
||||
|
||||
|
||||
@@ -65,12 +65,15 @@ namespace dom {
|
||||
simdjson_inline object::object() noexcept : tape{} {}
|
||||
simdjson_inline object::object(const internal::tape_ref &_tape) noexcept : tape{_tape} { }
|
||||
inline object::iterator object::begin() const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
return internal::tape_ref(tape.doc, tape.json_index + 1);
|
||||
}
|
||||
inline object::iterator object::end() const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
return internal::tape_ref(tape.doc, tape.after_element() - 1);
|
||||
}
|
||||
inline size_t object::size() const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
return tape.scope_count();
|
||||
}
|
||||
|
||||
@@ -81,6 +84,7 @@ inline simdjson_result<element> object::operator[](const char *key) const noexce
|
||||
return at_key(key);
|
||||
}
|
||||
inline simdjson_result<element> object::at_pointer(std::string_view json_pointer) const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
if(json_pointer.empty()) { // an empty string means that we return the current node
|
||||
return element(this->tape); // copy the current node
|
||||
} else if(json_pointer[0] != '/') { // otherwise there is an error
|
||||
|
||||
@@ -148,6 +148,9 @@ simdjson_inline simdjson_result<element> parser::parse(const std::string &s) & n
|
||||
simdjson_inline simdjson_result<element> parser::parse(const padded_string &s) & noexcept {
|
||||
return parse(s.data(), s.length(), false);
|
||||
}
|
||||
simdjson_inline simdjson_result<element> parser::parse(const padded_string_view &v) & noexcept {
|
||||
return parse(v.data(), v.length(), false);
|
||||
}
|
||||
|
||||
inline simdjson_result<document_stream> parser::parse_many(const uint8_t *buf, size_t len, size_t batch_size) noexcept {
|
||||
if(batch_size < MINIMAL_BATCH_SIZE) { batch_size = MINIMAL_BATCH_SIZE; }
|
||||
|
||||
@@ -199,6 +199,9 @@ public:
|
||||
/** @overload parse(const uint8_t *buf, size_t len, bool realloc_if_needed) */
|
||||
simdjson_inline simdjson_result<element> parse(const padded_string &s) & noexcept;
|
||||
simdjson_inline simdjson_result<element> parse(const padded_string &s) && =delete;
|
||||
/** @overload parse(const uint8_t *buf, size_t len, bool realloc_if_needed) */
|
||||
simdjson_inline simdjson_result<element> parse(const padded_string_view &v) & noexcept;
|
||||
simdjson_inline simdjson_result<element> parse(const padded_string_view &v) && =delete;
|
||||
|
||||
/** @private We do not want to allow implicit conversion from C string to std::string. */
|
||||
simdjson_inline simdjson_result<element> parse(const char *buf) noexcept = delete;
|
||||
|
||||
@@ -17,7 +17,9 @@ simdjson_inline tape_ref::tape_ref(const dom::document *_doc, size_t _json_index
|
||||
simdjson_inline bool tape_ref::is_document_root() const noexcept {
|
||||
return json_index == 1; // should we ever change the structure of the tape, this should get updated.
|
||||
}
|
||||
|
||||
simdjson_inline bool tape_ref::usable() const noexcept {
|
||||
return doc != nullptr; // when the document pointer is null, this tape_ref is uninitialized (should not be accessed).
|
||||
}
|
||||
// Some value types have a specific on-tape word value. It can be faster
|
||||
// to check the type by doing a word-to-word comparison instead of extracting the
|
||||
// most significant 8 bits.
|
||||
|
||||
@@ -38,6 +38,7 @@ public:
|
||||
simdjson_inline const char * get_c_str() const noexcept;
|
||||
inline std::string_view get_string_view() const noexcept;
|
||||
simdjson_inline bool is_document_root() const noexcept;
|
||||
simdjson_inline bool usable() const noexcept;
|
||||
|
||||
/** The document this element references. */
|
||||
const dom::document *doc;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#define SIMDJSON_SIMDJSON_VERSION_H
|
||||
|
||||
/** The version of simdjson being used (major.minor.revision) */
|
||||
#define SIMDJSON_VERSION 3.0.0
|
||||
#define SIMDJSON_VERSION 3.0.1
|
||||
|
||||
namespace simdjson {
|
||||
enum {
|
||||
@@ -19,7 +19,7 @@ enum {
|
||||
/**
|
||||
* The revision (major.minor.REVISION) of simdjson being used.
|
||||
*/
|
||||
SIMDJSON_VERSION_REVISION = 0
|
||||
SIMDJSON_VERSION_REVISION = 1
|
||||
};
|
||||
} // namespace simdjson
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* auto-generated on 2022-10-06 11:47:40 -0400. Do not edit! */
|
||||
/* auto-generated on 2022-11-23 10:31:42 -0500. Do not edit! */
|
||||
/* begin file src/simdjson.cpp */
|
||||
#include "simdjson.h"
|
||||
|
||||
@@ -868,9 +868,9 @@ inline char *format_buffer(char *buf, int len, int decimal_exponent,
|
||||
|
||||
std::memset(buf + k, '0', static_cast<size_t>(n) - static_cast<size_t>(k));
|
||||
// Make it look like a floating-point number (#362, #378)
|
||||
// buf[n + 0] = '.';
|
||||
// buf[n + 1] = '0';
|
||||
return buf + (static_cast<size_t>(n));
|
||||
buf[n + 0] = '.';
|
||||
buf[n + 1] = '0';
|
||||
return buf + (static_cast<size_t>(n)) + 2;
|
||||
}
|
||||
|
||||
if (0 < n && n <= max_exp) {
|
||||
@@ -933,10 +933,8 @@ char *to_chars(char *first, const char *last, double value) {
|
||||
{
|
||||
*first++ = '0';
|
||||
// Make it look like a floating-point number (#362, #378)
|
||||
if(negative) {
|
||||
*first++ = '.';
|
||||
*first++ = '0';
|
||||
}
|
||||
*first++ = '.';
|
||||
*first++ = '0';
|
||||
return first;
|
||||
}
|
||||
// Compute v = buffer * 10^decimal_exponent.
|
||||
|
||||
+42
-4
@@ -1,4 +1,4 @@
|
||||
/* auto-generated on 2022-10-06 11:47:40 -0400. Do not edit! */
|
||||
/* auto-generated on 2022-11-23 10:31:42 -0500. Do not edit! */
|
||||
/* begin file include/simdjson.h */
|
||||
#ifndef SIMDJSON_H
|
||||
#define SIMDJSON_H
|
||||
@@ -43,7 +43,7 @@
|
||||
#define SIMDJSON_SIMDJSON_VERSION_H
|
||||
|
||||
/** The version of simdjson being used (major.minor.revision) */
|
||||
#define SIMDJSON_VERSION 3.0.0
|
||||
#define SIMDJSON_VERSION 3.0.1
|
||||
|
||||
namespace simdjson {
|
||||
enum {
|
||||
@@ -58,7 +58,7 @@ enum {
|
||||
/**
|
||||
* The revision (major.minor.REVISION) of simdjson being used.
|
||||
*/
|
||||
SIMDJSON_VERSION_REVISION = 0
|
||||
SIMDJSON_VERSION_REVISION = 1
|
||||
};
|
||||
} // namespace simdjson
|
||||
|
||||
@@ -2253,6 +2253,13 @@ namespace std {
|
||||
# define simdjson_fallthrough do {} while (0) /* fallthrough */
|
||||
#endif // simdjson_fallthrough
|
||||
|
||||
|
||||
#if SIMDJSON_DEVELOPMENT_CHECKS
|
||||
#define SIMDJSON_DEVELOPMENT_ASSERT(expr) do { assert ((expr)); } while (0)
|
||||
#else
|
||||
#define SIMDJSON_DEVELOPMENT_ASSERT(expr) do { } while (0)
|
||||
#endif
|
||||
|
||||
#endif // SIMDJSON_COMMON_DEFS_H
|
||||
/* end file include/simdjson/common_defs.h */
|
||||
|
||||
@@ -4048,6 +4055,7 @@ public:
|
||||
simdjson_inline const char * get_c_str() const noexcept;
|
||||
inline std::string_view get_string_view() const noexcept;
|
||||
simdjson_inline bool is_document_root() const noexcept;
|
||||
simdjson_inline bool usable() const noexcept;
|
||||
|
||||
/** The document this element references. */
|
||||
const dom::document *doc;
|
||||
@@ -4533,6 +4541,9 @@ public:
|
||||
/** @overload parse(const uint8_t *buf, size_t len, bool realloc_if_needed) */
|
||||
simdjson_inline simdjson_result<element> parse(const padded_string &s) & noexcept;
|
||||
simdjson_inline simdjson_result<element> parse(const padded_string &s) && =delete;
|
||||
/** @overload parse(const uint8_t *buf, size_t len, bool realloc_if_needed) */
|
||||
simdjson_inline simdjson_result<element> parse(const padded_string_view &v) & noexcept;
|
||||
simdjson_inline simdjson_result<element> parse(const padded_string_view &v) && =delete;
|
||||
|
||||
/** @private We do not want to allow implicit conversion from C string to std::string. */
|
||||
simdjson_inline simdjson_result<element> parse(const char *buf) noexcept = delete;
|
||||
@@ -6844,18 +6855,23 @@ namespace dom {
|
||||
simdjson_inline array::array() noexcept : tape{} {}
|
||||
simdjson_inline array::array(const internal::tape_ref &_tape) noexcept : tape{_tape} {}
|
||||
inline array::iterator array::begin() const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
return internal::tape_ref(tape.doc, tape.json_index + 1);
|
||||
}
|
||||
inline array::iterator array::end() const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
return internal::tape_ref(tape.doc, tape.after_element() - 1);
|
||||
}
|
||||
inline size_t array::size() const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
return tape.scope_count();
|
||||
}
|
||||
inline size_t array::number_of_slots() const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
return tape.matching_brace_index() - tape.json_index;
|
||||
}
|
||||
inline simdjson_result<element> array::at_pointer(std::string_view json_pointer) const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
if(json_pointer.empty()) { // an empty string means that we return the current node
|
||||
return element(this->tape); // copy the current node
|
||||
} else if(json_pointer[0] != '/') { // otherwise there is an error
|
||||
@@ -6896,6 +6912,7 @@ inline simdjson_result<element> array::at_pointer(std::string_view json_pointer)
|
||||
}
|
||||
|
||||
inline simdjson_result<element> array::at(size_t index) const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
size_t i=0;
|
||||
for (auto element : *this) {
|
||||
if (i == index) { return element; }
|
||||
@@ -7130,11 +7147,13 @@ simdjson_inline element::element() noexcept : tape{} {}
|
||||
simdjson_inline element::element(const internal::tape_ref &_tape) noexcept : tape{_tape} { }
|
||||
|
||||
inline element_type element::type() const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
auto tape_type = tape.tape_ref_type();
|
||||
return tape_type == internal::tape_type::FALSE_VALUE ? element_type::BOOL : static_cast<element_type>(tape_type);
|
||||
}
|
||||
|
||||
inline simdjson_result<bool> element::get_bool() const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
if(tape.is_true()) {
|
||||
return true;
|
||||
} else if(tape.is_false()) {
|
||||
@@ -7143,6 +7162,7 @@ inline simdjson_result<bool> element::get_bool() const noexcept {
|
||||
return INCORRECT_TYPE;
|
||||
}
|
||||
inline simdjson_result<const char *> element::get_c_str() const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
switch (tape.tape_ref_type()) {
|
||||
case internal::tape_type::STRING: {
|
||||
return tape.get_c_str();
|
||||
@@ -7152,6 +7172,7 @@ inline simdjson_result<const char *> element::get_c_str() const noexcept {
|
||||
}
|
||||
}
|
||||
inline simdjson_result<size_t> element::get_string_length() const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
switch (tape.tape_ref_type()) {
|
||||
case internal::tape_type::STRING: {
|
||||
return tape.get_string_length();
|
||||
@@ -7161,6 +7182,7 @@ inline simdjson_result<size_t> element::get_string_length() const noexcept {
|
||||
}
|
||||
}
|
||||
inline simdjson_result<std::string_view> element::get_string() const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
switch (tape.tape_ref_type()) {
|
||||
case internal::tape_type::STRING:
|
||||
return tape.get_string_view();
|
||||
@@ -7169,6 +7191,7 @@ inline simdjson_result<std::string_view> element::get_string() const noexcept {
|
||||
}
|
||||
}
|
||||
inline simdjson_result<uint64_t> element::get_uint64() const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
if(simdjson_unlikely(!tape.is_uint64())) { // branch rarely taken
|
||||
if(tape.is_int64()) {
|
||||
int64_t result = tape.next_tape_value<int64_t>();
|
||||
@@ -7182,6 +7205,7 @@ inline simdjson_result<uint64_t> element::get_uint64() const noexcept {
|
||||
return tape.next_tape_value<int64_t>();
|
||||
}
|
||||
inline simdjson_result<int64_t> element::get_int64() const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
if(simdjson_unlikely(!tape.is_int64())) { // branch rarely taken
|
||||
if(tape.is_uint64()) {
|
||||
uint64_t result = tape.next_tape_value<uint64_t>();
|
||||
@@ -7196,6 +7220,7 @@ inline simdjson_result<int64_t> element::get_int64() const noexcept {
|
||||
return tape.next_tape_value<int64_t>();
|
||||
}
|
||||
inline simdjson_result<double> element::get_double() const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
// Performance considerations:
|
||||
// 1. Querying tape_ref_type() implies doing a shift, it is fast to just do a straight
|
||||
// comparison.
|
||||
@@ -7217,6 +7242,7 @@ inline simdjson_result<double> element::get_double() const noexcept {
|
||||
return tape.next_tape_value<double>();
|
||||
}
|
||||
inline simdjson_result<array> element::get_array() const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
switch (tape.tape_ref_type()) {
|
||||
case internal::tape_type::START_ARRAY:
|
||||
return array(tape);
|
||||
@@ -7225,6 +7251,7 @@ inline simdjson_result<array> element::get_array() const noexcept {
|
||||
}
|
||||
}
|
||||
inline simdjson_result<object> element::get_object() const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
switch (tape.tape_ref_type()) {
|
||||
case internal::tape_type::START_OBJECT:
|
||||
return object(tape);
|
||||
@@ -7304,6 +7331,7 @@ inline simdjson_result<element> element::operator[](const char *key) const noexc
|
||||
}
|
||||
|
||||
inline simdjson_result<element> element::at_pointer(std::string_view json_pointer) const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
switch (tape.tape_ref_type()) {
|
||||
case internal::tape_type::START_OBJECT:
|
||||
return object(tape).at_pointer(json_pointer);
|
||||
@@ -7339,6 +7367,7 @@ inline simdjson_result<element> element::at_key_case_insensitive(std::string_vie
|
||||
}
|
||||
|
||||
inline bool element::dump_raw_tape(std::ostream &out) const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
return tape.doc->dump_raw_tape(out);
|
||||
}
|
||||
|
||||
@@ -7946,12 +7975,15 @@ namespace dom {
|
||||
simdjson_inline object::object() noexcept : tape{} {}
|
||||
simdjson_inline object::object(const internal::tape_ref &_tape) noexcept : tape{_tape} { }
|
||||
inline object::iterator object::begin() const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
return internal::tape_ref(tape.doc, tape.json_index + 1);
|
||||
}
|
||||
inline object::iterator object::end() const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
return internal::tape_ref(tape.doc, tape.after_element() - 1);
|
||||
}
|
||||
inline size_t object::size() const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
return tape.scope_count();
|
||||
}
|
||||
|
||||
@@ -7962,6 +7994,7 @@ inline simdjson_result<element> object::operator[](const char *key) const noexce
|
||||
return at_key(key);
|
||||
}
|
||||
inline simdjson_result<element> object::at_pointer(std::string_view json_pointer) const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
if(json_pointer.empty()) { // an empty string means that we return the current node
|
||||
return element(this->tape); // copy the current node
|
||||
} else if(json_pointer[0] != '/') { // otherwise there is an error
|
||||
@@ -8767,6 +8800,9 @@ simdjson_inline simdjson_result<element> parser::parse(const std::string &s) & n
|
||||
simdjson_inline simdjson_result<element> parser::parse(const padded_string &s) & noexcept {
|
||||
return parse(s.data(), s.length(), false);
|
||||
}
|
||||
simdjson_inline simdjson_result<element> parser::parse(const padded_string_view &v) & noexcept {
|
||||
return parse(v.data(), v.length(), false);
|
||||
}
|
||||
|
||||
inline simdjson_result<document_stream> parser::parse_many(const uint8_t *buf, size_t len, size_t batch_size) noexcept {
|
||||
if(batch_size < MINIMAL_BATCH_SIZE) { batch_size = MINIMAL_BATCH_SIZE; }
|
||||
@@ -8873,7 +8909,9 @@ simdjson_inline tape_ref::tape_ref(const dom::document *_doc, size_t _json_index
|
||||
simdjson_inline bool tape_ref::is_document_root() const noexcept {
|
||||
return json_index == 1; // should we ever change the structure of the tape, this should get updated.
|
||||
}
|
||||
|
||||
simdjson_inline bool tape_ref::usable() const noexcept {
|
||||
return doc != nullptr; // when the document pointer is null, this tape_ref is uninitialized (should not be accessed).
|
||||
}
|
||||
// Some value types have a specific on-tape word value. It can be faster
|
||||
// to check the type by doing a word-to-word comparison instead of extracting the
|
||||
// most significant 8 bits.
|
||||
|
||||
+5
-7
@@ -860,9 +860,9 @@ inline char *format_buffer(char *buf, int len, int decimal_exponent,
|
||||
|
||||
std::memset(buf + k, '0', static_cast<size_t>(n) - static_cast<size_t>(k));
|
||||
// Make it look like a floating-point number (#362, #378)
|
||||
// buf[n + 0] = '.';
|
||||
// buf[n + 1] = '0';
|
||||
return buf + (static_cast<size_t>(n));
|
||||
buf[n + 0] = '.';
|
||||
buf[n + 1] = '0';
|
||||
return buf + (static_cast<size_t>(n)) + 2;
|
||||
}
|
||||
|
||||
if (0 < n && n <= max_exp) {
|
||||
@@ -925,10 +925,8 @@ char *to_chars(char *first, const char *last, double value) {
|
||||
{
|
||||
*first++ = '0';
|
||||
// Make it look like a floating-point number (#362, #378)
|
||||
if(negative) {
|
||||
*first++ = '.';
|
||||
*first++ = '0';
|
||||
}
|
||||
*first++ = '.';
|
||||
*first++ = '0';
|
||||
return first;
|
||||
}
|
||||
// Compute v = buffer * 10^decimal_exponent.
|
||||
|
||||
Reference in New Issue
Block a user