mirror of
https://github.com/simdjson/simdjson
synced 2026-06-08 17:27:07 +00:00
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3cb79e6977 | |||
| c5e21a2469 | |||
| 13aee51011 | |||
| 53fca1b5e6 | |||
| 7dad9fca0f | |||
| b249d7c76c | |||
| 4060f64232 | |||
| 5b2f7d3374 |
+17
-7
@@ -41,7 +41,7 @@ commands:
|
||||
- run: ARCHFLAGS=-march=haswell make test # this breaks runtime dispatch, but see https://github.com/lemire/simdjson/issues/444... this is a code robustness test
|
||||
- run: make clean
|
||||
- run: EXTRAFLAGS=-DSIMDJSON_NO_COMPUTED_GOTO=true make test # this should run tests with computed gotos disabled
|
||||
make_test_strict:
|
||||
make_test_strict: # this version fails when a warning is detected.
|
||||
steps:
|
||||
- checkout
|
||||
- run: EXTRAFLAGS=-Werror make
|
||||
@@ -50,15 +50,25 @@ commands:
|
||||
- run: EXTRAFLAGS=-Werror make quicktests
|
||||
- run: make clean
|
||||
|
||||
cmake_test:
|
||||
cmake_simple_test: # this version just builds and test
|
||||
steps:
|
||||
- run: apt-get update -qq
|
||||
- run: apt-get install -y cmake
|
||||
- checkout
|
||||
- run: cmake $CMAKE_TEST_FLAGS
|
||||
- run: make
|
||||
- run: make all
|
||||
- run: make test
|
||||
|
||||
cmake_test: # this version builds, install, test and then verifyi from the installation
|
||||
steps:
|
||||
- run: apt-get update -qq
|
||||
- run: apt-get install -y cmake
|
||||
- checkout
|
||||
- run: cmake $CMAKE_TEST_FLAGS -DCMAKE_INSTALL_PREFIX:PATH=destination
|
||||
- run: make all install
|
||||
- run: make test
|
||||
- run: echo -e '#include <simdjson.h>\nint main(int argc,char**argv) {simdjson::dom::parser parser;simdjson::dom::element tweets = parser.load(argv[1]); }' > tmp.cpp && c++ -Idestination/include -Ldestination/lib -std=c++17 -Wl,-rpath,destination/lib -o linkandrun tmp.cpp -lsimdjson && ./linkandrun jsonexamples/twitter.json # we not only want cmake to build and run tests, but we want also a succesful installation from which we can build, link and run programs
|
||||
|
||||
jobs:
|
||||
|
||||
gcc-avx-unthreaded:
|
||||
@@ -114,7 +124,7 @@ jobs:
|
||||
description: Build, run tests and check performance on GCC 7 and AVX 2 with a cmake sanitize build
|
||||
executor: gcc7
|
||||
environment: { CMAKE_TEST_FLAGS: -DSIMDJSON_BUILD_STATIC=OFF -DSIMDJSON_SANITIZE=ON }
|
||||
steps: [ cmake_test ]
|
||||
steps: [ cmake_simple_test ]
|
||||
|
||||
gcc-sse:
|
||||
description: Build, run tests and check performance on GCC 7 and SSE 4.2
|
||||
@@ -135,7 +145,7 @@ jobs:
|
||||
description: Build, run tests and check performance on GCC 7 and SSE 4.2 with a cmake sanitize build
|
||||
executor: gcc7
|
||||
environment: { CMAKE_TEST_FLAGS: -DSIMDJSON_BUILD_STATIC=OFF -DSIMDJSON_SANITIZE=ON }
|
||||
steps: [ cmake_test ]
|
||||
steps: [ cmake_simple_test ]
|
||||
|
||||
clang-avx:
|
||||
description: Build, run tests and check performance on clang 6 and AVX 2
|
||||
@@ -160,7 +170,7 @@ jobs:
|
||||
description: Build, run tests and check performance on clang 6 and AVX 2 with a cmake sanitize build
|
||||
executor: clang6
|
||||
environment: { CMAKE_TEST_FLAGS: -DSIMDJSON_BUILD_STATIC=OFF -DSIMDJSON_SANITIZE=ON }
|
||||
steps: [ init_clang6, cmake_test ]
|
||||
steps: [ init_clang6, cmake_simple_test ]
|
||||
|
||||
clang-sse:
|
||||
description: Build, run tests and check performance on Clang 6 and SSE 4.2
|
||||
@@ -181,7 +191,7 @@ jobs:
|
||||
description: Build, run tests and check performance on Clang 6 and SSE 4.2 with a cmake sanitize build
|
||||
executor: clang6
|
||||
environment: { CMAKE_TEST_FLAGS: -DSIMDJSON_BUILD_STATIC=OFF -DSIMDJSON_SANITIZE=ON }
|
||||
steps: [ init_clang6, cmake_test ]
|
||||
steps: [ init_clang6, cmake_simple_test ]
|
||||
|
||||
workflows:
|
||||
version: 2.1
|
||||
|
||||
+7
-3
@@ -27,9 +27,9 @@ set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||
set(SIMDJSON_LIB_NAME simdjson)
|
||||
set(PROJECT_VERSION_MAJOR 0)
|
||||
set(PROJECT_VERSION_MINOR 3)
|
||||
set(PROJECT_VERSION_PATCH 0)
|
||||
set(SIMDJSON_LIB_VERSION "0.3.0" CACHE STRING "simdjson library version")
|
||||
set(SIMDJSON_LIB_SOVERSION "0" CACHE STRING "simdjson library soversion")
|
||||
set(PROJECT_VERSION_PATCH 1)
|
||||
set(SIMDJSON_LIB_VERSION "0.3.1" CACHE STRING "simdjson library version")
|
||||
set(SIMDJSON_LIB_SOVERSION "1" CACHE STRING "simdjson library soversion")
|
||||
|
||||
option(SIMDJSON_IMPLEMENTATION_HASWELL "Include the haswell implementation" ON)
|
||||
option(SIMDJSON_IMPLEMENTATION_WESTMERE "Include the westmere implementation" ON)
|
||||
@@ -50,7 +50,11 @@ set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/tools/cmake")
|
||||
find_package(CTargets)
|
||||
find_package(Options)
|
||||
|
||||
# We used to have install(DIRECTORY include/${SIMDJSON_LIB_NAME} DESTINATION include)
|
||||
# alone.
|
||||
# However, this fails because we also need the root level simdjson.h file.
|
||||
install(DIRECTORY include/${SIMDJSON_LIB_NAME} DESTINATION include)
|
||||
install(FILES include/${SIMDJSON_LIB_NAME}.h DESTINATION include)
|
||||
set (TEST_DATA_DIR "${CMAKE_CURRENT_SOURCE_DIR}/jsonchecker/")
|
||||
set (BENCHMARK_DATA_DIR "${CMAKE_CURRENT_SOURCE_DIR}/jsonexamples/")
|
||||
add_definitions(-DSIMDJSON_TEST_DATA_DIR="${TEST_DATA_DIR}")
|
||||
|
||||
+63
-6
@@ -8,15 +8,16 @@ An overview of what you need to know to use simdjson, with examples.
|
||||
* [Using the Parsed JSON](#using-the-parsed-json)
|
||||
* [JSON Pointer](#json-pointer)
|
||||
* [Error Handling](#error-handling)
|
||||
* [Error Handling Example](#error-handling-example)
|
||||
* [Exceptions](#exceptions)
|
||||
* [Error Handling Example](#error-handling-example)
|
||||
* [Exceptions](#exceptions)
|
||||
* [Tree Walking and JSON Element Types](#tree-walking-and-json-element-types)
|
||||
* [Newline-Delimited JSON (ndjson) and JSON lines](#newline-delimited-json-ndjson-and-json-lines)
|
||||
* [Thread Safety](#thread-safety)
|
||||
|
||||
Including simdjson
|
||||
------------------
|
||||
|
||||
To include simdjson, copy [simdjson.h](singleheader/simdjson.h) and [simdjson.cpp](singleheader/simdjson.cpp)
|
||||
To include simdjson, copy [simdjson.h](/singleheader/simdjson.h) and [simdjson.cpp](/singleheader/simdjson.cpp)
|
||||
into your project. Then include it in your project with:
|
||||
|
||||
```c++
|
||||
@@ -67,6 +68,8 @@ Once you have an element, you can navigate it with idiomatic C++ iterators, oper
|
||||
first element.
|
||||
> Note that array[0] does not compile, because implementing [] gives the impression indexing is a
|
||||
> O(1) operation, which it is not presently in simdjson.
|
||||
* **Checking an Element Type:** You can check an element's type with `element.type()`. It
|
||||
returns an `element_type`.
|
||||
|
||||
Here are some examples of all of the above:
|
||||
|
||||
@@ -152,9 +155,9 @@ This is how the example in "Using the Parsed JSON" could be written using only e
|
||||
|
||||
```c++
|
||||
auto cars_json = R"( [
|
||||
{ "make": "Toyota", "model": "Camry", "year": 2018, "tire_pressure": [ 40.1, 39.9, 37.7, 40.4 ] },
|
||||
{ "make": "Kia", "model": "Soul", "year": 2012, "tire_pressure": [ 30.1, 31.0, 28.6, 28.7 ] },
|
||||
{ "make": "Toyota", "model": "Tercel", "year": 1999, "tire_pressure": [ 29.8, 30.0, 30.2, 30.5 ] }
|
||||
{ "make": "Toyota", "model": "Camry", "year": 2018, "tire_pressure": [ 40.1, 39.9, 37.7, 40.4 ] },
|
||||
{ "make": "Kia", "model": "Soul", "year": 2012, "tire_pressure": [ 30.1, 31.0, 28.6, 28.7 ] },
|
||||
{ "make": "Toyota", "model": "Tercel", "year": 1999, "tire_pressure": [ 29.8, 30.0, 30.2, 30.5 ] }
|
||||
] )"_padded;
|
||||
dom::parser parser;
|
||||
auto [cars, error] = parser.parse(cars_json).get<dom::array>();
|
||||
@@ -210,6 +213,60 @@ dom::element doc = parser.parse(json); // Throws an exception if there was an er
|
||||
When used this way, a `simdjson_error` exception will be thrown if an error occurs, preventing the
|
||||
program from continuing if there was an error.
|
||||
|
||||
Tree Walking and JSON Element Types
|
||||
-----------------------------------
|
||||
|
||||
Sometimes you don't necessarily have a document with a known type, and are trying to generically
|
||||
inspect or walk over JSON elements. To do that, you can use iterators and the type() method. For
|
||||
example, here's a quick and dirty recursive function that verbosely prints the JSON document as JSON
|
||||
(* ignoring nuances like trailing commas and escaping strings, for brevity's sake):
|
||||
|
||||
```c++
|
||||
void print_json(dom::element element) {
|
||||
switch (element.type()) {
|
||||
case dom::element_type::ARRAY:
|
||||
cout << "[";
|
||||
for (dom::element child : dom::array(element)) {
|
||||
print_json(child);
|
||||
cout << ",";
|
||||
}
|
||||
cout << "]";
|
||||
break;
|
||||
case dom::element_type::OBJECT:
|
||||
cout << "{";
|
||||
for (dom::key_value_pair field : dom::object(element)) {
|
||||
cout << "\"" << field.key << "\": ";
|
||||
print_json(field.value);
|
||||
}
|
||||
cout << "}";
|
||||
break;
|
||||
case dom::element_type::INT64:
|
||||
cout << int64_t(element) << endl;
|
||||
break;
|
||||
case dom::element_type::UINT64:
|
||||
cout << uint64_t(element) << endl;
|
||||
break;
|
||||
case dom::element_type::DOUBLE:
|
||||
cout << double(element) << endl;
|
||||
break;
|
||||
case dom::element_type::STRING:
|
||||
cout << std::string_view(element) << endl;
|
||||
break;
|
||||
case dom::element_type::BOOL:
|
||||
cout << bool(element) << endl;
|
||||
break;
|
||||
case dom::element_type::NULL_VALUE:
|
||||
cout << "null" << endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void basics_treewalk_1() {
|
||||
dom::parser parser;
|
||||
print_json(parser.load("twitter.json"));
|
||||
}
|
||||
```
|
||||
|
||||
Newline-Delimited JSON (ndjson) and JSON lines
|
||||
----------------------------------------------
|
||||
|
||||
|
||||
+86
-37
@@ -41,50 +41,65 @@ namespace simdjson::internal {
|
||||
using namespace simdjson::dom;
|
||||
|
||||
constexpr const uint64_t JSON_VALUE_MASK = 0x00FFFFFFFFFFFFFF;
|
||||
enum class tape_type;
|
||||
class tape_ref;
|
||||
/**
|
||||
* The possible types in the tape. Internal only.
|
||||
*/
|
||||
enum class tape_type {
|
||||
ROOT = 'r',
|
||||
START_ARRAY = '[',
|
||||
START_OBJECT = '{',
|
||||
END_ARRAY = ']',
|
||||
END_OBJECT = '}',
|
||||
STRING = '"',
|
||||
INT64 = 'l',
|
||||
UINT64 = 'u',
|
||||
DOUBLE = 'd',
|
||||
TRUE_VALUE = 't',
|
||||
FALSE_VALUE = 'f',
|
||||
NULL_VALUE = 'n'
|
||||
};
|
||||
|
||||
/**
|
||||
* A reference to an element on the tape. Internal only.
|
||||
*/
|
||||
class tape_ref {
|
||||
public:
|
||||
really_inline tape_ref() noexcept;
|
||||
really_inline tape_ref(const document *doc, size_t json_index) noexcept;
|
||||
inline size_t after_element() const noexcept;
|
||||
really_inline tape_type type() const noexcept;
|
||||
really_inline uint64_t tape_value() const noexcept;
|
||||
template<typename T>
|
||||
really_inline T next_tape_value() const noexcept;
|
||||
inline std::string_view get_string_view() const noexcept;
|
||||
/**
|
||||
* The 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'
|
||||
};
|
||||
|
||||
/** The document this element references. */
|
||||
const document *doc;
|
||||
/**
|
||||
* 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 tape_ref_type() const noexcept;
|
||||
really_inline uint64_t tape_value() const noexcept;
|
||||
template<typename T>
|
||||
really_inline T next_tape_value() const noexcept;
|
||||
inline std::string_view get_string_view() const noexcept;
|
||||
|
||||
/** The document this element references. */
|
||||
const document *doc;
|
||||
|
||||
/** The index of this element on `doc.tape[]` */
|
||||
size_t json_index;
|
||||
};
|
||||
|
||||
/** The index of this element on `doc.tape[]` */
|
||||
size_t json_index;
|
||||
};
|
||||
} // namespace simdjson::internal
|
||||
|
||||
namespace simdjson::dom {
|
||||
|
||||
/**
|
||||
* The actual concrete type of a JSON element
|
||||
* This is the type it is most easily cast to with get<>.
|
||||
*/
|
||||
enum class element_type {
|
||||
ARRAY, ///< dom::array
|
||||
OBJECT, ///< dom::object
|
||||
INT64, ///< int64_t
|
||||
UINT64, ///< uint64_t: any integer that fits in uint64_t but *not* int64_t
|
||||
DOUBLE, ///< double: Any number with a "." or "e" that fits in double.
|
||||
STRING, ///< std::string_view
|
||||
BOOL, ///< bool
|
||||
NULL_VALUE ///< null
|
||||
};
|
||||
|
||||
/**
|
||||
* JSON array.
|
||||
*/
|
||||
@@ -367,6 +382,9 @@ public:
|
||||
/** Create a new, invalid element. */
|
||||
really_inline element() noexcept;
|
||||
|
||||
/** The type of this element. */
|
||||
really_inline element_type type() const noexcept;
|
||||
|
||||
/** Whether this element is a json `null`. */
|
||||
really_inline bool is_null() const noexcept;
|
||||
|
||||
@@ -1121,6 +1139,36 @@ inline std::ostream& operator<<(std::ostream& out, const object &value) { return
|
||||
*/
|
||||
inline std::ostream& operator<<(std::ostream& out, const key_value_pair &value) { return out << minify(value); }
|
||||
|
||||
/**
|
||||
* Print element type to an output stream.
|
||||
*
|
||||
* @param out The output stream.
|
||||
* @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, element_type type) {
|
||||
switch (type) {
|
||||
case element_type::ARRAY:
|
||||
return out << "array";
|
||||
case element_type::OBJECT:
|
||||
return out << "object";
|
||||
case element_type::INT64:
|
||||
return out << "int64_t";
|
||||
case element_type::UINT64:
|
||||
return out << "uint64_t";
|
||||
case element_type::DOUBLE:
|
||||
return out << "double";
|
||||
case element_type::STRING:
|
||||
return out << "string";
|
||||
case element_type::BOOL:
|
||||
return out << "bool";
|
||||
case element_type::NULL_VALUE:
|
||||
return out << "null";
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
@@ -1172,6 +1220,7 @@ public:
|
||||
really_inline simdjson_result(dom::element &&value) noexcept; ///< @private
|
||||
really_inline simdjson_result(error_code error) noexcept; ///< @private
|
||||
|
||||
inline simdjson_result<dom::element_type> type() const noexcept;
|
||||
inline simdjson_result<bool> is_null() const noexcept;
|
||||
template<typename T>
|
||||
inline simdjson_result<bool> is() const noexcept;
|
||||
|
||||
@@ -23,6 +23,10 @@ really_inline simdjson_result<dom::element>::simdjson_result(dom::element &&valu
|
||||
: internal::simdjson_result_base<dom::element>(std::forward<dom::element>(value)) {}
|
||||
really_inline simdjson_result<dom::element>::simdjson_result(error_code error) noexcept
|
||||
: internal::simdjson_result_base<dom::element>(error) {}
|
||||
inline simdjson_result<dom::element_type> simdjson_result<dom::element>::type() const noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first.type();
|
||||
}
|
||||
inline simdjson_result<bool> simdjson_result<dom::element>::is_null() const noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first.is_null();
|
||||
@@ -715,13 +719,39 @@ inline key_value_pair::key_value_pair(const std::string_view &_key, element _val
|
||||
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) { }
|
||||
|
||||
inline element_type element::type() const noexcept {
|
||||
switch (tape_ref_type()) {
|
||||
case internal::tape_type::START_ARRAY:
|
||||
return element_type::ARRAY;
|
||||
case internal::tape_type::START_OBJECT:
|
||||
return element_type::OBJECT;
|
||||
case internal::tape_type::INT64:
|
||||
return element_type::INT64;
|
||||
case internal::tape_type::UINT64:
|
||||
return element_type::UINT64;
|
||||
case internal::tape_type::DOUBLE:
|
||||
return element_type::DOUBLE;
|
||||
case internal::tape_type::STRING:
|
||||
return element_type::STRING;
|
||||
case internal::tape_type::TRUE_VALUE:
|
||||
case internal::tape_type::FALSE_VALUE:
|
||||
return element_type::BOOL;
|
||||
case internal::tape_type::NULL_VALUE:
|
||||
return element_type::NULL_VALUE;
|
||||
case internal::tape_type::ROOT:
|
||||
case internal::tape_type::END_ARRAY:
|
||||
case internal::tape_type::END_OBJECT:
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
really_inline bool element::is_null() const noexcept {
|
||||
return type() == internal::tape_type::NULL_VALUE;
|
||||
return tape_ref_type() == internal::tape_type::NULL_VALUE;
|
||||
}
|
||||
|
||||
template<>
|
||||
inline simdjson_result<bool> element::get<bool>() const noexcept {
|
||||
switch (type()) {
|
||||
switch (tape_ref_type()) {
|
||||
case internal::tape_type::TRUE_VALUE:
|
||||
return true;
|
||||
case internal::tape_type::FALSE_VALUE:
|
||||
@@ -732,7 +762,7 @@ inline simdjson_result<bool> element::get<bool>() const noexcept {
|
||||
}
|
||||
template<>
|
||||
inline simdjson_result<const char *> element::get<const char *>() const noexcept {
|
||||
switch (type()) {
|
||||
switch (tape_ref_type()) {
|
||||
case internal::tape_type::STRING: {
|
||||
size_t string_buf_index = tape_value();
|
||||
return reinterpret_cast<const char *>(&doc->string_buf[string_buf_index + sizeof(uint32_t)]);
|
||||
@@ -743,7 +773,7 @@ inline simdjson_result<const char *> element::get<const char *>() const noexcept
|
||||
}
|
||||
template<>
|
||||
inline simdjson_result<std::string_view> element::get<std::string_view>() const noexcept {
|
||||
switch (type()) {
|
||||
switch (tape_ref_type()) {
|
||||
case internal::tape_type::STRING:
|
||||
return get_string_view();
|
||||
default:
|
||||
@@ -752,7 +782,7 @@ inline simdjson_result<std::string_view> element::get<std::string_view>() const
|
||||
}
|
||||
template<>
|
||||
inline simdjson_result<uint64_t> element::get<uint64_t>() const noexcept {
|
||||
switch (type()) {
|
||||
switch (tape_ref_type()) {
|
||||
case internal::tape_type::UINT64:
|
||||
return next_tape_value<uint64_t>();
|
||||
case internal::tape_type::INT64: {
|
||||
@@ -768,11 +798,11 @@ inline simdjson_result<uint64_t> element::get<uint64_t>() const noexcept {
|
||||
}
|
||||
template<>
|
||||
inline simdjson_result<int64_t> element::get<int64_t>() const noexcept {
|
||||
switch (type()) {
|
||||
switch (tape_ref_type()) {
|
||||
case internal::tape_type::UINT64: {
|
||||
uint64_t result = next_tape_value<uint64_t>();
|
||||
// Wrapping max in parens to handle Windows issue: https://stackoverflow.com/questions/11544073/how-do-i-deal-with-the-max-macro-in-windows-h-colliding-with-max-in-std
|
||||
if (result > (std::numeric_limits<uint64_t>::max)()) {
|
||||
if (result > (std::numeric_limits<int64_t>::max)()) {
|
||||
return NUMBER_OUT_OF_RANGE;
|
||||
}
|
||||
return static_cast<int64_t>(result);
|
||||
@@ -785,7 +815,7 @@ inline simdjson_result<int64_t> element::get<int64_t>() const noexcept {
|
||||
}
|
||||
template<>
|
||||
inline simdjson_result<double> element::get<double>() const noexcept {
|
||||
switch (type()) {
|
||||
switch (tape_ref_type()) {
|
||||
case internal::tape_type::UINT64:
|
||||
return next_tape_value<uint64_t>();
|
||||
case internal::tape_type::INT64: {
|
||||
@@ -804,7 +834,7 @@ inline simdjson_result<double> element::get<double>() const noexcept {
|
||||
}
|
||||
template<>
|
||||
inline simdjson_result<array> element::get<array>() const noexcept {
|
||||
switch (type()) {
|
||||
switch (tape_ref_type()) {
|
||||
case internal::tape_type::START_ARRAY:
|
||||
return array(doc, json_index);
|
||||
default:
|
||||
@@ -813,7 +843,7 @@ inline simdjson_result<array> element::get<array>() const noexcept {
|
||||
}
|
||||
template<>
|
||||
inline simdjson_result<object> element::get<object>() const noexcept {
|
||||
switch (type()) {
|
||||
switch (tape_ref_type()) {
|
||||
case internal::tape_type::START_OBJECT:
|
||||
return object(doc, json_index);
|
||||
default:
|
||||
@@ -838,10 +868,10 @@ inline element::operator double() const noexcept(false) { return get<double>();
|
||||
inline element::operator array() const noexcept(false) { return get<array>(); }
|
||||
inline element::operator object() const noexcept(false) { return get<object>(); }
|
||||
|
||||
inline dom::array::iterator dom::element::begin() const noexcept(false) {
|
||||
inline array::iterator element::begin() const noexcept(false) {
|
||||
return get<array>().begin();
|
||||
}
|
||||
inline dom::array::iterator dom::element::end() const noexcept(false) {
|
||||
inline array::iterator element::end() const noexcept(false) {
|
||||
return get<array>().end();
|
||||
}
|
||||
|
||||
@@ -854,7 +884,7 @@ inline simdjson_result<element> element::operator[](const char *key) const noexc
|
||||
return at_key(key);
|
||||
}
|
||||
inline simdjson_result<element> element::at(const std::string_view &json_pointer) const noexcept {
|
||||
switch (type()) {
|
||||
switch (tape_ref_type()) {
|
||||
case internal::tape_type::START_OBJECT:
|
||||
return object(doc, json_index).at(json_pointer);
|
||||
case internal::tape_type::START_ARRAY:
|
||||
@@ -905,7 +935,7 @@ inline std::ostream& minify<dom::element>::print(std::ostream& out) {
|
||||
out << '"' << internal::escape_json_string(iter.get_string_view()) << "\":";
|
||||
iter.json_index++;
|
||||
}
|
||||
switch (iter.type()) {
|
||||
switch (iter.tape_ref_type()) {
|
||||
|
||||
// Arrays
|
||||
case tape_type::START_ARRAY: {
|
||||
@@ -923,7 +953,7 @@ inline std::ostream& minify<dom::element>::print(std::ostream& out) {
|
||||
iter.json_index++;
|
||||
|
||||
// Handle empty [] (we don't want to come back around and print commas)
|
||||
if (iter.type() == tape_type::END_ARRAY) {
|
||||
if (iter.tape_ref_type() == tape_type::END_ARRAY) {
|
||||
out << ']';
|
||||
depth--;
|
||||
break;
|
||||
@@ -950,7 +980,7 @@ inline std::ostream& minify<dom::element>::print(std::ostream& out) {
|
||||
iter.json_index++;
|
||||
|
||||
// Handle empty {} (we don't want to come back around and print commas)
|
||||
if (iter.type() == tape_type::END_OBJECT) {
|
||||
if (iter.tape_ref_type() == tape_type::END_OBJECT) {
|
||||
out << '}';
|
||||
depth--;
|
||||
break;
|
||||
@@ -997,8 +1027,8 @@ inline std::ostream& minify<dom::element>::print(std::ostream& out) {
|
||||
after_value = true;
|
||||
|
||||
// Handle multiple ends in a row
|
||||
while (depth != 0 && (iter.type() == tape_type::END_ARRAY || iter.type() == tape_type::END_OBJECT)) {
|
||||
out << char(iter.type());
|
||||
while (depth != 0 && (iter.tape_ref_type() == tape_type::END_ARRAY || iter.tape_ref_type() == tape_type::END_OBJECT)) {
|
||||
out << char(iter.tape_ref_type());
|
||||
depth--;
|
||||
iter.json_index++;
|
||||
}
|
||||
@@ -1070,7 +1100,7 @@ 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()) {
|
||||
switch (tape_ref_type()) {
|
||||
case tape_type::START_ARRAY:
|
||||
case tape_type::START_OBJECT:
|
||||
return tape_value();
|
||||
@@ -1082,7 +1112,7 @@ inline size_t tape_ref::after_element() const noexcept {
|
||||
return json_index + 1;
|
||||
}
|
||||
}
|
||||
really_inline tape_type tape_ref::type() const noexcept {
|
||||
really_inline tape_type tape_ref::tape_ref_type() const noexcept {
|
||||
return static_cast<tape_type>(doc->tape[json_index] >> 56);
|
||||
}
|
||||
really_inline uint64_t internal::tape_ref::tape_value() const noexcept {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#define SIMDJSON_SIMDJSON_VERSION_H
|
||||
|
||||
/** The version of simdjson being used (major.minor.revision) */
|
||||
#define SIMDJSON_VERSION 0.3.0
|
||||
#define SIMDJSON_VERSION 0.3.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 Tue 31 Mar 2020 17:00:28 EDT. Do not edit! */
|
||||
/* auto-generated on Thu 2 Apr 2020 18:58:25 EDT. Do not edit! */
|
||||
|
||||
#include <iostream>
|
||||
#include "simdjson.h"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* auto-generated on Tue 31 Mar 2020 17:00:28 EDT. Do not edit! */
|
||||
/* auto-generated on Thu 2 Apr 2020 18:58:25 EDT. Do not edit! */
|
||||
#include "simdjson.h"
|
||||
|
||||
/* used for http://dmalloc.com/ Dmalloc - Debug Malloc Library */
|
||||
|
||||
+139
-60
@@ -1,4 +1,4 @@
|
||||
/* auto-generated on Tue 31 Mar 2020 17:00:28 EDT. Do not edit! */
|
||||
/* auto-generated on Thu 2 Apr 2020 18:58:25 EDT. Do not edit! */
|
||||
/* begin file include/simdjson.h */
|
||||
#ifndef SIMDJSON_H
|
||||
#define SIMDJSON_H
|
||||
@@ -40,7 +40,7 @@
|
||||
#define SIMDJSON_SIMDJSON_VERSION_H
|
||||
|
||||
/** The version of simdjson being used (major.minor.revision) */
|
||||
#define SIMDJSON_VERSION 0.3.0
|
||||
#define SIMDJSON_VERSION 0.3.1
|
||||
|
||||
namespace simdjson {
|
||||
enum {
|
||||
@@ -55,7 +55,7 @@ enum {
|
||||
/**
|
||||
* The revision (major.minor.REVISION) of simdjson being used.
|
||||
*/
|
||||
SIMDJSON_VERSION_REVISION = 0
|
||||
SIMDJSON_VERSION_REVISION = 1
|
||||
};
|
||||
} // namespace simdjson
|
||||
|
||||
@@ -744,50 +744,65 @@ namespace simdjson::internal {
|
||||
using namespace simdjson::dom;
|
||||
|
||||
constexpr const uint64_t JSON_VALUE_MASK = 0x00FFFFFFFFFFFFFF;
|
||||
enum class tape_type;
|
||||
class tape_ref;
|
||||
/**
|
||||
* The possible types in the tape. Internal only.
|
||||
*/
|
||||
enum class tape_type {
|
||||
ROOT = 'r',
|
||||
START_ARRAY = '[',
|
||||
START_OBJECT = '{',
|
||||
END_ARRAY = ']',
|
||||
END_OBJECT = '}',
|
||||
STRING = '"',
|
||||
INT64 = 'l',
|
||||
UINT64 = 'u',
|
||||
DOUBLE = 'd',
|
||||
TRUE_VALUE = 't',
|
||||
FALSE_VALUE = 'f',
|
||||
NULL_VALUE = 'n'
|
||||
};
|
||||
|
||||
/**
|
||||
* A reference to an element on the tape. Internal only.
|
||||
*/
|
||||
class tape_ref {
|
||||
public:
|
||||
really_inline tape_ref() noexcept;
|
||||
really_inline tape_ref(const document *doc, size_t json_index) noexcept;
|
||||
inline size_t after_element() const noexcept;
|
||||
really_inline tape_type type() const noexcept;
|
||||
really_inline uint64_t tape_value() const noexcept;
|
||||
template<typename T>
|
||||
really_inline T next_tape_value() const noexcept;
|
||||
inline std::string_view get_string_view() const noexcept;
|
||||
/**
|
||||
* The 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'
|
||||
};
|
||||
|
||||
/** The document this element references. */
|
||||
const document *doc;
|
||||
/**
|
||||
* 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 tape_ref_type() const noexcept;
|
||||
really_inline uint64_t tape_value() const noexcept;
|
||||
template<typename T>
|
||||
really_inline T next_tape_value() const noexcept;
|
||||
inline std::string_view get_string_view() const noexcept;
|
||||
|
||||
/** The document this element references. */
|
||||
const document *doc;
|
||||
|
||||
/** The index of this element on `doc.tape[]` */
|
||||
size_t json_index;
|
||||
};
|
||||
|
||||
/** The index of this element on `doc.tape[]` */
|
||||
size_t json_index;
|
||||
};
|
||||
} // namespace simdjson::internal
|
||||
|
||||
namespace simdjson::dom {
|
||||
|
||||
/**
|
||||
* The actual concrete type of a JSON element
|
||||
* This is the type it is most easily cast to with get<>.
|
||||
*/
|
||||
enum class element_type {
|
||||
ARRAY, ///< dom::array
|
||||
OBJECT, ///< dom::object
|
||||
INT64, ///< int64_t
|
||||
UINT64, ///< uint64_t: any integer that fits in uint64_t but *not* int64_t
|
||||
DOUBLE, ///< double: Any number with a "." or "e" that fits in double.
|
||||
STRING, ///< std::string_view
|
||||
BOOL, ///< bool
|
||||
NULL_VALUE ///< null
|
||||
};
|
||||
|
||||
/**
|
||||
* JSON array.
|
||||
*/
|
||||
@@ -1070,6 +1085,9 @@ public:
|
||||
/** Create a new, invalid element. */
|
||||
really_inline element() noexcept;
|
||||
|
||||
/** The type of this element. */
|
||||
really_inline element_type type() const noexcept;
|
||||
|
||||
/** Whether this element is a json `null`. */
|
||||
really_inline bool is_null() const noexcept;
|
||||
|
||||
@@ -1824,6 +1842,36 @@ inline std::ostream& operator<<(std::ostream& out, const object &value) { return
|
||||
*/
|
||||
inline std::ostream& operator<<(std::ostream& out, const key_value_pair &value) { return out << minify(value); }
|
||||
|
||||
/**
|
||||
* Print element type to an output stream.
|
||||
*
|
||||
* @param out The output stream.
|
||||
* @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, element_type type) {
|
||||
switch (type) {
|
||||
case element_type::ARRAY:
|
||||
return out << "array";
|
||||
case element_type::OBJECT:
|
||||
return out << "object";
|
||||
case element_type::INT64:
|
||||
return out << "int64_t";
|
||||
case element_type::UINT64:
|
||||
return out << "uint64_t";
|
||||
case element_type::DOUBLE:
|
||||
return out << "double";
|
||||
case element_type::STRING:
|
||||
return out << "string";
|
||||
case element_type::BOOL:
|
||||
return out << "bool";
|
||||
case element_type::NULL_VALUE:
|
||||
return out << "null";
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
@@ -1875,6 +1923,7 @@ public:
|
||||
really_inline simdjson_result(dom::element &&value) noexcept; ///< @private
|
||||
really_inline simdjson_result(error_code error) noexcept; ///< @private
|
||||
|
||||
inline simdjson_result<dom::element_type> type() const noexcept;
|
||||
inline simdjson_result<bool> is_null() const noexcept;
|
||||
template<typename T>
|
||||
inline simdjson_result<bool> is() const noexcept;
|
||||
@@ -2867,6 +2916,10 @@ really_inline simdjson_result<dom::element>::simdjson_result(dom::element &&valu
|
||||
: internal::simdjson_result_base<dom::element>(std::forward<dom::element>(value)) {}
|
||||
really_inline simdjson_result<dom::element>::simdjson_result(error_code error) noexcept
|
||||
: internal::simdjson_result_base<dom::element>(error) {}
|
||||
inline simdjson_result<dom::element_type> simdjson_result<dom::element>::type() const noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first.type();
|
||||
}
|
||||
inline simdjson_result<bool> simdjson_result<dom::element>::is_null() const noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first.is_null();
|
||||
@@ -3559,13 +3612,39 @@ inline key_value_pair::key_value_pair(const std::string_view &_key, element _val
|
||||
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) { }
|
||||
|
||||
inline element_type element::type() const noexcept {
|
||||
switch (tape_ref_type()) {
|
||||
case internal::tape_type::START_ARRAY:
|
||||
return element_type::ARRAY;
|
||||
case internal::tape_type::START_OBJECT:
|
||||
return element_type::OBJECT;
|
||||
case internal::tape_type::INT64:
|
||||
return element_type::INT64;
|
||||
case internal::tape_type::UINT64:
|
||||
return element_type::UINT64;
|
||||
case internal::tape_type::DOUBLE:
|
||||
return element_type::DOUBLE;
|
||||
case internal::tape_type::STRING:
|
||||
return element_type::STRING;
|
||||
case internal::tape_type::TRUE_VALUE:
|
||||
case internal::tape_type::FALSE_VALUE:
|
||||
return element_type::BOOL;
|
||||
case internal::tape_type::NULL_VALUE:
|
||||
return element_type::NULL_VALUE;
|
||||
case internal::tape_type::ROOT:
|
||||
case internal::tape_type::END_ARRAY:
|
||||
case internal::tape_type::END_OBJECT:
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
really_inline bool element::is_null() const noexcept {
|
||||
return type() == internal::tape_type::NULL_VALUE;
|
||||
return tape_ref_type() == internal::tape_type::NULL_VALUE;
|
||||
}
|
||||
|
||||
template<>
|
||||
inline simdjson_result<bool> element::get<bool>() const noexcept {
|
||||
switch (type()) {
|
||||
switch (tape_ref_type()) {
|
||||
case internal::tape_type::TRUE_VALUE:
|
||||
return true;
|
||||
case internal::tape_type::FALSE_VALUE:
|
||||
@@ -3576,7 +3655,7 @@ inline simdjson_result<bool> element::get<bool>() const noexcept {
|
||||
}
|
||||
template<>
|
||||
inline simdjson_result<const char *> element::get<const char *>() const noexcept {
|
||||
switch (type()) {
|
||||
switch (tape_ref_type()) {
|
||||
case internal::tape_type::STRING: {
|
||||
size_t string_buf_index = tape_value();
|
||||
return reinterpret_cast<const char *>(&doc->string_buf[string_buf_index + sizeof(uint32_t)]);
|
||||
@@ -3587,7 +3666,7 @@ inline simdjson_result<const char *> element::get<const char *>() const noexcept
|
||||
}
|
||||
template<>
|
||||
inline simdjson_result<std::string_view> element::get<std::string_view>() const noexcept {
|
||||
switch (type()) {
|
||||
switch (tape_ref_type()) {
|
||||
case internal::tape_type::STRING:
|
||||
return get_string_view();
|
||||
default:
|
||||
@@ -3596,7 +3675,7 @@ inline simdjson_result<std::string_view> element::get<std::string_view>() const
|
||||
}
|
||||
template<>
|
||||
inline simdjson_result<uint64_t> element::get<uint64_t>() const noexcept {
|
||||
switch (type()) {
|
||||
switch (tape_ref_type()) {
|
||||
case internal::tape_type::UINT64:
|
||||
return next_tape_value<uint64_t>();
|
||||
case internal::tape_type::INT64: {
|
||||
@@ -3612,11 +3691,11 @@ inline simdjson_result<uint64_t> element::get<uint64_t>() const noexcept {
|
||||
}
|
||||
template<>
|
||||
inline simdjson_result<int64_t> element::get<int64_t>() const noexcept {
|
||||
switch (type()) {
|
||||
switch (tape_ref_type()) {
|
||||
case internal::tape_type::UINT64: {
|
||||
uint64_t result = next_tape_value<uint64_t>();
|
||||
// Wrapping max in parens to handle Windows issue: https://stackoverflow.com/questions/11544073/how-do-i-deal-with-the-max-macro-in-windows-h-colliding-with-max-in-std
|
||||
if (result > (std::numeric_limits<uint64_t>::max)()) {
|
||||
if (result > (std::numeric_limits<int64_t>::max)()) {
|
||||
return NUMBER_OUT_OF_RANGE;
|
||||
}
|
||||
return static_cast<int64_t>(result);
|
||||
@@ -3629,7 +3708,7 @@ inline simdjson_result<int64_t> element::get<int64_t>() const noexcept {
|
||||
}
|
||||
template<>
|
||||
inline simdjson_result<double> element::get<double>() const noexcept {
|
||||
switch (type()) {
|
||||
switch (tape_ref_type()) {
|
||||
case internal::tape_type::UINT64:
|
||||
return next_tape_value<uint64_t>();
|
||||
case internal::tape_type::INT64: {
|
||||
@@ -3648,7 +3727,7 @@ inline simdjson_result<double> element::get<double>() const noexcept {
|
||||
}
|
||||
template<>
|
||||
inline simdjson_result<array> element::get<array>() const noexcept {
|
||||
switch (type()) {
|
||||
switch (tape_ref_type()) {
|
||||
case internal::tape_type::START_ARRAY:
|
||||
return array(doc, json_index);
|
||||
default:
|
||||
@@ -3657,7 +3736,7 @@ inline simdjson_result<array> element::get<array>() const noexcept {
|
||||
}
|
||||
template<>
|
||||
inline simdjson_result<object> element::get<object>() const noexcept {
|
||||
switch (type()) {
|
||||
switch (tape_ref_type()) {
|
||||
case internal::tape_type::START_OBJECT:
|
||||
return object(doc, json_index);
|
||||
default:
|
||||
@@ -3682,10 +3761,10 @@ inline element::operator double() const noexcept(false) { return get<double>();
|
||||
inline element::operator array() const noexcept(false) { return get<array>(); }
|
||||
inline element::operator object() const noexcept(false) { return get<object>(); }
|
||||
|
||||
inline dom::array::iterator dom::element::begin() const noexcept(false) {
|
||||
inline array::iterator element::begin() const noexcept(false) {
|
||||
return get<array>().begin();
|
||||
}
|
||||
inline dom::array::iterator dom::element::end() const noexcept(false) {
|
||||
inline array::iterator element::end() const noexcept(false) {
|
||||
return get<array>().end();
|
||||
}
|
||||
|
||||
@@ -3698,7 +3777,7 @@ inline simdjson_result<element> element::operator[](const char *key) const noexc
|
||||
return at_key(key);
|
||||
}
|
||||
inline simdjson_result<element> element::at(const std::string_view &json_pointer) const noexcept {
|
||||
switch (type()) {
|
||||
switch (tape_ref_type()) {
|
||||
case internal::tape_type::START_OBJECT:
|
||||
return object(doc, json_index).at(json_pointer);
|
||||
case internal::tape_type::START_ARRAY:
|
||||
@@ -3749,7 +3828,7 @@ inline std::ostream& minify<dom::element>::print(std::ostream& out) {
|
||||
out << '"' << internal::escape_json_string(iter.get_string_view()) << "\":";
|
||||
iter.json_index++;
|
||||
}
|
||||
switch (iter.type()) {
|
||||
switch (iter.tape_ref_type()) {
|
||||
|
||||
// Arrays
|
||||
case tape_type::START_ARRAY: {
|
||||
@@ -3767,7 +3846,7 @@ inline std::ostream& minify<dom::element>::print(std::ostream& out) {
|
||||
iter.json_index++;
|
||||
|
||||
// Handle empty [] (we don't want to come back around and print commas)
|
||||
if (iter.type() == tape_type::END_ARRAY) {
|
||||
if (iter.tape_ref_type() == tape_type::END_ARRAY) {
|
||||
out << ']';
|
||||
depth--;
|
||||
break;
|
||||
@@ -3794,7 +3873,7 @@ inline std::ostream& minify<dom::element>::print(std::ostream& out) {
|
||||
iter.json_index++;
|
||||
|
||||
// Handle empty {} (we don't want to come back around and print commas)
|
||||
if (iter.type() == tape_type::END_OBJECT) {
|
||||
if (iter.tape_ref_type() == tape_type::END_OBJECT) {
|
||||
out << '}';
|
||||
depth--;
|
||||
break;
|
||||
@@ -3841,8 +3920,8 @@ inline std::ostream& minify<dom::element>::print(std::ostream& out) {
|
||||
after_value = true;
|
||||
|
||||
// Handle multiple ends in a row
|
||||
while (depth != 0 && (iter.type() == tape_type::END_ARRAY || iter.type() == tape_type::END_OBJECT)) {
|
||||
out << char(iter.type());
|
||||
while (depth != 0 && (iter.tape_ref_type() == tape_type::END_ARRAY || iter.tape_ref_type() == tape_type::END_OBJECT)) {
|
||||
out << char(iter.tape_ref_type());
|
||||
depth--;
|
||||
iter.json_index++;
|
||||
}
|
||||
@@ -3914,7 +3993,7 @@ 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()) {
|
||||
switch (tape_ref_type()) {
|
||||
case tape_type::START_ARRAY:
|
||||
case tape_type::START_OBJECT:
|
||||
return tape_value();
|
||||
@@ -3926,7 +4005,7 @@ inline size_t tape_ref::after_element() const noexcept {
|
||||
return json_index + 1;
|
||||
}
|
||||
}
|
||||
really_inline tape_type tape_ref::type() const noexcept {
|
||||
really_inline tape_type tape_ref::tape_ref_type() const noexcept {
|
||||
return static_cast<tape_type>(doc->tape[json_index] >> 56);
|
||||
}
|
||||
really_inline uint64_t internal::tape_ref::tape_value() const noexcept {
|
||||
|
||||
@@ -23,6 +23,11 @@
|
||||
#define NDJSON_TEST_PATH "jsonexamples/amazon_cellphones.ndjson"
|
||||
#endif
|
||||
|
||||
#define ASSERT_EQUAL(ACTUAL, EXPECTED) if ((ACTUAL) != (EXPECTED)) { std::cerr << "Expected " << #ACTUAL << " to be " << (EXPECTED) << ", got " << (ACTUAL) << " instead!" << std::endl; return false; }
|
||||
#define ASSERT_TRUE(ACTUAL) ASSERT_EQUAL(ACTUAL, true)
|
||||
#define ASSERT_FALSE(ACTUAL) ASSERT_EQUAL(ACTUAL, false)
|
||||
#define ASSERT_SUCCESS(ERROR) if (ERROR) { std::cerr << (ERROR) << std::endl; return false; }
|
||||
|
||||
namespace number_tests {
|
||||
|
||||
// ulp distance
|
||||
@@ -1104,6 +1109,488 @@ namespace dom_api_tests {
|
||||
}
|
||||
}
|
||||
|
||||
namespace type_tests {
|
||||
using namespace simdjson;
|
||||
using namespace std;
|
||||
|
||||
const padded_string ALL_TYPES_JSON = R"(
|
||||
{
|
||||
"array": [],
|
||||
|
||||
"object": {},
|
||||
|
||||
"string": "foo",
|
||||
|
||||
"0": 0,
|
||||
"1": 1,
|
||||
"-1": -1,
|
||||
"9223372036854775807": 9223372036854775807,
|
||||
"-9223372036854775808": -9223372036854775808,
|
||||
|
||||
"9223372036854775808": 9223372036854775808,
|
||||
"18446744073709551615": 18446744073709551615,
|
||||
|
||||
"0.0": 0.0,
|
||||
"0.1": 0.1,
|
||||
"1e0": 1e0,
|
||||
"1e100": 1e100,
|
||||
|
||||
"true": true,
|
||||
"false": false,
|
||||
|
||||
"null": null
|
||||
}
|
||||
)"_padded;
|
||||
|
||||
bool test_array() {
|
||||
std::cout << "Running " << __func__ << std::endl;
|
||||
|
||||
const auto key = "array";
|
||||
const auto expected_type = dom::element_type::ARRAY;
|
||||
|
||||
dom::parser parser;
|
||||
simdjson_result<dom::element> result = parser.parse(ALL_TYPES_JSON)[key];
|
||||
ASSERT_SUCCESS(result.error());
|
||||
|
||||
// Test simdjson_result<element>.is<T>() (error chain)
|
||||
ASSERT_TRUE(result.is<dom::array>());
|
||||
ASSERT_FALSE(result.is<dom::object>());
|
||||
ASSERT_FALSE(result.is<std::string_view>());
|
||||
ASSERT_FALSE(result.is<const char *>());
|
||||
ASSERT_FALSE(result.is<int64_t>());
|
||||
ASSERT_FALSE(result.is<uint64_t>());
|
||||
ASSERT_FALSE(result.is<double>());
|
||||
ASSERT_FALSE(result.is<bool>());
|
||||
ASSERT_FALSE(result.is_null());
|
||||
|
||||
// Test simdjson_result<element>.type() (error chain)
|
||||
simdjson::error_code error;
|
||||
dom::element_type type;
|
||||
result.type().tie(type, error);
|
||||
ASSERT_SUCCESS(error);
|
||||
ASSERT_EQUAL(type, expected_type);
|
||||
|
||||
// Test element.is<T>()
|
||||
dom::element element = result.first;
|
||||
ASSERT_TRUE(element.is<dom::array>());
|
||||
ASSERT_FALSE(element.is<dom::object>());
|
||||
ASSERT_FALSE(element.is<std::string_view>());
|
||||
ASSERT_FALSE(element.is<const char *>());
|
||||
ASSERT_FALSE(element.is<int64_t>());
|
||||
ASSERT_FALSE(element.is<uint64_t>());
|
||||
ASSERT_FALSE(element.is<double>());
|
||||
ASSERT_FALSE(element.is<bool>());
|
||||
ASSERT_FALSE(element.is_null());
|
||||
|
||||
// Test element.type()
|
||||
ASSERT_EQUAL(element.type(), expected_type);
|
||||
|
||||
// Test element.get<T>()
|
||||
dom::array value;
|
||||
result.get<dom::array>().tie(value, error);
|
||||
ASSERT_SUCCESS(error);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool test_object() {
|
||||
std::cout << "Running " << __func__ << std::endl;
|
||||
|
||||
const auto key = "object";
|
||||
const auto expected_type = dom::element_type::OBJECT;
|
||||
|
||||
dom::parser parser;
|
||||
simdjson_result<dom::element> result = parser.parse(ALL_TYPES_JSON)[key];
|
||||
ASSERT_SUCCESS(result.error());
|
||||
|
||||
// Test simdjson_result<element>.is<T>() (error chain)
|
||||
ASSERT_FALSE(result.is<dom::array>());
|
||||
ASSERT_TRUE(result.is<dom::object>());
|
||||
ASSERT_FALSE(result.is<std::string_view>());
|
||||
ASSERT_FALSE(result.is<const char *>());
|
||||
ASSERT_FALSE(result.is<int64_t>());
|
||||
ASSERT_FALSE(result.is<uint64_t>());
|
||||
ASSERT_FALSE(result.is<double>());
|
||||
ASSERT_FALSE(result.is<bool>());
|
||||
ASSERT_FALSE(result.is_null());
|
||||
|
||||
// Test simdjson_result<element>.type() (error chain)
|
||||
simdjson::error_code error;
|
||||
dom::element_type type;
|
||||
result.type().tie(type, error);
|
||||
ASSERT_SUCCESS(error);
|
||||
ASSERT_EQUAL(type, expected_type);
|
||||
|
||||
// Test element.is<T>()
|
||||
dom::element element = result.first;
|
||||
ASSERT_FALSE(element.is<dom::array>());
|
||||
ASSERT_TRUE(element.is<dom::object>());
|
||||
ASSERT_FALSE(element.is<std::string_view>());
|
||||
ASSERT_FALSE(element.is<const char *>());
|
||||
ASSERT_FALSE(element.is<int64_t>());
|
||||
ASSERT_FALSE(element.is<uint64_t>());
|
||||
ASSERT_FALSE(element.is<double>());
|
||||
ASSERT_FALSE(element.is<bool>());
|
||||
ASSERT_FALSE(element.is_null());
|
||||
|
||||
// Test element.type()
|
||||
ASSERT_EQUAL(element.type(), expected_type);
|
||||
|
||||
// Test element.get<T>()
|
||||
dom::object value;
|
||||
result.get<dom::object>().tie(value, error);
|
||||
ASSERT_SUCCESS(error);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool test_string() {
|
||||
std::cout << "Running " << __func__ << std::endl;
|
||||
|
||||
const auto key = "string";
|
||||
const auto expected_type = dom::element_type::STRING;
|
||||
|
||||
dom::parser parser;
|
||||
simdjson_result<dom::element> result = parser.parse(ALL_TYPES_JSON)[key];
|
||||
ASSERT_SUCCESS(result.error());
|
||||
|
||||
// Test simdjson_result<element>.is<T>() (error chain)
|
||||
ASSERT_FALSE(result.is<dom::array>());
|
||||
ASSERT_FALSE(result.is<dom::object>());
|
||||
ASSERT_TRUE(result.is<std::string_view>());
|
||||
ASSERT_TRUE(result.is<const char *>());
|
||||
ASSERT_FALSE(result.is<int64_t>());
|
||||
ASSERT_FALSE(result.is<uint64_t>());
|
||||
ASSERT_FALSE(result.is<double>());
|
||||
ASSERT_FALSE(result.is<bool>());
|
||||
ASSERT_FALSE(result.is_null());
|
||||
|
||||
// Test simdjson_result<element>.type() (error chain)
|
||||
simdjson::error_code error;
|
||||
dom::element_type type;
|
||||
result.type().tie(type, error);
|
||||
ASSERT_SUCCESS(error);
|
||||
ASSERT_EQUAL(type, expected_type);
|
||||
|
||||
// Test element.is<T>()
|
||||
dom::element element = result.first;
|
||||
ASSERT_FALSE(element.is<dom::array>());
|
||||
ASSERT_FALSE(element.is<dom::object>());
|
||||
ASSERT_TRUE(element.is<std::string_view>());
|
||||
ASSERT_TRUE(element.is<const char *>());
|
||||
ASSERT_FALSE(element.is<int64_t>());
|
||||
ASSERT_FALSE(element.is<uint64_t>());
|
||||
ASSERT_FALSE(element.is<double>());
|
||||
ASSERT_FALSE(element.is<bool>());
|
||||
ASSERT_FALSE(element.is_null());
|
||||
|
||||
// Test element.type()
|
||||
ASSERT_EQUAL(element.type(), expected_type);
|
||||
|
||||
// Test element.get<T>()
|
||||
std::string_view value;
|
||||
result.get<std::string_view>().tie(value, error);
|
||||
ASSERT_SUCCESS(error);
|
||||
ASSERT_EQUAL(value, string_view("foo"));
|
||||
|
||||
const char *value2;
|
||||
result.get<const char *>().tie(value2, error);
|
||||
ASSERT_SUCCESS(error);
|
||||
ASSERT_EQUAL(string_view(value2), string_view("foo"));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool test_int64(const char *key, int64_t expected_value) {
|
||||
std::cout << "Running " << __func__ << "(" << key << ")" << std::endl;
|
||||
|
||||
const auto expected_type = dom::element_type::INT64;
|
||||
|
||||
dom::parser parser;
|
||||
simdjson_result<dom::element> result = parser.parse(ALL_TYPES_JSON)[key];
|
||||
ASSERT_SUCCESS(result.error());
|
||||
|
||||
// Test simdjson_result<element>.is<T>() (error chain)
|
||||
ASSERT_FALSE(result.is<dom::array>());
|
||||
ASSERT_FALSE(result.is<dom::object>());
|
||||
ASSERT_FALSE(result.is<std::string_view>());
|
||||
ASSERT_FALSE(result.is<const char *>());
|
||||
ASSERT_TRUE(result.is<int64_t>());
|
||||
if (expected_value < 0) {
|
||||
ASSERT_FALSE(result.is<uint64_t>());
|
||||
} else {
|
||||
ASSERT_TRUE(result.is<uint64_t>());
|
||||
}
|
||||
ASSERT_TRUE(result.is<double>());
|
||||
ASSERT_FALSE(result.is<bool>());
|
||||
ASSERT_FALSE(result.is_null());
|
||||
|
||||
// Test simdjson_result<element>.type() (error chain)
|
||||
simdjson::error_code error;
|
||||
dom::element_type type;
|
||||
result.type().tie(type, error);
|
||||
ASSERT_SUCCESS(error);
|
||||
ASSERT_EQUAL(type, expected_type);
|
||||
|
||||
// Test element.is<T>()
|
||||
dom::element element = result.first;
|
||||
ASSERT_FALSE(element.is<dom::array>());
|
||||
ASSERT_FALSE(element.is<dom::object>());
|
||||
ASSERT_FALSE(element.is<std::string_view>());
|
||||
ASSERT_FALSE(element.is<const char *>());
|
||||
ASSERT_TRUE(element.is<int64_t>());
|
||||
if (expected_value < 0) {
|
||||
ASSERT_FALSE(element.is<uint64_t>());
|
||||
} else {
|
||||
ASSERT_TRUE(element.is<uint64_t>());
|
||||
}
|
||||
ASSERT_TRUE(element.is<double>());
|
||||
ASSERT_FALSE(element.is<bool>());
|
||||
ASSERT_FALSE(element.is_null());
|
||||
|
||||
// Test element.type()
|
||||
ASSERT_EQUAL(element.type(), expected_type);
|
||||
|
||||
// Test element.get<T>()
|
||||
int64_t value;
|
||||
result.get<int64_t>().tie(value, error);
|
||||
ASSERT_SUCCESS(error);
|
||||
ASSERT_EQUAL(value, expected_value);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool test_uint64(const char *key, uint64_t expected_value) {
|
||||
std::cout << "Running " << __func__ << "(" << key << ")" << std::endl;
|
||||
|
||||
const auto expected_type = dom::element_type::UINT64;
|
||||
|
||||
dom::parser parser;
|
||||
simdjson_result<dom::element> result = parser.parse(ALL_TYPES_JSON)[key];
|
||||
ASSERT_SUCCESS(result.error());
|
||||
|
||||
// Test simdjson_result<element>.is<T>() (error chain)
|
||||
ASSERT_FALSE(result.is<dom::array>());
|
||||
ASSERT_FALSE(result.is<dom::object>());
|
||||
ASSERT_FALSE(result.is<std::string_view>());
|
||||
ASSERT_FALSE(result.is<const char *>());
|
||||
ASSERT_FALSE(result.is<int64_t>());
|
||||
ASSERT_TRUE(result.is<uint64_t>());
|
||||
ASSERT_TRUE(result.is<double>());
|
||||
ASSERT_FALSE(result.is<bool>());
|
||||
ASSERT_FALSE(result.is_null());
|
||||
|
||||
// Test simdjson_result<element>.type() (error chain)
|
||||
simdjson::error_code error;
|
||||
dom::element_type type;
|
||||
result.type().tie(type, error);
|
||||
ASSERT_SUCCESS(error);
|
||||
ASSERT_EQUAL(type, expected_type);
|
||||
|
||||
// Test element.is<T>()
|
||||
dom::element element = result.first;
|
||||
ASSERT_FALSE(element.is<dom::array>());
|
||||
ASSERT_FALSE(element.is<dom::object>());
|
||||
ASSERT_FALSE(element.is<std::string_view>());
|
||||
ASSERT_FALSE(element.is<const char *>());
|
||||
ASSERT_FALSE(element.is<int64_t>());
|
||||
ASSERT_TRUE(element.is<uint64_t>());
|
||||
ASSERT_TRUE(element.is<double>());
|
||||
ASSERT_FALSE(element.is<bool>());
|
||||
ASSERT_FALSE(element.is_null());
|
||||
|
||||
// Test element.type()
|
||||
ASSERT_EQUAL(element.type(), expected_type);
|
||||
|
||||
// Test element.get<T>()
|
||||
uint64_t value;
|
||||
result.get<uint64_t>().tie(value, error);
|
||||
ASSERT_SUCCESS(error);
|
||||
ASSERT_EQUAL(value, expected_value);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool test_double(const char *key, double expected_value) {
|
||||
std::cout << "Running " << __func__ << "(" << key << ")" << std::endl;
|
||||
|
||||
const auto expected_type = dom::element_type::DOUBLE;
|
||||
|
||||
dom::parser parser;
|
||||
simdjson_result<dom::element> result = parser.parse(ALL_TYPES_JSON)[key];
|
||||
ASSERT_SUCCESS(result.error());
|
||||
|
||||
// Test simdjson_result<element>.is<T>() (error chain)
|
||||
ASSERT_FALSE(result.is<dom::array>());
|
||||
ASSERT_FALSE(result.is<dom::object>());
|
||||
ASSERT_FALSE(result.is<std::string_view>());
|
||||
ASSERT_FALSE(result.is<const char *>());
|
||||
ASSERT_FALSE(result.is<int64_t>());
|
||||
ASSERT_FALSE(result.is<uint64_t>());
|
||||
ASSERT_TRUE(result.is<double>());
|
||||
ASSERT_FALSE(result.is<bool>());
|
||||
ASSERT_FALSE(result.is_null());
|
||||
|
||||
// Test simdjson_result<element>.type() (error chain)
|
||||
simdjson::error_code error;
|
||||
dom::element_type type;
|
||||
result.type().tie(type, error);
|
||||
ASSERT_SUCCESS(error);
|
||||
ASSERT_EQUAL(type, expected_type);
|
||||
|
||||
// Test element.is<T>()
|
||||
dom::element element = result.first;
|
||||
ASSERT_FALSE(element.is<dom::array>());
|
||||
ASSERT_FALSE(element.is<dom::object>());
|
||||
ASSERT_FALSE(element.is<std::string_view>());
|
||||
ASSERT_FALSE(element.is<const char *>());
|
||||
ASSERT_FALSE(element.is<int64_t>());
|
||||
ASSERT_FALSE(element.is<uint64_t>());
|
||||
ASSERT_TRUE(element.is<double>());
|
||||
ASSERT_FALSE(element.is<bool>());
|
||||
ASSERT_FALSE(element.is_null());
|
||||
|
||||
// Test element.type()
|
||||
ASSERT_EQUAL(element.type(), expected_type);
|
||||
|
||||
// Test element.get<T>()
|
||||
double value;
|
||||
result.get<double>().tie(value, error);
|
||||
ASSERT_SUCCESS(error);
|
||||
ASSERT_EQUAL(value, expected_value);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool test_bool(const char *key, bool expected_value) {
|
||||
std::cout << "Running " << __func__ << "(" << key << ")" << std::endl;
|
||||
|
||||
const auto expected_type = dom::element_type::BOOL;
|
||||
|
||||
dom::parser parser;
|
||||
simdjson_result<dom::element> result = parser.parse(ALL_TYPES_JSON)[key];
|
||||
ASSERT_SUCCESS(result.error());
|
||||
|
||||
// Test simdjson_result<element>.is<T>() (error chain)
|
||||
ASSERT_FALSE(result.is<dom::array>());
|
||||
ASSERT_FALSE(result.is<dom::object>());
|
||||
ASSERT_FALSE(result.is<std::string_view>());
|
||||
ASSERT_FALSE(result.is<const char *>());
|
||||
ASSERT_FALSE(result.is<int64_t>());
|
||||
ASSERT_FALSE(result.is<uint64_t>());
|
||||
ASSERT_FALSE(result.is<double>());
|
||||
ASSERT_TRUE(result.is<bool>());
|
||||
ASSERT_FALSE(result.is_null());
|
||||
|
||||
// Test simdjson_result<element>.type() (error chain)
|
||||
simdjson::error_code error;
|
||||
dom::element_type type;
|
||||
result.type().tie(type, error);
|
||||
ASSERT_SUCCESS(error);
|
||||
ASSERT_EQUAL(type, expected_type);
|
||||
|
||||
// Test element.is<T>()
|
||||
dom::element element = result.first;
|
||||
ASSERT_FALSE(element.is<dom::array>());
|
||||
ASSERT_FALSE(element.is<dom::object>());
|
||||
ASSERT_FALSE(element.is<std::string_view>());
|
||||
ASSERT_FALSE(element.is<const char *>());
|
||||
ASSERT_FALSE(element.is<int64_t>());
|
||||
ASSERT_FALSE(element.is<uint64_t>());
|
||||
ASSERT_FALSE(element.is<double>());
|
||||
ASSERT_TRUE(element.is<bool>());
|
||||
ASSERT_FALSE(element.is_null());
|
||||
|
||||
// Test element.type()
|
||||
ASSERT_EQUAL(element.type(), expected_type);
|
||||
|
||||
// Test element.get<T>()
|
||||
bool value;
|
||||
result.get<bool>().tie(value, error);
|
||||
ASSERT_SUCCESS(error);
|
||||
ASSERT_EQUAL(value, expected_value);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool test_null() {
|
||||
std::cout << "Running " << __func__ << std::endl;
|
||||
|
||||
const auto expected_type = dom::element_type::NULL_VALUE;
|
||||
|
||||
dom::parser parser;
|
||||
simdjson_result<dom::element> result = parser.parse(ALL_TYPES_JSON)["null"];
|
||||
ASSERT_SUCCESS(result.error());
|
||||
|
||||
// Test simdjson_result<element>.is<T>() (error chain)
|
||||
ASSERT_FALSE(result.is<dom::array>());
|
||||
ASSERT_FALSE(result.is<dom::object>());
|
||||
ASSERT_FALSE(result.is<std::string_view>());
|
||||
ASSERT_FALSE(result.is<const char *>());
|
||||
ASSERT_FALSE(result.is<int64_t>());
|
||||
ASSERT_FALSE(result.is<uint64_t>());
|
||||
ASSERT_FALSE(result.is<double>());
|
||||
ASSERT_FALSE(result.is<bool>());
|
||||
ASSERT_TRUE(result.is_null());
|
||||
|
||||
// Test simdjson_result<element>.type() (error chain)
|
||||
simdjson::error_code error;
|
||||
dom::element_type type;
|
||||
result.type().tie(type, error);
|
||||
ASSERT_SUCCESS(error);
|
||||
ASSERT_EQUAL(type, expected_type);
|
||||
|
||||
// Test element.is<T>()
|
||||
dom::element element = result.first;
|
||||
ASSERT_FALSE(element.is<dom::array>());
|
||||
ASSERT_FALSE(element.is<dom::object>());
|
||||
ASSERT_FALSE(element.is<std::string_view>());
|
||||
ASSERT_FALSE(element.is<const char *>());
|
||||
ASSERT_FALSE(element.is<int64_t>());
|
||||
ASSERT_FALSE(element.is<uint64_t>());
|
||||
ASSERT_FALSE(element.is<double>());
|
||||
ASSERT_FALSE(element.is<bool>());
|
||||
ASSERT_TRUE(element.is_null());
|
||||
|
||||
// Test element.type()
|
||||
ASSERT_EQUAL(element.type(), expected_type);
|
||||
|
||||
// Test element.get<T>()
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool run() {
|
||||
return test_array() &&
|
||||
|
||||
test_object() &&
|
||||
|
||||
test_string() &&
|
||||
|
||||
test_int64("0", 0) &&
|
||||
test_int64("1", 1) &&
|
||||
test_int64("-1", -1) &&
|
||||
test_int64("9223372036854775807", 9223372036854775807LL) &&
|
||||
test_int64("-9223372036854775808", -1 - 9223372036854775807LL) &&
|
||||
|
||||
test_uint64("9223372036854775808", 9223372036854775808ULL) &&
|
||||
test_uint64("18446744073709551615", 18446744073709551615ULL) &&
|
||||
|
||||
test_double("0.0", 0.0) &&
|
||||
test_double("0.1", 0.1) &&
|
||||
test_double("1e0", 1e0) &&
|
||||
test_double("1e100", 1e100) &&
|
||||
|
||||
test_bool("true", true) &&
|
||||
test_bool("false", false) &&
|
||||
|
||||
test_null() &&
|
||||
|
||||
true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace format_tests {
|
||||
using namespace simdjson;
|
||||
using namespace simdjson::dom;
|
||||
@@ -1378,6 +1865,7 @@ int main(int argc, char *argv[]) {
|
||||
std::cout << "Running basic tests." << std::endl;
|
||||
if (parse_api_tests::run() &&
|
||||
dom_api_tests::run() &&
|
||||
type_tests::run() &&
|
||||
format_tests::run() &&
|
||||
document_tests::run() &&
|
||||
number_tests::run() &&
|
||||
|
||||
@@ -64,6 +64,52 @@ void basics_dom_2() {
|
||||
cout << cars.at("0/tire_pressure/1") << endl; // Prints 39.9}
|
||||
}
|
||||
|
||||
namespace treewalk_1 {
|
||||
void print_json(dom::element element) {
|
||||
switch (element.type()) {
|
||||
case dom::element_type::ARRAY:
|
||||
cout << "[";
|
||||
for (dom::element child : dom::array(element)) {
|
||||
print_json(child);
|
||||
cout << ",";
|
||||
}
|
||||
cout << "]";
|
||||
break;
|
||||
case dom::element_type::OBJECT:
|
||||
cout << "{";
|
||||
for (dom::key_value_pair field : dom::object(element)) {
|
||||
cout << "\"" << field.key << "\": ";
|
||||
print_json(field.value);
|
||||
}
|
||||
cout << "}";
|
||||
break;
|
||||
case dom::element_type::INT64:
|
||||
cout << int64_t(element) << endl;
|
||||
break;
|
||||
case dom::element_type::UINT64:
|
||||
cout << uint64_t(element) << endl;
|
||||
break;
|
||||
case dom::element_type::DOUBLE:
|
||||
cout << double(element) << endl;
|
||||
break;
|
||||
case dom::element_type::STRING:
|
||||
cout << std::string_view(element) << endl;
|
||||
break;
|
||||
case dom::element_type::BOOL:
|
||||
cout << bool(element) << endl;
|
||||
break;
|
||||
case dom::element_type::NULL_VALUE:
|
||||
cout << "null" << endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void basics_treewalk_1() {
|
||||
dom::parser parser;
|
||||
print_json(parser.load("twitter.json"));
|
||||
}
|
||||
}
|
||||
|
||||
void basics_ndjson() {
|
||||
dom::parser parser;
|
||||
for (dom::element doc : parser.load_many("x.txt")) {
|
||||
|
||||
@@ -76,7 +76,10 @@ elif (newversion[1] != currentv[1]):
|
||||
else :
|
||||
assert newversion[2] == currentv[2] + 1
|
||||
|
||||
atleastminor= (currentv[0] != newversion[0]) or (currentv[1] != newversion[1])
|
||||
|
||||
if(atleastminor):
|
||||
print("This is more than a revision.")
|
||||
|
||||
versionfilerel = os.sep + "include" + os.sep + "simdjson" + os.sep + "simdjson_version.h"
|
||||
versionfile = maindir + versionfilerel
|
||||
@@ -114,17 +117,35 @@ print(versionfile + " modified")
|
||||
import fileinput
|
||||
import re
|
||||
|
||||
|
||||
newmajorversionstring = str(newversion[0])
|
||||
mewminorversionstring = str(newversion[1])
|
||||
newrevversionstring = str(newversion[2])
|
||||
newversionstring = str(newversion[0]) + "." + str(newversion[1]) + "." + str(newversion[2])
|
||||
cmakefile = maindir + os.sep + "CMakeLists.txt"
|
||||
|
||||
sonumber = None
|
||||
pattern = re.compile("set\(SIMDJSON_LIB_SOVERSION \"(\d+)\" CACHE STRING \"simdjson library soversion\"\)")
|
||||
with open (cmakefile, 'rt') as myfile:
|
||||
for line in myfile:
|
||||
m = pattern.search(line)
|
||||
if m != None:
|
||||
sonumber = int(m.group(1))
|
||||
break
|
||||
print("so library number "+str(sonumber))
|
||||
|
||||
if(atleastminor):
|
||||
print("Given that we have a minor revision, it seems necessary to bump the so library number")
|
||||
print("See https://github.com/simdjson/simdjson/issues/661")
|
||||
sonumber += 1
|
||||
|
||||
for line in fileinput.input(cmakefile, inplace=1, backup='.bak'):
|
||||
line = re.sub('SIMDJSON_LIB_VERSION "\d+\.\d+\.\d+','SIMDJSON_LIB_VERSION "'+newversionstring, line.rstrip())
|
||||
line = re.sub('SIMDJSON_LIB_SOVERSION "\d+','SIMDJSON_LIB_SOVERSION "'+newmajorversionstring, line)
|
||||
line = re.sub('set\(PROJECT_VERSION_MAJOR \d+','set(PROJECT_VERSION_MAJOR '+newmajorversionstring, line)
|
||||
line = re.sub('set\(PROJECT_VERSION_MINOR \d+','set(PROJECT_VERSION_MINOR '+mewminorversionstring, line)
|
||||
line = re.sub('set\(PROJECT_VERSION_PATCH \d+','set(PROJECT_VERSION_PATCH '+newrevversionstring, line)
|
||||
line = re.sub('set\(SIMDJSON_LIB_SOVERSION \"\d+\"','set(SIMDJSON_LIB_SOVERSION \"'+str(sonumber)+'\"', line)
|
||||
print(line)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user