mirror of
https://github.com/simdjson/simdjson
synced 2026-06-08 17:27:07 +00:00
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| db91f62bd7 | |||
| 20cd6e30ee | |||
| e45d8edbd6 | |||
| 6efb8d81bd | |||
| f562878afc | |||
| 60aa25a0c2 | |||
| d01662560d | |||
| a63c77a977 | |||
| bbb3cb80a6 | |||
| 43219e50e0 | |||
| 49b9860899 | |||
| 0388d79770 | |||
| c0fa1aec66 | |||
| 6e61b7f6ef | |||
| a76e778804 |
@@ -0,0 +1,29 @@
|
|||||||
|
name: Ubuntu ppc64le (GCC 11)
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: uraimo/run-on-arch-action@v2
|
||||||
|
name: Test
|
||||||
|
id: runcmd
|
||||||
|
with:
|
||||||
|
arch: aarch64
|
||||||
|
distro: ubuntu_latest
|
||||||
|
githubToken: ${{ github.token }}
|
||||||
|
install: |
|
||||||
|
apt-get update -q -y
|
||||||
|
apt-get install -y cmake make g++
|
||||||
|
run: |
|
||||||
|
cmake -DSIMDJSON_SANITIZE_UNDEFINED=ON -DSIMDJSON_DEVELOPER_MODE=ON -DSIMDJSON_COMPETITION=OFF -B build
|
||||||
|
cmake --build build -j=2
|
||||||
|
ctest --output-on-failure --test-dir build
|
||||||
@@ -17,7 +17,7 @@ jobs:
|
|||||||
fuzz-seconds: 600
|
fuzz-seconds: 600
|
||||||
dry-run: false
|
dry-run: false
|
||||||
- name: Upload Crash
|
- name: Upload Crash
|
||||||
uses: actions/upload-artifact@v1
|
uses: actions/upload-artifact@v4
|
||||||
if: failure() && steps.build.outcome == 'success'
|
if: failure() && steps.build.outcome == 'success'
|
||||||
with:
|
with:
|
||||||
name: artifacts
|
name: artifacts
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ jobs:
|
|||||||
echo "no trailing whitespace found, good!"
|
echo "no trailing whitespace found, good!"
|
||||||
fi
|
fi
|
||||||
- name: Archive whitespace patch
|
- name: Archive whitespace patch
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v4
|
||||||
if: always()
|
if: always()
|
||||||
with:
|
with:
|
||||||
name: whitespace-patch
|
name: whitespace-patch
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ jobs:
|
|||||||
- msystem: "MINGW64"
|
- msystem: "MINGW64"
|
||||||
install: mingw-w64-x86_64-cmake mingw-w64-x86_64-ninja mingw-w64-x86_64-gcc
|
install: mingw-w64-x86_64-cmake mingw-w64-x86_64-ninja mingw-w64-x86_64-gcc
|
||||||
type: Debug
|
type: Debug
|
||||||
- msystem: "MINGW64"
|
- msystem: "MINGW64"
|
||||||
install: mingw-w64-x86_64-cmake mingw-w64-x86_64-ninja mingw-w64-x86_64-gcc
|
install: mingw-w64-x86_64-cmake mingw-w64-x86_64-ninja mingw-w64-x86_64-gcc
|
||||||
type: RelWithDebInfo
|
type: RelWithDebInfo
|
||||||
env:
|
env:
|
||||||
|
|||||||
@@ -24,6 +24,6 @@ jobs:
|
|||||||
apt-get update -q -y
|
apt-get update -q -y
|
||||||
apt-get install -y cmake make g++
|
apt-get install -y cmake make g++
|
||||||
run: |
|
run: |
|
||||||
cmake -DCMAKE_BUILD_TYPE=Release -B build
|
cmake -DCMAKE_BUILD_TYPE=Release -DSIMDJSON_DEVELOPER_MODE=ON -DSIMDJSON_COMPETITION=OFF -B build
|
||||||
cmake --build build -j=2
|
cmake --build build -j=2
|
||||||
ctest --output-on-failure --test-dir build
|
ctest --output-on-failure --test-dir build
|
||||||
|
|||||||
@@ -24,6 +24,6 @@ jobs:
|
|||||||
apt-get update -q -y
|
apt-get update -q -y
|
||||||
apt-get install -y cmake make g++
|
apt-get install -y cmake make g++
|
||||||
run: |
|
run: |
|
||||||
cmake -DCMAKE_BUILD_TYPE=Release -B build
|
cmake -DCMAKE_BUILD_TYPE=Release -DSIMDJSON_DEVELOPER_MODE=ON -DSIMDJSON_COMPETITION=OFF -B build
|
||||||
cmake --build build -j=2
|
cmake --build build -j=2
|
||||||
ctest --output-on-failure --test-dir build
|
ctest --output-on-failure --test-dir build
|
||||||
|
|||||||
@@ -24,6 +24,6 @@ jobs:
|
|||||||
apt-get update -q -y
|
apt-get update -q -y
|
||||||
apt-get install -y cmake make g++
|
apt-get install -y cmake make g++
|
||||||
run: |
|
run: |
|
||||||
cmake -DCMAKE_BUILD_TYPE=Release -B build
|
cmake -DCMAKE_BUILD_TYPE=Release -DSIMDJSON_DEVELOPER_MODE=ON -DSIMDJSON_COMPETITION=OFF -B build
|
||||||
cmake --build build -j=2
|
cmake --build build -j=2
|
||||||
ctest --output-on-failure --test-dir build
|
ctest --output-on-failure --test-dir build
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
name: Ubuntu 24.04 CI (CXX 20)
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
jobs:
|
||||||
|
ubuntu-build:
|
||||||
|
if: >-
|
||||||
|
! contains(toJSON(github.event.commits.*.message), '[skip ci]') &&
|
||||||
|
! contains(toJSON(github.event.commits.*.message), '[skip github]')
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
cxx: [g++-13, clang++-16]
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||||
|
- name: Prepare
|
||||||
|
run: cmake -DSIMDJSON_CXX_STANDARD=20 -DSIMDJSON_DEVELOPER_MODE=ON -B build
|
||||||
|
env:
|
||||||
|
CXX: ${{matrix.cxx}}
|
||||||
|
- name: Build
|
||||||
|
run: cmake --build build -j=2
|
||||||
|
- name: Test
|
||||||
|
run: ctest --output-on-failure --test-dir build
|
||||||
@@ -26,15 +26,15 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
cmake -G "${{matrix.gen}}" -A ${{matrix.arch}} -DSIMDJSON_DEVELOPER_MODE=ON -DSIMDJSON_COMPETITION=OFF -DBUILD_SHARED_LIBS=${{matrix.shared}} -B build
|
cmake -G "${{matrix.gen}}" -A ${{matrix.arch}} -DSIMDJSON_DEVELOPER_MODE=ON -DSIMDJSON_COMPETITION=OFF -DBUILD_SHARED_LIBS=${{matrix.shared}} -B build
|
||||||
- name: Build Debug
|
- name: Build Debug
|
||||||
run: cmake --build build --config ${{build_type}} --verbose
|
run: cmake --build build --config ${{matrix.build_type}} --verbose
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: |
|
run: |
|
||||||
cd build
|
cd build
|
||||||
ctest -C ${{build_type}} -LE explicitonly --output-on-failure
|
ctest -C ${{matrix.build_type}} -LE explicitonly --output-on-failure
|
||||||
- name: Install
|
- name: Install
|
||||||
run: |
|
run: |
|
||||||
cmake --install build --config ${{build_type}}
|
cmake --install build --config ${{matrix.build_type}}
|
||||||
- name: Test Installation
|
- name: Test Installation
|
||||||
run: |
|
run: |
|
||||||
cmake -G "${{matrix.gen}}" -A ${{matrix.arch}} -B build_install_test tests/installation_tests/find
|
cmake -G "${{matrix.gen}}" -A ${{matrix.arch}} -B build_install_test tests/installation_tests/find
|
||||||
cmake --build build_install_test --config ${{build_type}}
|
cmake --build build_install_test --config ${{matrix.build_type}}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
name: VS17-CLANG-CI
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
ci:
|
||||||
|
if: >-
|
||||||
|
! contains(toJSON(github.event.commits.*.message), '[skip ci]') &&
|
||||||
|
! contains(toJSON(github.event.commits.*.message), '[skip github]')
|
||||||
|
name: windows-vs17
|
||||||
|
runs-on: windows-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- {gen: Visual Studio 17 2022, arch: x64, build_type: Debug}
|
||||||
|
- {gen: Visual Studio 17 2022, arch: x64, build_type: Release}
|
||||||
|
- {gen: Visual Studio 17 2022, arch: x64, build_type: RelWithDebInfo}
|
||||||
|
steps:
|
||||||
|
- name: checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Configure
|
||||||
|
run: |
|
||||||
|
cmake -G "${{matrix.gen}}" -A ${{matrix.arch}} -T ClangCL -DSIMDJSON_DEVELOPER_MODE=ON -DSIMDJSON_COMPETITION=OFF -B build
|
||||||
|
- name: Build
|
||||||
|
run: cmake --build build --config ${{matrix.build_type}} --verbose
|
||||||
|
- name: Run tests
|
||||||
|
run: |
|
||||||
|
cd build
|
||||||
|
ctest -C ${{matrix.build_type}} -LE explicitonly --output-on-failure
|
||||||
|
- name: Install
|
||||||
|
run: |
|
||||||
|
cmake --install build --config ${{matrix.build_type}}
|
||||||
|
- name: Test Installation
|
||||||
|
run: |
|
||||||
|
cmake -G "${{matrix.gen}}" -A ${{matrix.arch}} -B build_install_test tests/installation_tests/find
|
||||||
|
cmake --build build_install_test --config ${{matrix.build_type}}
|
||||||
Vendored
+18
-1
@@ -109,6 +109,23 @@
|
|||||||
"numbers": "cpp",
|
"numbers": "cpp",
|
||||||
"semaphore": "cpp",
|
"semaphore": "cpp",
|
||||||
"stop_token": "cpp",
|
"stop_token": "cpp",
|
||||||
"cfenv": "cpp"
|
"cfenv": "cpp",
|
||||||
|
"format": "cpp",
|
||||||
|
"xlocmes": "cpp",
|
||||||
|
"xlocmon": "cpp",
|
||||||
|
"xlocnum": "cpp",
|
||||||
|
"xloctime": "cpp",
|
||||||
|
"xutility": "cpp",
|
||||||
|
"coroutine": "cpp",
|
||||||
|
"xfacet": "cpp",
|
||||||
|
"xhash": "cpp",
|
||||||
|
"xiosbase": "cpp",
|
||||||
|
"xlocale": "cpp",
|
||||||
|
"xlocbuf": "cpp",
|
||||||
|
"xlocinfo": "cpp",
|
||||||
|
"xmemory": "cpp",
|
||||||
|
"xstring": "cpp",
|
||||||
|
"xtr1common": "cpp",
|
||||||
|
"xtree": "cpp"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -13,7 +13,7 @@ struct nlohmann_json {
|
|||||||
auto root = nlohmann::json::parse(json.data(), json.data() + json.size());
|
auto root = nlohmann::json::parse(json.data(), json.data() + json.size());
|
||||||
for (auto tweet : root["statuses"]) {
|
for (auto tweet : root["statuses"]) {
|
||||||
if (tweet["id"] == find_id) {
|
if (tweet["id"] == find_id) {
|
||||||
result = tweet["text"];
|
result = to_string(tweet["text"]);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,8 +26,8 @@ struct nlohmann_json {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result.text = top_tweet["text"];
|
result.text = to_string(top_tweet["text"]);
|
||||||
result.screen_name = top_tweet["user"]["screen_name"];
|
result.screen_name = to_string(top_tweet["user"]["screen_name"]);
|
||||||
return result.retweet_count != -1;
|
return result.retweet_count != -1;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
+210
-7
@@ -17,6 +17,8 @@ An overview of what you need to know to use simdjson, with examples.
|
|||||||
- [Using the parsed JSON](#using-the-parsed-json)
|
- [Using the parsed JSON](#using-the-parsed-json)
|
||||||
- [Using the parsed JSON: additional examples](#using-the-parsed-json-additional-examples)
|
- [Using the parsed JSON: additional examples](#using-the-parsed-json-additional-examples)
|
||||||
- [Adding support for custom types](#adding-support-for-custom-types)
|
- [Adding support for custom types](#adding-support-for-custom-types)
|
||||||
|
- [1. Specialize `simdjson::ondemand::value::get` to get custom types](#1-specialize-simdjsonondemandvalueget-to-get-custom-types)
|
||||||
|
- [2. Use `tag_invoke` for custom types (C++20)](#2-use-tag_invoke-for-custom-types-c20)
|
||||||
- [Minifying JSON strings without parsing](#minifying-json-strings-without-parsing)
|
- [Minifying JSON strings without parsing](#minifying-json-strings-without-parsing)
|
||||||
- [UTF-8 validation (alone)](#utf-8-validation-alone)
|
- [UTF-8 validation (alone)](#utf-8-validation-alone)
|
||||||
- [JSON Pointer](#json-pointer)
|
- [JSON Pointer](#json-pointer)
|
||||||
@@ -788,6 +790,25 @@ for (ondemand::object points : parser.iterate(points_json)) {
|
|||||||
Adding support for custom types
|
Adding support for custom types
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
|
There are 2 main ways provided by simdjson to deserialize a value into a custom type:
|
||||||
|
|
||||||
|
1. Provide a [**template specialization** for member functions](https://en.cppreference.com/w/cpp/language/template_specialization#Members_of_specializations)
|
||||||
|
1. Specialize `simdjson::ondemand::document::get` for the whole document
|
||||||
|
2. Specialize `simdjson::ondemand::value::get` for each value
|
||||||
|
2. Using `tag_invoke` *(the recommended way if your system supports C++20 or better)*
|
||||||
|
|
||||||
|
The differences between the two approaches are as follows:
|
||||||
|
|
||||||
|
1. Your compiler needs to support C++20 for `tag_invoke`.
|
||||||
|
2. The first way limits you to know your type fully, but in the `tag_invoke` way, you can use C++20 concepts and template meta programming as well.
|
||||||
|
3. Another difference between the two ways is that in `tag_invoke` way you may or may not mark your deserialization function (`tag_invoke` itself) as `noexcept`, but in the
|
||||||
|
*template specialization* way (the first way) you HAVE TO mark your specialization as `noexcept` which means that you may need to catch exceptions so
|
||||||
|
that your function does not throw any exception all the while it potentially can (for example any type like `std::string`, `std::vector`, etc. that has an allocator can potentially throw exceptions).
|
||||||
|
4. Another difference is that the `tag_invoke` way can work on both `document` and `value` but in the first way you have to provide 2 distinct specializations.
|
||||||
|
5. If you by mistake use both way with each other, the *specialization way* will be used silently due to backward-compatibility.
|
||||||
|
|
||||||
|
### 1. Specialize `simdjson::ondemand::value::get` to get custom types
|
||||||
|
|
||||||
Suppose you have your own types, such as a `Car` struct:
|
Suppose you have your own types, such as a `Car` struct:
|
||||||
|
|
||||||
```C++
|
```C++
|
||||||
@@ -821,9 +842,14 @@ type:
|
|||||||
```
|
```
|
||||||
|
|
||||||
We may do so by providing additional template definitions to the `ondemand::value` type.
|
We may do so by providing additional template definitions to the `ondemand::value` type.
|
||||||
We may start by providing a definition for `std::vector<double>` as follows:
|
We may start by providing a definition for `std::vector<double>` as follows. Observe
|
||||||
|
how we guard the code with `#ifndef __cpp_concepts`: that is because the necessary code
|
||||||
|
is automatically provided by simdjson if C++20 (and concepts) are available.
|
||||||
|
See [Use `tag_invoke` for custom types](#2-use-tag_invoke-for-custom-types-c20) if you have
|
||||||
|
C++20 support.
|
||||||
|
|
||||||
```c++
|
```c++
|
||||||
|
#ifndef __cpp_concepts // because the code is unnecessary with C++20
|
||||||
template <>
|
template <>
|
||||||
simdjson_inline simdjson_result<std::vector<double>>
|
simdjson_inline simdjson_result<std::vector<double>>
|
||||||
simdjson::ondemand::value::get() noexcept {
|
simdjson::ondemand::value::get() noexcept {
|
||||||
@@ -835,10 +861,11 @@ simdjson::ondemand::value::get() noexcept {
|
|||||||
double val;
|
double val;
|
||||||
error = v.get_double().get(val);
|
error = v.get_double().get(val);
|
||||||
if (error) { return error; }
|
if (error) { return error; }
|
||||||
vec.push_back(val);
|
try { vec.push_back(val); } catch (...) { return simdjson::UNEXPECTED_ERROR; }
|
||||||
}
|
}
|
||||||
return vec;
|
return vec;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
```
|
```
|
||||||
|
|
||||||
We may then provide support for our `Car` struct:
|
We may then provide support for our `Car` struct:
|
||||||
@@ -856,6 +883,7 @@ simdjson_inline simdjson_result<Car> simdjson::ondemand::value::get() noexcept {
|
|||||||
raw_json_string key;
|
raw_json_string key;
|
||||||
error = field.key().get(key);
|
error = field.key().get(key);
|
||||||
if (error) { return error; }
|
if (error) { return error; }
|
||||||
|
|
||||||
if (key == "make") {
|
if (key == "make") {
|
||||||
error = field.value().get_string(car.make);
|
error = field.value().get_string(car.make);
|
||||||
if (error) { return error; }
|
if (error) { return error; }
|
||||||
@@ -867,7 +895,7 @@ simdjson_inline simdjson_result<Car> simdjson::ondemand::value::get() noexcept {
|
|||||||
if (error) { return error; }
|
if (error) { return error; }
|
||||||
} else if (key == "tire_pressure") {
|
} else if (key == "tire_pressure") {
|
||||||
error = field.value().get<std::vector<double>>().get(car.tire_pressure);
|
error = field.value().get<std::vector<double>>().get(car.tire_pressure);
|
||||||
if (auto error) { return error; }
|
if (error) { return error; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return car;
|
return car;
|
||||||
@@ -893,6 +921,7 @@ struct Car {
|
|||||||
std::vector<double> tire_pressure;
|
std::vector<double> tire_pressure;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifndef __cpp_concepts // because the code is unnecessary with C++20
|
||||||
template <>
|
template <>
|
||||||
simdjson_inline simdjson_result<std::vector<double>>
|
simdjson_inline simdjson_result<std::vector<double>>
|
||||||
simdjson::ondemand::value::get() noexcept {
|
simdjson::ondemand::value::get() noexcept {
|
||||||
@@ -908,6 +937,7 @@ simdjson::ondemand::value::get() noexcept {
|
|||||||
}
|
}
|
||||||
return vec;
|
return vec;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
@@ -950,7 +980,7 @@ int main(void) {
|
|||||||
ondemand::parser parser;
|
ondemand::parser parser;
|
||||||
ondemand::document doc = parser.iterate(json);
|
ondemand::document doc = parser.iterate(json);
|
||||||
for (auto val : doc) {
|
for (auto val : doc) {
|
||||||
Car c(val);
|
Car c(val); // an exception may be thrown
|
||||||
std::cout << c.make << std::endl;
|
std::cout << c.make << std::endl;
|
||||||
}
|
}
|
||||||
direct();
|
direct();
|
||||||
@@ -958,7 +988,7 @@ int main(void) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Observe that we require an explicit cast (`Car c(val)` instead of `for (Car c : doc) {`): it is by design.
|
Observe that we require an explicit cast (`Car c(val)` instead of `for (Car c : doc) {`): it is by design. We require explicit casting.
|
||||||
|
|
||||||
If you prefer to avoid exceptions, you may modify the `main` function as follows:
|
If you prefer to avoid exceptions, you may modify the `main` function as follows:
|
||||||
|
|
||||||
@@ -1009,6 +1039,7 @@ struct Car {
|
|||||||
std::vector<double> tire_pressure;
|
std::vector<double> tire_pressure;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifndef __cpp_concepts // because the code is unnecessary with C++20
|
||||||
template <>
|
template <>
|
||||||
simdjson_inline simdjson_result<std::vector<double>>
|
simdjson_inline simdjson_result<std::vector<double>>
|
||||||
simdjson::ondemand::value::get() noexcept {
|
simdjson::ondemand::value::get() noexcept {
|
||||||
@@ -1022,7 +1053,7 @@ simdjson::ondemand::value::get() noexcept {
|
|||||||
}
|
}
|
||||||
return vec;
|
return vec;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
simdjson_inline simdjson_result<Car> simdjson::ondemand::document::get() & noexcept {
|
simdjson_inline simdjson_result<Car> simdjson::ondemand::document::get() & noexcept {
|
||||||
@@ -1066,6 +1097,178 @@ int main(void) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### 2. Use `tag_invoke` for custom types (C++20)
|
||||||
|
|
||||||
|
A standard approach to provide support for deserialization is to add a `tag_invoke` function
|
||||||
|
in your own class:
|
||||||
|
|
||||||
|
```C++
|
||||||
|
/**
|
||||||
|
* A custom type that we want to parse.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct Car {
|
||||||
|
std::string make;
|
||||||
|
std::string model;
|
||||||
|
int year = 0;
|
||||||
|
std::vector<double> tire_pressure;
|
||||||
|
|
||||||
|
friend simdjson_result<Car>
|
||||||
|
tag_invoke(simdjson::deserialize_tag, std::type_identity<Car>, auto &val) {
|
||||||
|
simdjson::ondemand::object obj;
|
||||||
|
auto error = val.get_object().get(obj);
|
||||||
|
if (error) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
Car car{};
|
||||||
|
// Instead of repeatedly obj["something"], we iterate through the object
|
||||||
|
// which we expect to be faster.
|
||||||
|
for (auto field : obj) {
|
||||||
|
simdjson::ondemand::raw_json_string key;
|
||||||
|
error = field.key().get(key);
|
||||||
|
if (error) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
if (key == "make") {
|
||||||
|
error = field.value().get_string(car.make);
|
||||||
|
if (error) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
} else if (key == "model") {
|
||||||
|
error = field.value().get_string(car.model);
|
||||||
|
if (error) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
} else if (key == "year") {
|
||||||
|
error = field.value().get(car.year);
|
||||||
|
if (error) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
} else if (key == "tire_pressure") {
|
||||||
|
error = field.value().get(car.tire_pressure);
|
||||||
|
if (error) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return car;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
Let us explain each argument of `tag_invoke`:
|
||||||
|
|
||||||
|
- `simdjson::deserialize_tag`: it is the tag for Customization Point Object (CPO)
|
||||||
|
- `std::type_identity<T>`: We specify the custom type we want here
|
||||||
|
- `simdjson::ondemand::value&` or `simdjson::ondemand::document&`: the value or document that we want to deserialize from; you may want to just specify `auto&` to capture both of them.
|
||||||
|
|
||||||
|
You can use it like so:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
simdjson::padded_string json =
|
||||||
|
R"( { "make": "Toyota", "model": "Camry", "year": 2018,
|
||||||
|
"tire_pressure": [ 40.1, 39.9 ] })"_padded;
|
||||||
|
simdjson::ondemand::parser parser;
|
||||||
|
simdjson::ondemand::document doc = parser.iterate(json);
|
||||||
|
Car c(doc);
|
||||||
|
std::cout << c.make << std::endl;
|
||||||
|
```
|
||||||
|
|
||||||
|
Observe how we first get an instance of `document` and then we cast.
|
||||||
|
|
||||||
|
You can also handle errors explicitly:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
simdjson::padded_string json =
|
||||||
|
R"( { "make": "Toyota", "model": "Camry", "year": 2018,
|
||||||
|
"tire_pressure": [ 40.1, 39.9 ] })"_padded;
|
||||||
|
simdjson::ondemand::parser parser;
|
||||||
|
simdjson::ondemand::document doc = parser.iterate(json);
|
||||||
|
Car c;
|
||||||
|
auto error = doc.get(c);
|
||||||
|
if(error) { std::cerr << simdjson::error_message(error); return false; }
|
||||||
|
std::cout << c.make << std::endl;
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also read instances of `Car` from an array or an object:
|
||||||
|
```cpp
|
||||||
|
simdjson::padded_string json =
|
||||||
|
R"( [ { "make": "Toyota", "model": "Camry", "year": 2018,
|
||||||
|
"tire_pressure": [ 40.1, 39.9 ] },
|
||||||
|
{ "make": "Kia", "model": "Soul", "year": 2012,
|
||||||
|
"tire_pressure": [ 30.1, 31.0 ] },
|
||||||
|
{ "make": "Toyota", "model": "Tercel", "year": 1999,
|
||||||
|
"tire_pressure": [ 29.8, 30.0 ] }
|
||||||
|
])"_padded;
|
||||||
|
|
||||||
|
simdjson::ondemand::parser parser;
|
||||||
|
simdjson::ondemand::document doc = parser.iterate(json);
|
||||||
|
for (auto val : doc) {
|
||||||
|
Car c(val); // an exception may be thrown
|
||||||
|
std::cout << c.year << std::endl;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Observe how we first get a generic (`val`) which we cast to `Car`. It is by design: we require
|
||||||
|
explicit casting. The cast may throw an exception.
|
||||||
|
|
||||||
|
Once more, you can handle errors explicitly:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
simdjson::ondemand::parser parser;
|
||||||
|
simdjson::ondemand::document doc = parser.iterate(json);
|
||||||
|
for (auto val : doc) {
|
||||||
|
Car c;
|
||||||
|
auto error = val.get(c);
|
||||||
|
if(error) { std::cerr << simdjson::error_message(error) << std::endl; return false; }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also use the custom `Car` type as part of a template such as `std::vector`:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
simdjson::ondemand::parser parser;
|
||||||
|
simdjson::ondemand::document doc = parser.iterate(json);
|
||||||
|
std::vector<Car> cars(doc);
|
||||||
|
// visual studio users need an explicit call:
|
||||||
|
// std::vector<Car> cars = doc.get<std::vector<Car>>();
|
||||||
|
// because the compiler does not know whether to convert
|
||||||
|
// doc to an unsigned int or to a vector.
|
||||||
|
for(Car& c : cars) {
|
||||||
|
std::cout << c.year << std::endl;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also extend support to arbitrary templates.
|
||||||
|
Suppose your custom types are `std::unique_ptr<any type>`,
|
||||||
|
you could add the following `tag_invoke`:
|
||||||
|
|
||||||
|
```C++
|
||||||
|
namespace simdjson {
|
||||||
|
|
||||||
|
// This tag_invoke MUST be inside simdjson namespace since we can't make it a friend of unique_ptr
|
||||||
|
template <typename T>
|
||||||
|
auto tag_invoke(deserialize_tag, std::type_identity<std::unique_ptr<T>>, auto &val) {
|
||||||
|
return simdjson_result{std::make_unique<T>(val.template get<T>())};
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace simdjson
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also mark your `tag_invoke` function as `noexcept` and we will obey that, unlike the *template specialization* way.
|
||||||
|
|
||||||
|
You would use it like this:
|
||||||
|
```C++
|
||||||
|
int main() {
|
||||||
|
auto const json = R"( { "make": "Toyota", "model": "Camry", "year": 2018,
|
||||||
|
"tire_pressure": [ 40.1, 39.9 ] })"_padded;
|
||||||
|
simdjson::ondemand::parser parser;
|
||||||
|
simdjson::ondemand::document doc = parser.iterate(json);
|
||||||
|
std::unique_ptr<Car> c(doc);
|
||||||
|
std::cout << c->make << std::endl;
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
Minifying JSON strings without parsing
|
Minifying JSON strings without parsing
|
||||||
----------------------
|
----------------------
|
||||||
@@ -1343,7 +1546,7 @@ Notice how we can retrieve the exact error condition (in this instance `simdjson
|
|||||||
from the exception.
|
from the exception.
|
||||||
|
|
||||||
We can write a "quick start" example where we attempt to parse the following JSON file and access some data, without triggering exceptions:
|
We can write a "quick start" example where we attempt to parse the following JSON file and access some data, without triggering exceptions:
|
||||||
```JavaScript
|
```JSON
|
||||||
{
|
{
|
||||||
"statuses": [
|
"statuses": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -50,4 +50,16 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __has_include
|
||||||
|
#if __has_include(<version>)
|
||||||
|
#include <version>
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cpp_concepts
|
||||||
|
#include <utility>
|
||||||
|
#define SIMDJSON_SUPPORTS_DESERIALIZATION 1
|
||||||
|
#else // __cpp_concepts
|
||||||
|
#define SIMDJSON_SUPPORTS_DESERIALIZATION 0
|
||||||
|
#endif
|
||||||
#endif // SIMDJSON_COMPILER_CHECK_H
|
#endif // SIMDJSON_COMPILER_CHECK_H
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
// Stuff other things depend on
|
// Stuff other things depend on
|
||||||
#include "simdjson/generic/ondemand/base.h"
|
#include "simdjson/generic/ondemand/base.h"
|
||||||
|
#include "simdjson/generic/ondemand/deserialize.h"
|
||||||
#include "simdjson/generic/ondemand/value_iterator.h"
|
#include "simdjson/generic/ondemand/value_iterator.h"
|
||||||
#include "simdjson/generic/ondemand/value.h"
|
#include "simdjson/generic/ondemand/value.h"
|
||||||
#include "simdjson/generic/ondemand/logger.h"
|
#include "simdjson/generic/ondemand/logger.h"
|
||||||
@@ -23,9 +24,13 @@
|
|||||||
#include "simdjson/generic/ondemand/object_iterator.h"
|
#include "simdjson/generic/ondemand/object_iterator.h"
|
||||||
#include "simdjson/generic/ondemand/serialization.h"
|
#include "simdjson/generic/ondemand/serialization.h"
|
||||||
|
|
||||||
|
// Deserialization for standard types
|
||||||
|
#include "simdjson/generic/ondemand/std_deserialize.h"
|
||||||
|
|
||||||
// Inline definitions
|
// Inline definitions
|
||||||
#include "simdjson/generic/ondemand/array-inl.h"
|
#include "simdjson/generic/ondemand/array-inl.h"
|
||||||
#include "simdjson/generic/ondemand/array_iterator-inl.h"
|
#include "simdjson/generic/ondemand/array_iterator-inl.h"
|
||||||
|
#include "simdjson/generic/ondemand/value-inl.h"
|
||||||
#include "simdjson/generic/ondemand/document-inl.h"
|
#include "simdjson/generic/ondemand/document-inl.h"
|
||||||
#include "simdjson/generic/ondemand/document_stream-inl.h"
|
#include "simdjson/generic/ondemand/document_stream-inl.h"
|
||||||
#include "simdjson/generic/ondemand/field-inl.h"
|
#include "simdjson/generic/ondemand/field-inl.h"
|
||||||
@@ -38,5 +43,6 @@
|
|||||||
#include "simdjson/generic/ondemand/raw_json_string-inl.h"
|
#include "simdjson/generic/ondemand/raw_json_string-inl.h"
|
||||||
#include "simdjson/generic/ondemand/serialization-inl.h"
|
#include "simdjson/generic/ondemand/serialization-inl.h"
|
||||||
#include "simdjson/generic/ondemand/token_iterator-inl.h"
|
#include "simdjson/generic/ondemand/token_iterator-inl.h"
|
||||||
#include "simdjson/generic/ondemand/value-inl.h"
|
|
||||||
#include "simdjson/generic/ondemand/value_iterator-inl.h"
|
#include "simdjson/generic/ondemand/value_iterator-inl.h"
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,114 @@
|
|||||||
|
#if SIMDJSON_SUPPORTS_DESERIALIZATION
|
||||||
|
|
||||||
|
#ifndef SIMDJSON_ONDEMAND_DESERIALIZE_H
|
||||||
|
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
#define SIMDJSON_ONDEMAND_DESERIALIZE_H
|
||||||
|
#include "simdjson/generic/ondemand/base.h"
|
||||||
|
#include "simdjson/generic/ondemand/array.h"
|
||||||
|
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
|
||||||
|
#include <concepts>
|
||||||
|
namespace simdjson {
|
||||||
|
|
||||||
|
namespace tag_invoke_fn_ns {
|
||||||
|
void tag_invoke();
|
||||||
|
|
||||||
|
struct tag_invoke_fn {
|
||||||
|
template <typename Tag, typename... Args>
|
||||||
|
requires requires(Tag tag, Args &&...args) {
|
||||||
|
tag_invoke(std::forward<Tag>(tag), std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
constexpr auto operator()(Tag tag, Args &&...args) const
|
||||||
|
noexcept(noexcept(tag_invoke(std::forward<Tag>(tag),
|
||||||
|
std::forward<Args>(args)...)))
|
||||||
|
-> decltype(tag_invoke(std::forward<Tag>(tag),
|
||||||
|
std::forward<Args>(args)...)) {
|
||||||
|
return tag_invoke(std::forward<Tag>(tag), std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace tag_invoke_fn_ns
|
||||||
|
|
||||||
|
inline namespace tag_invoke_ns {
|
||||||
|
inline constexpr tag_invoke_fn_ns::tag_invoke_fn tag_invoke = {};
|
||||||
|
} // namespace tag_invoke_ns
|
||||||
|
|
||||||
|
template <typename Tag, typename... Args>
|
||||||
|
concept tag_invocable = requires(Tag tag, Args... args) {
|
||||||
|
tag_invoke(std::forward<Tag>(tag), std::forward<Args>(args)...);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Tag, typename... Args>
|
||||||
|
concept nothrow_tag_invocable =
|
||||||
|
tag_invocable<Tag, Args...> && requires(Tag tag, Args... args) {
|
||||||
|
{
|
||||||
|
tag_invoke(std::forward<Tag>(tag), std::forward<Args>(args)...)
|
||||||
|
} noexcept;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Tag, typename... Args>
|
||||||
|
using tag_invoke_result =
|
||||||
|
std::invoke_result<decltype(tag_invoke), Tag, Args...>;
|
||||||
|
|
||||||
|
template <typename Tag, typename... Args>
|
||||||
|
using tag_invoke_result_t =
|
||||||
|
std::invoke_result_t<decltype(tag_invoke), Tag, Args...>;
|
||||||
|
|
||||||
|
template <auto &Tag> using tag_t = std::decay_t<decltype(Tag)>;
|
||||||
|
|
||||||
|
|
||||||
|
struct deserialize_tag;
|
||||||
|
|
||||||
|
/// These types are deserializable in a built-in way
|
||||||
|
template <typename> struct is_builtin_deserializable : std::false_type {};
|
||||||
|
template <> struct is_builtin_deserializable<int64_t> : std::true_type {};
|
||||||
|
template <> struct is_builtin_deserializable<uint64_t> : std::true_type {};
|
||||||
|
template <> struct is_builtin_deserializable<double> : std::true_type {};
|
||||||
|
template <> struct is_builtin_deserializable<bool> : std::true_type {};
|
||||||
|
template <> struct is_builtin_deserializable<SIMDJSON_IMPLEMENTATION::ondemand::array> : std::true_type {};
|
||||||
|
template <> struct is_builtin_deserializable<SIMDJSON_IMPLEMENTATION::ondemand::object> : std::true_type {};
|
||||||
|
template <> struct is_builtin_deserializable<SIMDJSON_IMPLEMENTATION::ondemand::value> : std::true_type {};
|
||||||
|
template <> struct is_builtin_deserializable<SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string> : std::true_type {};
|
||||||
|
template <> struct is_builtin_deserializable<std::string_view> : std::true_type {};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
concept is_builtin_deserializable_v = is_builtin_deserializable<T>::value;
|
||||||
|
|
||||||
|
template <typename T, typename ValT = SIMDJSON_IMPLEMENTATION::ondemand::value>
|
||||||
|
concept custom_deserializable = tag_invocable<deserialize_tag, ValT&, T&>;
|
||||||
|
|
||||||
|
template <typename T, typename ValT = SIMDJSON_IMPLEMENTATION::ondemand::value>
|
||||||
|
concept deserializable = custom_deserializable<T, ValT> || is_builtin_deserializable_v<T>;
|
||||||
|
|
||||||
|
template <typename T, typename ValT = SIMDJSON_IMPLEMENTATION::ondemand::value>
|
||||||
|
concept nothrow_custom_deserializable = nothrow_tag_invocable<deserialize_tag, ValT&, T&>;
|
||||||
|
|
||||||
|
// built-in types are noexcept and if an error happens, the value simply gets ignored and the error is returned.
|
||||||
|
template <typename T, typename ValT = SIMDJSON_IMPLEMENTATION::ondemand::value>
|
||||||
|
concept nothrow_deserializable = nothrow_custom_deserializable<T, ValT> || is_builtin_deserializable_v<T>;
|
||||||
|
|
||||||
|
/// Deserialize Tag
|
||||||
|
inline constexpr struct deserialize_tag {
|
||||||
|
using value_type = SIMDJSON_IMPLEMENTATION::ondemand::value;
|
||||||
|
using document_type = SIMDJSON_IMPLEMENTATION::ondemand::document;
|
||||||
|
|
||||||
|
// Customization Point for value
|
||||||
|
template <typename T>
|
||||||
|
requires custom_deserializable<T, value_type>
|
||||||
|
[[nodiscard]] constexpr /* error_code */ auto operator()(value_type &object, T& output) const noexcept(nothrow_custom_deserializable<T, value_type>) {
|
||||||
|
return tag_invoke(*this, object, output);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Customization Point for document
|
||||||
|
template <typename T>
|
||||||
|
requires custom_deserializable<T, document_type>
|
||||||
|
[[nodiscard]] constexpr /* error_code */ auto operator()(document_type &object, T& output) const noexcept(nothrow_custom_deserializable<T, document_type>) {
|
||||||
|
return tag_invoke(*this, object, output);
|
||||||
|
}
|
||||||
|
|
||||||
|
} deserialize{};
|
||||||
|
|
||||||
|
} // namespace simdjson
|
||||||
|
|
||||||
|
#endif // SIMDJSON_ONDEMAND_DESERIALIZE_H
|
||||||
|
#endif // SIMDJSON_SUPPORTS_DESERIALIZATION
|
||||||
|
|
||||||
@@ -13,7 +13,9 @@
|
|||||||
#include "simdjson/generic/ondemand/object-inl.h"
|
#include "simdjson/generic/ondemand/object-inl.h"
|
||||||
#include "simdjson/generic/ondemand/raw_json_string.h"
|
#include "simdjson/generic/ondemand/raw_json_string.h"
|
||||||
#include "simdjson/generic/ondemand/value.h"
|
#include "simdjson/generic/ondemand/value.h"
|
||||||
|
#include "simdjson/generic/ondemand/value-inl.h"
|
||||||
#include "simdjson/generic/ondemand/value_iterator-inl.h"
|
#include "simdjson/generic/ondemand/value_iterator-inl.h"
|
||||||
|
#include "simdjson/generic/ondemand/deserialize.h"
|
||||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
|
||||||
namespace simdjson {
|
namespace simdjson {
|
||||||
@@ -167,20 +169,16 @@ template<> simdjson_inline simdjson_result<int64_t> document::get() & noexcept {
|
|||||||
template<> simdjson_inline simdjson_result<bool> document::get() & noexcept { return get_bool(); }
|
template<> simdjson_inline simdjson_result<bool> document::get() & noexcept { return get_bool(); }
|
||||||
template<> simdjson_inline simdjson_result<value> document::get() & noexcept { return get_value(); }
|
template<> simdjson_inline simdjson_result<value> document::get() & noexcept { return get_value(); }
|
||||||
|
|
||||||
template<> simdjson_inline simdjson_result<raw_json_string> document::get() && noexcept { return get_raw_json_string(); }
|
template<> simdjson_inline error_code document::get(array& out) & noexcept { return get_array().get(out); }
|
||||||
template<> simdjson_inline simdjson_result<std::string_view> document::get() && noexcept { return get_string(false); }
|
template<> simdjson_inline error_code document::get(object& out) & noexcept { return get_object().get(out); }
|
||||||
template<> simdjson_inline simdjson_result<double> document::get() && noexcept { return std::forward<document>(*this).get_double(); }
|
template<> simdjson_inline error_code document::get(raw_json_string& out) & noexcept { return get_raw_json_string().get(out); }
|
||||||
template<> simdjson_inline simdjson_result<uint64_t> document::get() && noexcept { return std::forward<document>(*this).get_uint64(); }
|
template<> simdjson_inline error_code document::get(std::string_view& out) & noexcept { return get_string(false).get(out); }
|
||||||
template<> simdjson_inline simdjson_result<int64_t> document::get() && noexcept { return std::forward<document>(*this).get_int64(); }
|
template<> simdjson_inline error_code document::get(double& out) & noexcept { return get_double().get(out); }
|
||||||
template<> simdjson_inline simdjson_result<bool> document::get() && noexcept { return std::forward<document>(*this).get_bool(); }
|
template<> simdjson_inline error_code document::get(uint64_t& out) & noexcept { return get_uint64().get(out); }
|
||||||
template<> simdjson_inline simdjson_result<value> document::get() && noexcept { return get_value(); }
|
template<> simdjson_inline error_code document::get(int64_t& out) & noexcept { return get_int64().get(out); }
|
||||||
|
template<> simdjson_inline error_code document::get(bool& out) & noexcept { return get_bool().get(out); }
|
||||||
|
template<> simdjson_inline error_code document::get(value& out) & noexcept { return get_value().get(out); }
|
||||||
|
|
||||||
template<typename T> simdjson_inline error_code document::get(T &out) & noexcept {
|
|
||||||
return get<T>().get(out);
|
|
||||||
}
|
|
||||||
template<typename T> simdjson_inline error_code document::get(T &out) && noexcept {
|
|
||||||
return std::forward<document>(*this).get<T>().get(out);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if SIMDJSON_EXCEPTIONS
|
#if SIMDJSON_EXCEPTIONS
|
||||||
template <class T>
|
template <class T>
|
||||||
|
|||||||
@@ -4,8 +4,11 @@
|
|||||||
#define SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_H
|
#define SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_H
|
||||||
#include "simdjson/generic/ondemand/base.h"
|
#include "simdjson/generic/ondemand/base.h"
|
||||||
#include "simdjson/generic/ondemand/json_iterator.h"
|
#include "simdjson/generic/ondemand/json_iterator.h"
|
||||||
|
#include "simdjson/generic/ondemand/deserialize.h"
|
||||||
|
#include "simdjson/generic/ondemand/value.h"
|
||||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
|
||||||
|
|
||||||
namespace simdjson {
|
namespace simdjson {
|
||||||
namespace SIMDJSON_IMPLEMENTATION {
|
namespace SIMDJSON_IMPLEMENTATION {
|
||||||
namespace ondemand {
|
namespace ondemand {
|
||||||
@@ -178,24 +181,39 @@ public:
|
|||||||
* @returns A value of the given type, parsed from the JSON.
|
* @returns A value of the given type, parsed from the JSON.
|
||||||
* @returns INCORRECT_TYPE If the JSON value is not the given type.
|
* @returns INCORRECT_TYPE If the JSON value is not the given type.
|
||||||
*/
|
*/
|
||||||
template<typename T> simdjson_inline simdjson_result<T> get() & noexcept {
|
template <typename T>
|
||||||
// Unless the simdjson library or the user provides an inline implementation, calling this method should
|
simdjson_inline simdjson_result<T> get() &
|
||||||
// immediately fail.
|
#if SIMDJSON_SUPPORTS_DESERIALIZATION
|
||||||
static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. "
|
noexcept(custom_deserializable<T, document> ? nothrow_custom_deserializable<T, document> : true)
|
||||||
"The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, "
|
#else
|
||||||
"int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), "
|
noexcept
|
||||||
" get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template."
|
#endif
|
||||||
" You may also add support for custom types, see our documentation.");
|
{
|
||||||
|
static_assert(std::is_default_constructible<T>::value, "Cannot initialize the specified type.");
|
||||||
|
T out{};
|
||||||
|
SIMDJSON_TRY(get<T>(out));
|
||||||
|
return out;
|
||||||
}
|
}
|
||||||
/** @overload template<typename T> simdjson_result<T> get() & noexcept */
|
/**
|
||||||
template<typename T> simdjson_inline simdjson_result<T> get() && noexcept {
|
* @overload template<typename T> simdjson_result<T> get() & noexcept
|
||||||
// Unless the simdjson library or the user provides an inline implementation, calling this method should
|
*
|
||||||
// immediately fail.
|
* We disallow the use tag_invoke CPO on a moved document; it may create UB
|
||||||
static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. "
|
* if user uses `ondemand::array` or `ondemand::object` in their custom type.
|
||||||
"The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, "
|
*
|
||||||
"int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), "
|
* The member function is still remains specialize-able for compatibility
|
||||||
" get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template."
|
* reasons, but we completely disallow its use when a tag_invoke customization
|
||||||
" You may also add support for custom types, see our documentation.");
|
* is provided.
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
simdjson_inline simdjson_result<T> get() &&
|
||||||
|
#if SIMDJSON_SUPPORTS_DESERIALIZATION
|
||||||
|
noexcept(custom_deserializable<T, document> ? nothrow_custom_deserializable<T, document> : true)
|
||||||
|
#else
|
||||||
|
noexcept
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
static_assert(!std::is_same<T, array>::value && !std::is_same<T, object>::value, "You should never hold either an ondemand::array or ondemand::object without a corresponding ondemand::document being alive; that would be Undefined Behaviour.");
|
||||||
|
return static_cast<document&>(*this).get<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -209,7 +227,32 @@ public:
|
|||||||
* @returns INCORRECT_TYPE If the JSON value is not an object.
|
* @returns INCORRECT_TYPE If the JSON value is not an object.
|
||||||
* @returns SUCCESS If the parse succeeded and the out parameter was set to the value.
|
* @returns SUCCESS If the parse succeeded and the out parameter was set to the value.
|
||||||
*/
|
*/
|
||||||
template<typename T> simdjson_inline error_code get(T &out) & noexcept;
|
template<typename T>
|
||||||
|
simdjson_inline error_code get(T &out) &
|
||||||
|
#if SIMDJSON_SUPPORTS_DESERIALIZATION
|
||||||
|
noexcept(custom_deserializable<T, document> ? nothrow_custom_deserializable<T, document> : true)
|
||||||
|
#else
|
||||||
|
noexcept
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
#if SIMDJSON_SUPPORTS_DESERIALIZATION
|
||||||
|
if constexpr (custom_deserializable<T, document>) {
|
||||||
|
return deserialize(*this, out);
|
||||||
|
} else {
|
||||||
|
#endif // SIMDJSON_SUPPORTS_DESERIALIZATION
|
||||||
|
// Unless the simdjson library or the user provides an inline implementation, calling this method should
|
||||||
|
// immediately fail.
|
||||||
|
static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. "
|
||||||
|
"The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, "
|
||||||
|
"int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), "
|
||||||
|
" get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template."
|
||||||
|
" You may also add support for custom types, see our documentation.");
|
||||||
|
static_cast<void>(out); // to get rid of unused errors
|
||||||
|
return UNINITIALIZED;
|
||||||
|
#if SIMDJSON_SUPPORTS_DESERIALIZATION
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
/** @overload template<typename T> error_code get(T &out) & noexcept */
|
/** @overload template<typename T> error_code get(T &out) & noexcept */
|
||||||
template<typename T> simdjson_inline error_code get(T &out) && noexcept;
|
template<typename T> simdjson_inline error_code get(T &out) && noexcept;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,196 @@
|
|||||||
|
#if SIMDJSON_SUPPORTS_DESERIALIZATION
|
||||||
|
|
||||||
|
#ifndef SIMDJSON_ONDEMAND_DESERIALIZE_H
|
||||||
|
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
#define SIMDJSON_ONDEMAND_DESERIALIZE_H
|
||||||
|
#include "simdjson/generic/ondemand/base.h"
|
||||||
|
#include "simdjson/generic/ondemand/array.h"
|
||||||
|
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
|
||||||
|
#include <concepts>
|
||||||
|
#include <limits>
|
||||||
|
#include <list>
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace simdjson {
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
// Number deserialization
|
||||||
|
//////////////////////////////
|
||||||
|
|
||||||
|
template <std::unsigned_integral T>
|
||||||
|
error_code tag_invoke(deserialize_tag, auto &val, T &out) noexcept {
|
||||||
|
using limits = std::numeric_limits<T>;
|
||||||
|
|
||||||
|
uint64_t x;
|
||||||
|
SIMDJSON_TRY(val.get_uint64().get(x));
|
||||||
|
if (x > (limits::max)()) {
|
||||||
|
return NUMBER_OUT_OF_RANGE;
|
||||||
|
}
|
||||||
|
out = static_cast<T>(x);
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <std::floating_point T>
|
||||||
|
error_code tag_invoke(deserialize_tag, auto &val, T &out) noexcept {
|
||||||
|
double x;
|
||||||
|
SIMDJSON_TRY(val.get_double().get(x));
|
||||||
|
out = static_cast<T>(x);
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <std::signed_integral T>
|
||||||
|
error_code tag_invoke(deserialize_tag, auto &val, T &out) noexcept {
|
||||||
|
using limits = std::numeric_limits<T>;
|
||||||
|
|
||||||
|
int64_t x;
|
||||||
|
SIMDJSON_TRY(val.get_int64().get(x));
|
||||||
|
if (x > (limits::max)() || x < (limits::min)()) {
|
||||||
|
return NUMBER_OUT_OF_RANGE;
|
||||||
|
}
|
||||||
|
out = static_cast<T>(x);
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
// STL list deserialization
|
||||||
|
//////////////////////////////
|
||||||
|
|
||||||
|
template <typename T, typename AllocT, typename ValT>
|
||||||
|
error_code tag_invoke(deserialize_tag, ValT &val,
|
||||||
|
std::list<T, AllocT> &out) noexcept(false) {
|
||||||
|
|
||||||
|
// For better error messages, don't use these as constraints on
|
||||||
|
// the tag_invoke CPO.
|
||||||
|
static_assert(
|
||||||
|
deserializable<T, ValT>,
|
||||||
|
"The specified type inside the list must itself be deserializable");
|
||||||
|
static_assert(
|
||||||
|
std::is_default_constructible_v<T>,
|
||||||
|
"The specified type inside the list must default constructible.");
|
||||||
|
|
||||||
|
SIMDJSON_IMPLEMENTATION::ondemand::array arr;
|
||||||
|
SIMDJSON_TRY(val.get_array().get(arr));
|
||||||
|
for (auto v : arr) {
|
||||||
|
if (auto const err = v.get<T>().get(out.emplace_back()); err) {
|
||||||
|
// If an error occurs, the empty element that we just inserted gets
|
||||||
|
// removed. We're not using a temp variable because if T is a heavy type,
|
||||||
|
// we want the valid path to be the fast path and the slow path be the
|
||||||
|
// path that has errors in it.
|
||||||
|
static_cast<void>(out.pop_back());
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
// std::string deserialization
|
||||||
|
//////////////////////////////
|
||||||
|
|
||||||
|
template <typename CharT,
|
||||||
|
typename TraitsT,
|
||||||
|
typename AllocT,
|
||||||
|
typename ValT>
|
||||||
|
error_code tag_invoke(deserialize_tag, ValT &val, std::basic_string<CharT, TraitsT, AllocT> &out) noexcept(false) {
|
||||||
|
using string_type = std::basic_string<CharT, TraitsT, AllocT>;
|
||||||
|
|
||||||
|
if constexpr (std::same_as<string_type, string_type>) {
|
||||||
|
SIMDJSON_TRY(val.get_string(out));
|
||||||
|
} else {
|
||||||
|
// todo: optimize performance
|
||||||
|
std::string tmp;
|
||||||
|
SIMDJSON_TRY(val.get_string(tmp));
|
||||||
|
for (auto const ch : tmp) {
|
||||||
|
out.push_back(ch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
// STL Vector deserialization
|
||||||
|
//////////////////////////////
|
||||||
|
|
||||||
|
/**
|
||||||
|
* STL containers have several constructors including one that takes a single
|
||||||
|
* size argument. Thus, some compilers (Visual Studio) will not be able to
|
||||||
|
* disambiguate between the size and container constructor. Users should
|
||||||
|
* explicitly specify the type of the container as needed: e.g.,
|
||||||
|
* doc.get<std::vector<int>>().
|
||||||
|
*/
|
||||||
|
template <typename T, typename AllocT, typename ValT>
|
||||||
|
error_code tag_invoke(deserialize_tag, ValT &val,
|
||||||
|
std::vector<T, AllocT> &out) noexcept(false) {
|
||||||
|
|
||||||
|
// For better error messages, don't use these as constraints on
|
||||||
|
// the tag_invoke CPO.
|
||||||
|
static_assert(
|
||||||
|
deserializable<T, ValT>,
|
||||||
|
"The specified type inside the vector must itself be deserializable");
|
||||||
|
static_assert(
|
||||||
|
std::is_default_constructible_v<T>,
|
||||||
|
"The specified type inside the vector must default constructible.");
|
||||||
|
|
||||||
|
SIMDJSON_IMPLEMENTATION::ondemand::array arr;
|
||||||
|
SIMDJSON_TRY(val.get_array().get(arr));
|
||||||
|
for (auto v : arr) {
|
||||||
|
if (auto const err = v.get<T>().get(out.emplace_back()); err) {
|
||||||
|
// If an error occurs, the empty element that we just inserted gets
|
||||||
|
// removed. We're not using a temp variable because if T is a heavy type,
|
||||||
|
// we want the valid path to be the fast path and the slow path be the
|
||||||
|
// path that has errors in it.
|
||||||
|
static_cast<void>(out.pop_back());
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
// std::unique_ptr deserialization
|
||||||
|
//////////////////////////////
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This CPO (Customization Point Object) will help deserialize into
|
||||||
|
* `unique_ptr`s.
|
||||||
|
*
|
||||||
|
* If constructing T is nothrow, this conversion should be nothrow as well since
|
||||||
|
* we return MEMALLOC if we're not able to allocate memory instead of throwing
|
||||||
|
* the the error message.
|
||||||
|
*
|
||||||
|
* @tparam T The type inside the unique_ptr
|
||||||
|
* @tparam Deleter The Deleter of the unique_ptr
|
||||||
|
* @tparam ValT document/value type
|
||||||
|
* @param val document/value
|
||||||
|
* @param out output unique_ptr
|
||||||
|
* @return status of the conversion
|
||||||
|
*/
|
||||||
|
template <typename T, typename Deleter, typename ValT>
|
||||||
|
error_code tag_invoke(deserialize_tag, ValT &val,
|
||||||
|
std::unique_ptr<T, Deleter>
|
||||||
|
&out) noexcept(nothrow_deserializable<T, ValT>) {
|
||||||
|
|
||||||
|
// For better error messages, don't use these as constraints on
|
||||||
|
// the tag_invoke CPO.
|
||||||
|
static_assert(
|
||||||
|
deserializable<T, ValT>,
|
||||||
|
"The specified type inside the unique_ptr must itself be deserializable");
|
||||||
|
static_assert(
|
||||||
|
std::is_default_constructible_v<T>,
|
||||||
|
"The specified type inside the unique_ptr must default constructible.");
|
||||||
|
|
||||||
|
auto ptr = new (std::nothrow) T();
|
||||||
|
if (ptr == nullptr) {
|
||||||
|
return MEMALLOC;
|
||||||
|
}
|
||||||
|
SIMDJSON_TRY(val.template get<T>(*ptr));
|
||||||
|
out.reset(ptr);
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
} // namespace simdjson
|
||||||
|
|
||||||
|
#endif // SIMDJSON_ONDEMAND_DESERIALIZE_H
|
||||||
|
#endif // SIMDJSON_SUPPORTS_DESERIALIZATION
|
||||||
@@ -80,6 +80,7 @@ simdjson_inline simdjson_result<bool> value::get_bool() noexcept {
|
|||||||
simdjson_inline simdjson_result<bool> value::is_null() noexcept {
|
simdjson_inline simdjson_result<bool> value::is_null() noexcept {
|
||||||
return iter.is_null();
|
return iter.is_null();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<> simdjson_inline simdjson_result<array> value::get() noexcept { return get_array(); }
|
template<> simdjson_inline simdjson_result<array> value::get() noexcept { return get_array(); }
|
||||||
template<> simdjson_inline simdjson_result<object> value::get() noexcept { return get_object(); }
|
template<> simdjson_inline simdjson_result<object> value::get() noexcept { return get_object(); }
|
||||||
template<> simdjson_inline simdjson_result<raw_json_string> value::get() noexcept { return get_raw_json_string(); }
|
template<> simdjson_inline simdjson_result<raw_json_string> value::get() noexcept { return get_raw_json_string(); }
|
||||||
@@ -90,9 +91,16 @@ template<> simdjson_inline simdjson_result<uint64_t> value::get() noexcept { ret
|
|||||||
template<> simdjson_inline simdjson_result<int64_t> value::get() noexcept { return get_int64(); }
|
template<> simdjson_inline simdjson_result<int64_t> value::get() noexcept { return get_int64(); }
|
||||||
template<> simdjson_inline simdjson_result<bool> value::get() noexcept { return get_bool(); }
|
template<> simdjson_inline simdjson_result<bool> value::get() noexcept { return get_bool(); }
|
||||||
|
|
||||||
template<typename T> simdjson_inline error_code value::get(T &out) noexcept {
|
|
||||||
return get<T>().get(out);
|
template<> simdjson_inline error_code value::get(array& out) noexcept { return get_array().get(out); }
|
||||||
}
|
template<> simdjson_inline error_code value::get(object& out) noexcept { return get_object().get(out); }
|
||||||
|
template<> simdjson_inline error_code value::get(raw_json_string& out) noexcept { return get_raw_json_string().get(out); }
|
||||||
|
template<> simdjson_inline error_code value::get(std::string_view& out) noexcept { return get_string(false).get(out); }
|
||||||
|
template<> simdjson_inline error_code value::get(number& out) noexcept { return get_number().get(out); }
|
||||||
|
template<> simdjson_inline error_code value::get(double& out) noexcept { return get_double().get(out); }
|
||||||
|
template<> simdjson_inline error_code value::get(uint64_t& out) noexcept { return get_uint64().get(out); }
|
||||||
|
template<> simdjson_inline error_code value::get(int64_t& out) noexcept { return get_int64().get(out); }
|
||||||
|
template<> simdjson_inline error_code value::get(bool& out) noexcept { return get_bool().get(out); }
|
||||||
|
|
||||||
#if SIMDJSON_EXCEPTIONS
|
#if SIMDJSON_EXCEPTIONS
|
||||||
template <class T>
|
template <class T>
|
||||||
@@ -416,6 +424,12 @@ simdjson_inline simdjson_result<bool> simdjson_result<SIMDJSON_IMPLEMENTATION::o
|
|||||||
return first.is_null();
|
return first.is_null();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<> simdjson_inline error_code simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::get<SIMDJSON_IMPLEMENTATION::ondemand::value>(SIMDJSON_IMPLEMENTATION::ondemand::value &out) noexcept {
|
||||||
|
if (error()) { return error(); }
|
||||||
|
out = first;
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T> simdjson_inline simdjson_result<T> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::get() noexcept {
|
template<typename T> simdjson_inline simdjson_result<T> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::get() noexcept {
|
||||||
if (error()) { return error(); }
|
if (error()) { return error(); }
|
||||||
return first.get<T>();
|
return first.get<T>();
|
||||||
@@ -429,11 +443,6 @@ template<> simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::va
|
|||||||
if (error()) { return error(); }
|
if (error()) { return error(); }
|
||||||
return std::move(first);
|
return std::move(first);
|
||||||
}
|
}
|
||||||
template<> simdjson_inline error_code simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::get<SIMDJSON_IMPLEMENTATION::ondemand::value>(SIMDJSON_IMPLEMENTATION::ondemand::value &out) noexcept {
|
|
||||||
if (error()) { return error(); }
|
|
||||||
out = first;
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::json_type> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::type() noexcept {
|
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::json_type> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::type() noexcept {
|
||||||
if (error()) { return error(); }
|
if (error()) { return error(); }
|
||||||
@@ -467,7 +476,7 @@ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::number> simdj
|
|||||||
template <class T>
|
template <class T>
|
||||||
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::operator T() noexcept(false) {
|
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::operator T() noexcept(false) {
|
||||||
if (error()) { throw simdjson_error(error()); }
|
if (error()) { throw simdjson_error(error()); }
|
||||||
return static_cast<T>(first);
|
return first.get<T>();
|
||||||
}
|
}
|
||||||
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::operator SIMDJSON_IMPLEMENTATION::ondemand::array() noexcept(false) {
|
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::operator SIMDJSON_IMPLEMENTATION::ondemand::array() noexcept(false) {
|
||||||
if (error()) { throw simdjson_error(error()); }
|
if (error()) { throw simdjson_error(error()); }
|
||||||
|
|||||||
@@ -5,12 +5,15 @@
|
|||||||
#include "simdjson/generic/ondemand/base.h"
|
#include "simdjson/generic/ondemand/base.h"
|
||||||
#include "simdjson/generic/implementation_simdjson_result_base.h"
|
#include "simdjson/generic/implementation_simdjson_result_base.h"
|
||||||
#include "simdjson/generic/ondemand/value_iterator.h"
|
#include "simdjson/generic/ondemand/value_iterator.h"
|
||||||
|
#include "simdjson/generic/ondemand/deserialize.h"
|
||||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
namespace simdjson {
|
namespace simdjson {
|
||||||
|
|
||||||
namespace SIMDJSON_IMPLEMENTATION {
|
namespace SIMDJSON_IMPLEMENTATION {
|
||||||
namespace ondemand {
|
namespace ondemand {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An ephemeral JSON value returned during iteration. It is only valid for as long as you do
|
* An ephemeral JSON value returned during iteration. It is only valid for as long as you do
|
||||||
* not access more data in the JSON document.
|
* not access more data in the JSON document.
|
||||||
@@ -35,16 +38,21 @@ public:
|
|||||||
* @returns A value of the given type, parsed from the JSON.
|
* @returns A value of the given type, parsed from the JSON.
|
||||||
* @returns INCORRECT_TYPE If the JSON value is not the given type.
|
* @returns INCORRECT_TYPE If the JSON value is not the given type.
|
||||||
*/
|
*/
|
||||||
template<typename T> simdjson_inline simdjson_result<T> get() noexcept {
|
template <typename T>
|
||||||
// Unless the simdjson library or the user provides an inline implementation, calling this method should
|
simdjson_inline simdjson_result<T> get()
|
||||||
// immediately fail.
|
#if SIMDJSON_SUPPORTS_DESERIALIZATION
|
||||||
static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. "
|
noexcept(custom_deserializable<T, value> ? nothrow_custom_deserializable<T, value> : true)
|
||||||
"The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, "
|
#else
|
||||||
"int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), "
|
noexcept
|
||||||
" get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template."
|
#endif
|
||||||
" You may also add support for custom types, see our documentation.");
|
{
|
||||||
|
static_assert(std::is_default_constructible<T>::value, "The specified type is not default constructible.");
|
||||||
|
T out{};
|
||||||
|
SIMDJSON_TRY(get<T>(out));
|
||||||
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get this value as the given type.
|
* Get this value as the given type.
|
||||||
*
|
*
|
||||||
@@ -54,7 +62,32 @@ public:
|
|||||||
* @returns INCORRECT_TYPE If the JSON value is not an object.
|
* @returns INCORRECT_TYPE If the JSON value is not an object.
|
||||||
* @returns SUCCESS If the parse succeeded and the out parameter was set to the value.
|
* @returns SUCCESS If the parse succeeded and the out parameter was set to the value.
|
||||||
*/
|
*/
|
||||||
template<typename T> simdjson_inline error_code get(T &out) noexcept;
|
template <typename T>
|
||||||
|
simdjson_inline error_code get(T &out)
|
||||||
|
#if SIMDJSON_SUPPORTS_DESERIALIZATION
|
||||||
|
noexcept(custom_deserializable<T, value> ? nothrow_custom_deserializable<T, value> : true)
|
||||||
|
#else
|
||||||
|
noexcept
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
#if SIMDJSON_SUPPORTS_DESERIALIZATION
|
||||||
|
if constexpr (custom_deserializable<T, value>) {
|
||||||
|
return deserialize(*this, out);
|
||||||
|
} else {
|
||||||
|
#endif // SIMDJSON_SUPPORTS_DESERIALIZATION
|
||||||
|
// Unless the simdjson library or the user provides an inline implementation, calling this method should
|
||||||
|
// immediately fail.
|
||||||
|
static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. "
|
||||||
|
"The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, "
|
||||||
|
"int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), "
|
||||||
|
" get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template."
|
||||||
|
" You may also add support for custom types, see our documentation.");
|
||||||
|
static_cast<void>(out); // to get rid of unused errors
|
||||||
|
return UNINITIALIZED;
|
||||||
|
#if SIMDJSON_SUPPORTS_DESERIALIZATION
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cast this JSON value to an array.
|
* Cast this JSON value to an array.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* auto-generated on 2024-08-01 09:31:50 -0400. Do not edit! */
|
/* auto-generated on 2024-07-15 08:51:57 -0400. Do not edit! */
|
||||||
/* including simdjson.cpp: */
|
/* including simdjson.cpp: */
|
||||||
/* begin file simdjson.cpp */
|
/* begin file simdjson.cpp */
|
||||||
#define SIMDJSON_SRC_SIMDJSON_CPP
|
#define SIMDJSON_SRC_SIMDJSON_CPP
|
||||||
@@ -77,6 +77,18 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __has_include
|
||||||
|
#if __has_include(<version>)
|
||||||
|
#include <version>
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cpp_concepts
|
||||||
|
#include <utility>
|
||||||
|
#define SIMDJSON_SUPPORTS_DESERIALIZATION 1
|
||||||
|
#else // __cpp_concepts
|
||||||
|
#define SIMDJSON_SUPPORTS_DESERIALIZATION 0
|
||||||
|
#endif
|
||||||
#endif // SIMDJSON_COMPILER_CHECK_H
|
#endif // SIMDJSON_COMPILER_CHECK_H
|
||||||
/* end file simdjson/compiler_check.h */
|
/* end file simdjson/compiler_check.h */
|
||||||
/* including simdjson/portability.h: #include "simdjson/portability.h" */
|
/* including simdjson/portability.h: #include "simdjson/portability.h" */
|
||||||
|
|||||||
+7941
-4705
File diff suppressed because it is too large
Load Diff
@@ -2,32 +2,35 @@
|
|||||||
link_libraries(simdjson)
|
link_libraries(simdjson)
|
||||||
include_directories(..)
|
include_directories(..)
|
||||||
add_subdirectory(compilation_failure_tests)
|
add_subdirectory(compilation_failure_tests)
|
||||||
add_cpp_test(ondemand_log_tests LABELS ondemand acceptance per_implementation)
|
add_cpp_test(ondemand_log_tests LABELS ondemand acceptance per_implementation)
|
||||||
add_cpp_test(ondemand_log_error_tests LABELS ondemand acceptance per_implementation)
|
add_cpp_test(ondemand_log_error_tests LABELS ondemand acceptance per_implementation)
|
||||||
add_cpp_test(ondemand_tostring_tests LABELS ondemand acceptance per_implementation)
|
add_cpp_test(ondemand_tostring_tests LABELS ondemand acceptance per_implementation)
|
||||||
add_cpp_test(ondemand_active_tests LABELS ondemand acceptance per_implementation)
|
add_cpp_test(ondemand_active_tests LABELS ondemand acceptance per_implementation)
|
||||||
add_cpp_test(ondemand_array_tests LABELS ondemand acceptance per_implementation)
|
add_cpp_test(ondemand_array_tests LABELS ondemand acceptance per_implementation)
|
||||||
add_cpp_test(ondemand_array_error_tests LABELS ondemand acceptance per_implementation)
|
add_cpp_test(ondemand_array_error_tests LABELS ondemand acceptance per_implementation)
|
||||||
add_cpp_test(ondemand_compilation_tests LABELS ondemand acceptance per_implementation)
|
add_cpp_test(ondemand_compilation_tests LABELS ondemand acceptance per_implementation)
|
||||||
add_cpp_test(ondemand_document_stream_tests LABELS ondemand acceptance per_implementation)
|
add_cpp_test(ondemand_document_stream_tests LABELS ondemand acceptance per_implementation)
|
||||||
add_cpp_test(ondemand_error_tests LABELS ondemand acceptance per_implementation)
|
add_cpp_test(ondemand_error_tests LABELS ondemand acceptance per_implementation)
|
||||||
add_cpp_test(ondemand_error_location_tests LABELS ondemand acceptance per_implementation)
|
add_cpp_test(ondemand_error_location_tests LABELS ondemand acceptance per_implementation)
|
||||||
add_cpp_test(ondemand_json_pointer_tests LABELS ondemand acceptance per_implementation)
|
add_cpp_test(ondemand_json_pointer_tests LABELS ondemand acceptance per_implementation)
|
||||||
add_cpp_test(ondemand_json_path_tests LABELS ondemand acceptance per_implementation)
|
add_cpp_test(ondemand_json_path_tests LABELS ondemand acceptance per_implementation)
|
||||||
add_cpp_test(ondemand_key_string_tests LABELS ondemand acceptance per_implementation)
|
add_cpp_test(ondemand_key_string_tests LABELS ondemand acceptance per_implementation)
|
||||||
add_cpp_test(ondemand_misc_tests LABELS ondemand acceptance per_implementation)
|
add_cpp_test(ondemand_misc_tests LABELS ondemand acceptance per_implementation)
|
||||||
add_cpp_test(ondemand_number_tests LABELS ondemand acceptance per_implementation)
|
add_cpp_test(ondemand_number_tests LABELS ondemand acceptance per_implementation)
|
||||||
add_cpp_test(ondemand_number_in_string_tests LABELS ondemand acceptance per_implementation)
|
add_cpp_test(ondemand_number_in_string_tests LABELS ondemand acceptance per_implementation)
|
||||||
add_cpp_test(ondemand_object_tests LABELS ondemand acceptance per_implementation)
|
add_cpp_test(ondemand_object_tests LABELS ondemand acceptance per_implementation)
|
||||||
add_cpp_test(ondemand_object_error_tests LABELS ondemand acceptance per_implementation)
|
add_cpp_test(ondemand_object_error_tests LABELS ondemand acceptance per_implementation)
|
||||||
add_cpp_test(ondemand_ordering_tests LABELS ondemand acceptance per_implementation)
|
add_cpp_test(ondemand_ordering_tests LABELS ondemand acceptance per_implementation)
|
||||||
add_cpp_test(ondemand_parse_api_tests LABELS ondemand acceptance per_implementation)
|
add_cpp_test(ondemand_parse_api_tests LABELS ondemand acceptance per_implementation)
|
||||||
add_cpp_test(ondemand_readme_examples LABELS ondemand acceptance per_implementation)
|
add_cpp_test(ondemand_readme_examples LABELS ondemand acceptance per_implementation)
|
||||||
add_cpp_test(ondemand_scalar_tests LABELS ondemand acceptance per_implementation)
|
add_cpp_test(ondemand_scalar_tests LABELS ondemand acceptance per_implementation)
|
||||||
add_cpp_test(ondemand_to_string LABELS ondemand acceptance per_implementation)
|
add_cpp_test(ondemand_to_string LABELS ondemand acceptance per_implementation)
|
||||||
add_cpp_test(ondemand_twitter_tests LABELS ondemand acceptance per_implementation)
|
add_cpp_test(ondemand_twitter_tests LABELS ondemand acceptance per_implementation)
|
||||||
add_cpp_test(ondemand_wrong_type_error_tests LABELS ondemand acceptance per_implementation)
|
add_cpp_test(ondemand_wrong_type_error_tests LABELS ondemand acceptance per_implementation)
|
||||||
add_cpp_test(ondemand_iterate_many_csv LABELS ondemand acceptance per_implementation)
|
add_cpp_test(ondemand_iterate_many_csv LABELS ondemand acceptance per_implementation)
|
||||||
|
add_cpp_test(ondemand_custom_types_tests LABELS ondemand acceptance per_implementation)
|
||||||
|
add_cpp_test(ondemand_custom_types_document_tests LABELS ondemand acceptance per_implementation)
|
||||||
|
add_cpp_test(ondemand_stl_types_tests LABELS ondemand acceptance per_implementation)
|
||||||
if(NOT SIMDJSON_SANITIZE)
|
if(NOT SIMDJSON_SANITIZE)
|
||||||
add_cpp_test(ondemand_cacheline LABELS ondemand acceptance per_implementation)
|
add_cpp_test(ondemand_cacheline LABELS ondemand acceptance per_implementation)
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -0,0 +1,192 @@
|
|||||||
|
#include "simdjson.h"
|
||||||
|
#include "test_ondemand.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#if SIMDJSON_SUPPORTS_DESERIALIZATION
|
||||||
|
|
||||||
|
namespace simdjson {
|
||||||
|
|
||||||
|
// unique_ptr<T>
|
||||||
|
template <typename T>
|
||||||
|
error_code tag_invoke(deserialize_tag, auto &val, std::unique_ptr<T>& out) {
|
||||||
|
out = std::make_unique<T>(val.template get<T>());
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace simdjson
|
||||||
|
|
||||||
|
#endif // SIMDJSON_SUPPORTS_DESERIALIZATION
|
||||||
|
|
||||||
|
namespace doc_custom_types_tests {
|
||||||
|
#if SIMDJSON_EXCEPTIONS && defined(__cpp_concepts)
|
||||||
|
struct Car {
|
||||||
|
std::string make{};
|
||||||
|
std::string model{};
|
||||||
|
int64_t year{};
|
||||||
|
std::vector<double> tire_pressure{};
|
||||||
|
|
||||||
|
friend error_code tag_invoke(simdjson::deserialize_tag,
|
||||||
|
auto &val, Car& car) {
|
||||||
|
simdjson::ondemand::object obj;
|
||||||
|
if (auto const error = val.get_object().get(obj)) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
// Instead of repeatedly obj["something"], we iterate through the object
|
||||||
|
// which we expect to be faster.
|
||||||
|
for (auto field : obj) {
|
||||||
|
simdjson::ondemand::raw_json_string key;
|
||||||
|
if (auto const error = field.key().get(key)) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
if (key == "make") {
|
||||||
|
if (auto const error = field.value().get_string(car.make)) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
} else if (key == "model") {
|
||||||
|
if (auto const error = field.value().get_string(car.model)) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
} else if (key == "year") {
|
||||||
|
if (auto const error = field.value().get_int64().get(car.year)) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
} else if (key == "tire_pressure") {
|
||||||
|
if (auto const error = field.value().get<std::vector<double>>().get(
|
||||||
|
car.tire_pressure)) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return error_code::SUCCESS;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(simdjson::custom_deserializable<std::unique_ptr<Car>, simdjson::ondemand::value>, "It should be invocable");
|
||||||
|
static_assert(simdjson::custom_deserializable<std::unique_ptr<Car>, simdjson::ondemand::document>, "Tag_invoke should work with document as well.");
|
||||||
|
static_assert(simdjson::custom_deserializable<std::vector<Car>, simdjson::ondemand::value>, "It should be invocable");
|
||||||
|
static_assert(simdjson::custom_deserializable<std::vector<Car>, simdjson::ondemand::document>, "Tag_invoke should work with document as well.");
|
||||||
|
|
||||||
|
bool custom_test() {
|
||||||
|
TEST_START();
|
||||||
|
auto const json = R"( {
|
||||||
|
"make": "Toyota",
|
||||||
|
"model": "Camry",
|
||||||
|
"year": 2018,
|
||||||
|
"tire_pressure": [ 40.1, 39.9 ]
|
||||||
|
} )"_padded;
|
||||||
|
|
||||||
|
simdjson::ondemand::parser parser;
|
||||||
|
simdjson::ondemand::document doc = parser.iterate(json);
|
||||||
|
|
||||||
|
// creating car directly from "doc":
|
||||||
|
const std::unique_ptr<Car> car(doc);
|
||||||
|
if (car->make != "Toyota") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (car->model != "Camry") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (car->year != 2018) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (car->tire_pressure.size() != 2) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
TEST_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool readme_test() {
|
||||||
|
TEST_START();
|
||||||
|
auto const json = R"( { "make": "Toyota", "model": "Camry", "year": 2018,
|
||||||
|
"tire_pressure": [ 40.1, 39.9 ] })"_padded;
|
||||||
|
simdjson::ondemand::parser parser;
|
||||||
|
simdjson::ondemand::document doc = parser.iterate(json);
|
||||||
|
std::unique_ptr<Car> c(doc);
|
||||||
|
std::cout << c->make << std::endl;
|
||||||
|
TEST_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool simple_document_test() {
|
||||||
|
TEST_START();
|
||||||
|
simdjson::padded_string json =
|
||||||
|
R"( { "make": "Toyota", "model": "Camry", "year": 2018,
|
||||||
|
"tire_pressure": [ 40.1, 39.9 ] })"_padded;
|
||||||
|
simdjson::ondemand::parser parser;
|
||||||
|
simdjson::ondemand::document doc = parser.iterate(json);
|
||||||
|
Car c(doc);
|
||||||
|
std::cout << c.make << std::endl;
|
||||||
|
ASSERT_EQUAL(c.make, "Toyota");
|
||||||
|
TEST_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool custom_test_crazier() {
|
||||||
|
TEST_START();
|
||||||
|
simdjson::padded_string json =
|
||||||
|
R"( [ { "make": "Toyota", "model": "Camry", "year": 2018,
|
||||||
|
"tire_pressure": [ 40.1, 39.9 ] },
|
||||||
|
{ "make": "Kia", "model": "Soul", "year": 2012,
|
||||||
|
"tire_pressure": [ 30.1, 31.0 ] },
|
||||||
|
{ "make": "Toyota", "model": "Tercel", "year": 1999,
|
||||||
|
"tire_pressure": [ 29.8, 30.0 ] }
|
||||||
|
])"_padded;
|
||||||
|
|
||||||
|
simdjson::ondemand::parser parser;
|
||||||
|
simdjson::ondemand::document doc = parser.iterate(json);
|
||||||
|
#if SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||||
|
std::vector<Car> cars = doc.get<std::vector<Car>>();
|
||||||
|
#else
|
||||||
|
std::vector<Car> cars(doc);
|
||||||
|
#endif
|
||||||
|
for(Car& c : cars) {
|
||||||
|
std::cout << c.year << std::endl;
|
||||||
|
if (c.make != "Toyota" && c.make != "Kia") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (c.model != "Camry" && c.model != "Soul" && c.model != "Tercel") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (c.year != 2018 && c.year != 2012 && c.year != 1999) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (c.tire_pressure.size() != 2) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TEST_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool simple_document_test_no_except() {
|
||||||
|
TEST_START();
|
||||||
|
simdjson::padded_string json =
|
||||||
|
R"( { "make": "Toyota", "model": "Camry", "year": 2018,
|
||||||
|
"tire_pressure": [ 40.1, 39.9 ] })"_padded;
|
||||||
|
simdjson::ondemand::parser parser;
|
||||||
|
simdjson::ondemand::document doc = parser.iterate(json);
|
||||||
|
Car c;
|
||||||
|
auto error = doc.get(c);
|
||||||
|
if(error) { std::cerr << simdjson::error_message(error); return false; }
|
||||||
|
std::cout << c.make << std::endl;
|
||||||
|
ASSERT_EQUAL(c.make, "Toyota");
|
||||||
|
TEST_SUCCEED();
|
||||||
|
}
|
||||||
|
#endif // SIMDJSON_EXCEPTIONS
|
||||||
|
bool run() {
|
||||||
|
return
|
||||||
|
#if SIMDJSON_EXCEPTIONS && defined(__cpp_concepts)
|
||||||
|
readme_test() &&
|
||||||
|
custom_test() &&
|
||||||
|
simple_document_test() &&
|
||||||
|
simple_document_test_no_except() &&
|
||||||
|
custom_test_crazier() &&
|
||||||
|
#endif // SIMDJSON_EXCEPTIONS
|
||||||
|
true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace doc_custom_types_tests
|
||||||
|
|
||||||
|
int main(const int argc, char *argv[]) {
|
||||||
|
return test_main(argc, argv, doc_custom_types_tests::run);
|
||||||
|
}
|
||||||
@@ -0,0 +1,229 @@
|
|||||||
|
#include "simdjson.h"
|
||||||
|
#include "test_ondemand.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#if SIMDJSON_SUPPORTS_DESERIALIZATION
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct is_unique_ptr : std::false_type {
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct is_unique_ptr<std::unique_ptr<T>> : std::true_type {
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
concept is_unique_ptr_v = is_unique_ptr<T>::value;
|
||||||
|
|
||||||
|
|
||||||
|
namespace simdjson {
|
||||||
|
|
||||||
|
// this is to demonstrate that we can use concept; otherwise a simple
|
||||||
|
// type_identity<unique_ptr<T>> as the second argument would have done the job.
|
||||||
|
//
|
||||||
|
// This tag_invoke MUST be inside simdjson namespace
|
||||||
|
template <typename T>
|
||||||
|
requires is_unique_ptr_v<T>
|
||||||
|
auto tag_invoke(deserialize_tag, auto &val, T& out) {
|
||||||
|
using type = typename T::element_type;
|
||||||
|
out = std::make_unique<type>(val.template get<type>());
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace simdjson
|
||||||
|
|
||||||
|
|
||||||
|
#endif // SIMDJSON_SUPPORTS_DESERIALIZATION
|
||||||
|
|
||||||
|
|
||||||
|
namespace custom_types_tests {
|
||||||
|
#if SIMDJSON_EXCEPTIONS && SIMDJSON_SUPPORTS_DESERIALIZATION
|
||||||
|
struct Car {
|
||||||
|
std::string make{};
|
||||||
|
std::string model{};
|
||||||
|
int year{};
|
||||||
|
std::vector<double> tire_pressure{};
|
||||||
|
|
||||||
|
friend simdjson::error_code tag_invoke(simdjson::deserialize_tag, auto &val, Car& car) {
|
||||||
|
simdjson::ondemand::object obj;
|
||||||
|
auto error = val.get_object().get(obj);
|
||||||
|
if (error) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
// Instead of repeatedly obj["something"], we iterate through the object
|
||||||
|
// which we expect to be faster.
|
||||||
|
for (auto field : obj) {
|
||||||
|
simdjson::ondemand::raw_json_string key;
|
||||||
|
error = field.key().get(key);
|
||||||
|
if (error) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
if (key == "make") {
|
||||||
|
error = field.value().get_string(car.make);
|
||||||
|
if (error) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
} else if (key == "model") {
|
||||||
|
error = field.value().get_string(car.model);
|
||||||
|
if (error) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
} else if (key == "year") {
|
||||||
|
error = field.value().get(car.year);
|
||||||
|
if (error) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
} else if (key == "tire_pressure") {
|
||||||
|
error = field.value().get(car.tire_pressure);
|
||||||
|
if (error) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return simdjson::SUCCESS;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(simdjson::custom_deserializable<std::unique_ptr<Car>>, "It should be deserializable");
|
||||||
|
|
||||||
|
bool custom_uniqueptr_test() {
|
||||||
|
TEST_START();
|
||||||
|
simdjson::padded_string json =
|
||||||
|
R"( [ { "make": "Toyota", "model": "Camry", "year": 2018,
|
||||||
|
"tire_pressure": [ 40.1, 39.9 ] },
|
||||||
|
{ "make": "Kia", "model": "Soul", "year": 2012,
|
||||||
|
"tire_pressure": [ 30.1, 31.0 ] },
|
||||||
|
{ "make": "Toyota", "model": "Tercel", "year": 1999,
|
||||||
|
"tire_pressure": [ 29.8, 30.0 ] }
|
||||||
|
])"_padded;
|
||||||
|
|
||||||
|
simdjson::ondemand::parser parser;
|
||||||
|
simdjson::ondemand::document doc = parser.iterate(json);
|
||||||
|
for (auto val : doc) {
|
||||||
|
std::unique_ptr<Car> c(val);
|
||||||
|
if (c->make != "Toyota" && c->make != "Kia") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (c->model != "Camry" && c->model != "Soul" && c->model != "Tercel") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (c->year != 2018 && c->year != 2012 && c->year != 1999) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (c->tire_pressure.size() != 2) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool custom_test() {
|
||||||
|
TEST_START();
|
||||||
|
simdjson::padded_string json =
|
||||||
|
R"( [ { "make": "Toyota", "model": "Camry", "year": 2018,
|
||||||
|
"tire_pressure": [ 40.1, 39.9 ] },
|
||||||
|
{ "make": "Kia", "model": "Soul", "year": 2012,
|
||||||
|
"tire_pressure": [ 30.1, 31.0 ] },
|
||||||
|
{ "make": "Toyota", "model": "Tercel", "year": 1999,
|
||||||
|
"tire_pressure": [ 29.8, 30.0 ] }
|
||||||
|
])"_padded;
|
||||||
|
|
||||||
|
simdjson::ondemand::parser parser;
|
||||||
|
simdjson::ondemand::document doc = parser.iterate(json);
|
||||||
|
for (auto val : doc) {
|
||||||
|
Car c(val);
|
||||||
|
if (c.make != "Toyota" && c.make != "Kia") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (c.model != "Camry" && c.model != "Soul" && c.model != "Tercel") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (c.year != 2018 && c.year != 2012 && c.year != 1999) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (c.tire_pressure.size() != 2) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool custom_test_crazy() {
|
||||||
|
TEST_START();
|
||||||
|
simdjson::padded_string json =
|
||||||
|
R"( [ { "make": "Toyota", "model": "Camry", "year": 2018,
|
||||||
|
"tire_pressure": [ 40.1, 39.9 ] },
|
||||||
|
{ "make": "Kia", "model": "Soul", "year": 2012,
|
||||||
|
"tire_pressure": [ 30.1, 31.0 ] },
|
||||||
|
{ "make": "Toyota", "model": "Tercel", "year": 1999,
|
||||||
|
"tire_pressure": [ 29.8, 30.0 ] }
|
||||||
|
])"_padded;
|
||||||
|
|
||||||
|
simdjson::ondemand::parser parser;
|
||||||
|
simdjson::ondemand::document doc = parser.iterate(json);
|
||||||
|
for (auto val : doc) {
|
||||||
|
Car c(val);
|
||||||
|
std::cout << c.year << std::endl;
|
||||||
|
if (c.make != "Toyota" && c.make != "Kia") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (c.model != "Camry" && c.model != "Soul" && c.model != "Tercel") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (c.year != 2018 && c.year != 2012 && c.year != 1999) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (c.tire_pressure.size() != 2) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool custom_no_except() {
|
||||||
|
TEST_START();
|
||||||
|
simdjson::padded_string json =
|
||||||
|
R"( [ { "make": "Toyota", "model": "Camry", "year": 2018,
|
||||||
|
"tire_pressure": [ 40.1, 39.9 ] },
|
||||||
|
{ "make": "Kia", "model": "Soul", "year": 2012,
|
||||||
|
"tire_pressure": [ 30.1, 31.0 ] },
|
||||||
|
{ "make": "Toyota", "model": "Tercel", "year": 1999,
|
||||||
|
"tire_pressure": [ 29.8, 30.0 ] }
|
||||||
|
])"_padded;
|
||||||
|
|
||||||
|
simdjson::ondemand::parser parser;
|
||||||
|
simdjson::ondemand::document doc = parser.iterate(json);
|
||||||
|
for (auto val : doc) {
|
||||||
|
Car c;
|
||||||
|
auto error = val.get(c);
|
||||||
|
if(error) { std::cerr << simdjson::error_message(error) << std::endl; return false; }
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_SUCCEED();
|
||||||
|
}
|
||||||
|
#endif // SIMDJSON_EXCEPTIONS
|
||||||
|
bool run() {
|
||||||
|
return
|
||||||
|
#if SIMDJSON_EXCEPTIONS && SIMDJSON_SUPPORTS_DESERIALIZATION
|
||||||
|
custom_test() &&
|
||||||
|
custom_uniqueptr_test() &&
|
||||||
|
custom_no_except() &&
|
||||||
|
#endif // SIMDJSON_EXCEPTIONS
|
||||||
|
true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace custom_types_tests
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
return test_main(argc, argv, custom_types_tests::run);
|
||||||
|
}
|
||||||
@@ -49,6 +49,7 @@ struct Car {
|
|||||||
std::vector<double> tire_pressure;
|
std::vector<double> tire_pressure;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifndef __cpp_concepts
|
||||||
template <>
|
template <>
|
||||||
simdjson_inline simdjson_result<std::vector<double>>
|
simdjson_inline simdjson_result<std::vector<double>>
|
||||||
simdjson::ondemand::value::get() noexcept {
|
simdjson::ondemand::value::get() noexcept {
|
||||||
@@ -66,7 +67,7 @@ simdjson::ondemand::value::get() noexcept {
|
|||||||
}
|
}
|
||||||
return vec;
|
return vec;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
@@ -193,8 +194,8 @@ int custom_type_with_exceptions() {
|
|||||||
])"_padded;
|
])"_padded;
|
||||||
ondemand::parser parser;
|
ondemand::parser parser;
|
||||||
ondemand::document doc = parser.iterate(json);
|
ondemand::document doc = parser.iterate(json);
|
||||||
for (auto val : doc) {
|
for (auto value : doc) {
|
||||||
Car c(val);
|
Car c(value);
|
||||||
std::cout << c.make << std::endl;
|
std::cout << c.make << std::endl;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
#include "simdjson.h"
|
||||||
|
#include "test_ondemand.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace stl_types {
|
||||||
|
#if SIMDJSON_EXCEPTIONS && SIMDJSON_SUPPORTS_DESERIALIZATION
|
||||||
|
|
||||||
|
bool basic_general_madness() {
|
||||||
|
TEST_START();
|
||||||
|
simdjson::padded_string json =
|
||||||
|
R"( [ { "codes": [1.2, 3.4, 5.6, 7.8, 9.0] },
|
||||||
|
{ "codes": [2.2, 4.4, 6.6, 8.8, 10.0] } ])"_padded;
|
||||||
|
|
||||||
|
simdjson::ondemand::parser parser;
|
||||||
|
simdjson::ondemand::document doc = parser.iterate(json);
|
||||||
|
std::vector<std::unique_ptr<float>> codes;
|
||||||
|
for (auto val : doc) {
|
||||||
|
simdjson::ondemand::object obj;
|
||||||
|
SIMDJSON_TRY(val.get_object().get(obj));
|
||||||
|
obj["codes"].get(codes); // append to it
|
||||||
|
}
|
||||||
|
|
||||||
|
if (codes.size() != 10) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (*codes[5] != 2.2f || *codes[7] != 6.6f || *codes[9] != 10.0f) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // SIMDJSON_EXCEPTIONS
|
||||||
|
bool run() {
|
||||||
|
return
|
||||||
|
#if SIMDJSON_EXCEPTIONS && SIMDJSON_SUPPORTS_DESERIALIZATION
|
||||||
|
basic_general_madness() &&
|
||||||
|
#endif // SIMDJSON_EXCEPTIONS
|
||||||
|
true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace stl_types
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
return test_main(argc, argv, stl_types::run);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user