mirror of
https://github.com/simdjson/simdjson
synced 2026-06-08 17:27:07 +00:00
Compare commits
114 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5541e78402 | |||
| 9a9ed0e2da | |||
| bca8d3e277 | |||
| 97196fa969 | |||
| 23fab307ca | |||
| 0a14e05ec7 | |||
| b88f831dbd | |||
| 71a73c2c47 | |||
| 07603aa7f7 | |||
| b8a6b889c7 | |||
| 7898234bb3 | |||
| f52533538a | |||
| 3bb2f0a186 | |||
| d6551bf278 | |||
| 0173eaaad7 | |||
| 5459dbd6c6 | |||
| 9c45f1f292 | |||
| 665cbba159 | |||
| a26f664907 | |||
| 17cb457ffd | |||
| 8b2af0473a | |||
| f1bfa43385 | |||
| 29fbbee852 | |||
| baa7d961ce | |||
| 6412b27c7e | |||
| 503da5ec83 | |||
| 9dd6e9c959 | |||
| 6db330c1a2 | |||
| 993ac4b87c | |||
| 35e87896f0 | |||
| f7e281cadc | |||
| 13405afd4b | |||
| 24b44309fb | |||
| e11ad58aad | |||
| 1875ed6550 | |||
| 80d26298a0 | |||
| 25b5015c09 | |||
| 26f8c566c7 | |||
| ff77ac801e | |||
| e0699994ef | |||
| 68ba9a1b2a | |||
| 6fed6bd29b | |||
| cc24bb4114 | |||
| 14ec0ca8f4 | |||
| 8dabd02c3a | |||
| c9692005fd | |||
| 2e0a9397c9 | |||
| f7922075c3 | |||
| b2e20e04c9 | |||
| adc9d18efd | |||
| bf849e3619 | |||
| c09e8dc225 | |||
| 5bf585ef02 | |||
| caff09cafc | |||
| f043db4dca | |||
| e3bd0828d1 | |||
| 9408298e0e | |||
| 573bbac2d2 | |||
| ac78c625df | |||
| 390a66c6e8 | |||
| 210e0a56a1 | |||
| 084f662f32 | |||
| c878ff2500 | |||
| 06afe9ecb3 | |||
| e658502adb | |||
| 6e7d415040 | |||
| 2ccd5b9c97 | |||
| 1cdcbf79b3 | |||
| 7013ed98cc | |||
| b383c717d7 | |||
| b8743bced0 | |||
| ae9ba2bed2 | |||
| 939844d79f | |||
| 4f4e81668e | |||
| bb54946b78 | |||
| 4dec6ed5a7 | |||
| 1dfd48195d | |||
| 23afc6b695 | |||
| e3cac71afe | |||
| cbe562c1d5 | |||
| 30437d0ff6 | |||
| 1e97af7dfb | |||
| 80bc9e5051 | |||
| a74e87df17 | |||
| 3274299647 | |||
| 22ca25faa6 | |||
| 37399fd41b | |||
| a170145d5b | |||
| 7d1d635883 | |||
| ddfa8ae928 | |||
| 25dfb078c7 | |||
| 9f0710e3ad | |||
| 19b9cd9b05 | |||
| 7540248396 | |||
| ab09e96de9 | |||
| 66252e4925 | |||
| 944778c186 | |||
| 62868a2f53 | |||
| 3c446c551b | |||
| efe3d4b7d7 | |||
| 28db262b47 | |||
| bf076bfb5f | |||
| 7bf1ecff9e | |||
| e25a40facf | |||
| a442842f0d | |||
| 421ed4f390 | |||
| 7dff5fa37c | |||
| 9a0527c380 | |||
| b160cf0610 | |||
| 553ee69b7c | |||
| bf70cd0ebf | |||
| cf0551edf5 | |||
| ddb094d550 | |||
| 975fdda03c |
@@ -1,2 +1,46 @@
|
|||||||
CompileFlags:
|
CompileFlags:
|
||||||
CompilationDatabase: build
|
CompilationDatabase: build
|
||||||
|
Add:
|
||||||
|
- -Werror -Wall -Wextra -Weffc++ -Wsign-compare -Wshadow -Wwrite-strings -Wpointer-arith -Winit-self -Wconversion -Wno-sign-conversion
|
||||||
|
- -Wundefined-inline
|
||||||
|
Diagnostics:
|
||||||
|
Suppress:
|
||||||
|
- misc-unused-alias-decls
|
||||||
|
- misc-unused-using-decls
|
||||||
|
- misc-definitions-in-headers # TODO fix and remove these violations
|
||||||
|
---
|
||||||
|
If:
|
||||||
|
PathMatch:
|
||||||
|
- include/.*
|
||||||
|
- src/.*
|
||||||
|
PathExclude:
|
||||||
|
- include/simdjson.h
|
||||||
|
- src/simdjson.cpp
|
||||||
|
CompileFlags:
|
||||||
|
Add:
|
||||||
|
- -Wno-unneeded-internal-declaration
|
||||||
|
- -Wno-undefined-internal # TODO fix and remove these violations
|
||||||
|
- -Wno-unused-function
|
||||||
|
- -Wno-unused-const-variable
|
||||||
|
Diagnostics:
|
||||||
|
Suppress:
|
||||||
|
- pp_including_mainfile_in_preamble
|
||||||
|
---
|
||||||
|
# Amalgamated files that require or partly define an implementation
|
||||||
|
If:
|
||||||
|
PathMatch:
|
||||||
|
- .*/(arm64|fallback|haswell|icelake|ppc64|westmere)/begin.h
|
||||||
|
- .*/generic/.*
|
||||||
|
Diagnostics:
|
||||||
|
Suppress:
|
||||||
|
- pragma_attribute_no_pop_eof
|
||||||
|
---
|
||||||
|
# clang has a bad time detecting the push/pop together in src/ for some reason
|
||||||
|
If:
|
||||||
|
PathMatch:
|
||||||
|
- include/simdjson/.*/end.h
|
||||||
|
- src/(arm64|fallback|haswell|icelake|ppc64|westmere).cpp
|
||||||
|
Diagnostics:
|
||||||
|
Suppress:
|
||||||
|
- pragma_attribute_no_pop_eof
|
||||||
|
- pragma_attribute_stack_mismatch
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ It is fine to report bugs against our main branch, but if that is what you are d
|
|||||||
- Version [e.g. 22]
|
- Version [e.g. 22]
|
||||||
- Optimization setting (e.g., -O3)
|
- Optimization setting (e.g., -O3)
|
||||||
|
|
||||||
We support up-to-date 64-bit ARM and x64 FreeBSD, macOS, Windows and Linux systems. Please ensure that your configuration is supported before labelling the issue as a bug. In particular, we do not support legacy 32-bit systems.
|
We support up-to-date 64-bit ARM and x64 FreeBSD, macOS, Windows and Linux systems. Please ensure that your configuration is supported before labelling the issue as a bug.
|
||||||
|
|
||||||
**Indicate whether you are willing or able to provide a bug fix as a pull request**
|
**Indicate whether you are willing or able to provide a bug fix as a pull request**
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ A clear and concise description of any alternative solutions or features you've
|
|||||||
**Additional context**
|
**Additional context**
|
||||||
Add any other context or screenshots about the feature request here.
|
Add any other context or screenshots about the feature request here.
|
||||||
|
|
||||||
** Are you willing to contribute code or documentation toward this new feature? **
|
**Are you willing to contribute code or documentation toward this new feature?**
|
||||||
If you plan to contribute to simdjson, please read our
|
If you plan to contribute to simdjson, please read our
|
||||||
* CONTRIBUTING guide: https://github.com/simdjson/simdjson/blob/master/CONTRIBUTING.md and our
|
* CONTRIBUTING guide: https://github.com/simdjson/simdjson/blob/master/CONTRIBUTING.md and our
|
||||||
* HACKING guide: https://github.com/simdjson/simdjson/blob/master/HACKING.md
|
* HACKING guide: https://github.com/simdjson/simdjson/blob/master/HACKING.md
|
||||||
|
|||||||
@@ -31,4 +31,4 @@ jobs:
|
|||||||
./alpine.sh cmake --build build_for_alpine
|
./alpine.sh cmake --build build_for_alpine
|
||||||
- name: test
|
- name: test
|
||||||
run: |
|
run: |
|
||||||
./alpine.sh bash -c "cd build_for_alpine && ctest -LE explicitonly"
|
./alpine.sh bash -c "cd build_for_alpine && ctest -LE explicitonly --output-on-failure"
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ jobs:
|
|||||||
sudo apt update
|
sudo apt update
|
||||||
sudo apt-get install --quiet ninja-build valgrind zip unzip lsb-release wget software-properties-common gnupg
|
sudo apt-get install --quiet ninja-build valgrind zip unzip lsb-release wget software-properties-common gnupg
|
||||||
wget https://apt.llvm.org/llvm.sh
|
wget https://apt.llvm.org/llvm.sh
|
||||||
|
sudo apt-get purge --auto-remove llvm python3-lldb-14 llvm-14
|
||||||
chmod +x llvm.sh
|
chmod +x llvm.sh
|
||||||
sudo ./llvm.sh $CLANGVERSION
|
sudo ./llvm.sh $CLANGVERSION
|
||||||
|
|
||||||
|
|||||||
@@ -20,14 +20,25 @@ jobs:
|
|||||||
cd builddebug &&
|
cd builddebug &&
|
||||||
cmake -DCMAKE_BUILD_TYPE=Debug -DSIMDJSON_GOOGLE_BENCHMARKS=OFF -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=OFF .. &&
|
cmake -DCMAKE_BUILD_TYPE=Debug -DSIMDJSON_GOOGLE_BENCHMARKS=OFF -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=OFF .. &&
|
||||||
cmake --build . &&
|
cmake --build . &&
|
||||||
ctest -j --output-on-failure -LE explicitonly &&
|
ctest --output-on-failure -LE explicitonly -j &&
|
||||||
cd .. &&
|
cd .. &&
|
||||||
mkdir build &&
|
mkdir build &&
|
||||||
cd build &&
|
cd build &&
|
||||||
cmake -DSIMDJSON_GOOGLE_BENCHMARKS=ON -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=OFF -DCMAKE_INSTALL_PREFIX:PATH=destination .. &&
|
cmake -DSIMDJSON_GOOGLE_BENCHMARKS=ON -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=OFF -DCMAKE_INSTALL_PREFIX:PATH=destination .. &&
|
||||||
cmake --build . &&
|
cmake --build . &&
|
||||||
ctest -j --output-on-failure -LE explicitonly &&
|
ctest --output-on-failure -LE explicitonly -j &&
|
||||||
cmake --install . &&
|
cmake --install . &&
|
||||||
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 &&
|
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 &&
|
||||||
cd ../tests/installation_tests/find &&
|
cd ../tests/installation_tests/find &&
|
||||||
mkdir build && cd build && cmake -DCMAKE_INSTALL_PREFIX:PATH=../../../build/destination .. && cmake --build .
|
mkdir build && cd build && cmake -DCMAKE_INSTALL_PREFIX:PATH=../../../build/destination .. && cmake --build .
|
||||||
|
- name: Use cmake (shared)
|
||||||
|
run: |
|
||||||
|
mkdir buildshared &&
|
||||||
|
cd buildshared &&
|
||||||
|
cmake -DSIMDJSON_GOOGLE_BENCHMARKS=ON -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=ON -DCMAKE_INSTALL_PREFIX:PATH=destination .. &&
|
||||||
|
cmake --build . &&
|
||||||
|
ctest --output-on-failure -LE explicitonly -j &&
|
||||||
|
cmake --install . &&
|
||||||
|
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 &&
|
||||||
|
cd ../tests/installation_tests/find &&
|
||||||
|
mkdir buildshared && cd buildshared && cmake -DCMAKE_INSTALL_PREFIX:PATH=../../../buildshared/destination .. && cmake --build .
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
name: Ubuntu riscv64 (GCC 11)
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- uses: uraimo/run-on-arch-action@v2
|
||||||
|
name: Test
|
||||||
|
id: runcmd
|
||||||
|
with:
|
||||||
|
arch: riscv64
|
||||||
|
distro: ubuntu_latest
|
||||||
|
githubToken: ${{ github.token }}
|
||||||
|
install: |
|
||||||
|
apt-get update -q -y
|
||||||
|
apt-get install -y cmake make g++
|
||||||
|
run: |
|
||||||
|
cmake -DCMAKE_BUILD_TYPE=Release -B build
|
||||||
|
cmake --build build -j=2
|
||||||
|
ctest --output-on-failure --test-dir build
|
||||||
@@ -25,13 +25,13 @@ jobs:
|
|||||||
cd builddebug &&
|
cd builddebug &&
|
||||||
cmake -DCMAKE_BUILD_TYPE=Debug -DSIMDJSON_GOOGLE_BENCHMARKS=OFF -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=OFF .. &&
|
cmake -DCMAKE_BUILD_TYPE=Debug -DSIMDJSON_GOOGLE_BENCHMARKS=OFF -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=OFF .. &&
|
||||||
cmake --build . &&
|
cmake --build . &&
|
||||||
ctest -j --output-on-failure -LE explicitonly &&
|
ctest --output-on-failure -LE explicitonly -j &&
|
||||||
cd .. &&
|
cd .. &&
|
||||||
mkdir build &&
|
mkdir build &&
|
||||||
cd build &&
|
cd build &&
|
||||||
cmake -DSIMDJSON_GOOGLE_BENCHMARKS=ON -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=OFF -DCMAKE_INSTALL_PREFIX:PATH=destination .. &&
|
cmake -DSIMDJSON_GOOGLE_BENCHMARKS=ON -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=OFF -DCMAKE_INSTALL_PREFIX:PATH=destination .. &&
|
||||||
cmake --build . &&
|
cmake --build . &&
|
||||||
ctest -j --output-on-failure -LE explicitonly &&
|
ctest --output-on-failure -LE explicitonly -j &&
|
||||||
cmake --install . &&
|
cmake --install . &&
|
||||||
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 &&
|
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 &&
|
||||||
cd ../tests/installation_tests/find &&
|
cd ../tests/installation_tests/find &&
|
||||||
|
|||||||
@@ -20,13 +20,13 @@ jobs:
|
|||||||
cd builddebug &&
|
cd builddebug &&
|
||||||
cmake -DCMAKE_BUILD_TYPE=Debug -DSIMDJSON_GOOGLE_BENCHMARKS=OFF -DSIMDJSON_DEVELOPER_MODE=ON -DSIMDJSON_EXCEPTIONS=OFF -DBUILD_SHARED_LIBS=OFF .. &&
|
cmake -DCMAKE_BUILD_TYPE=Debug -DSIMDJSON_GOOGLE_BENCHMARKS=OFF -DSIMDJSON_DEVELOPER_MODE=ON -DSIMDJSON_EXCEPTIONS=OFF -DBUILD_SHARED_LIBS=OFF .. &&
|
||||||
cmake --build . &&
|
cmake --build . &&
|
||||||
ctest -j --output-on-failure -LE explicitonly &&
|
ctest --output-on-failure -LE explicitonly -j &&
|
||||||
cd .. &&
|
cd .. &&
|
||||||
mkdir build &&
|
mkdir build &&
|
||||||
cd build &&
|
cd build &&
|
||||||
cmake -DSIMDJSON_DEVELOPER_MODE=ON -DSIMDJSON_GOOGLE_BENCHMARKS=ON -DSIMDJSON_GOOGLE_BENCHMARKS=ON -DSIMDJSON_EXCEPTIONS=OFF -DBUILD_SHARED_LIBS=OFF -DCMAKE_INSTALL_PREFIX:PATH=destination .. &&
|
cmake -DSIMDJSON_DEVELOPER_MODE=ON -DSIMDJSON_GOOGLE_BENCHMARKS=ON -DSIMDJSON_GOOGLE_BENCHMARKS=ON -DSIMDJSON_EXCEPTIONS=OFF -DBUILD_SHARED_LIBS=OFF -DCMAKE_INSTALL_PREFIX:PATH=destination .. &&
|
||||||
cmake --build . &&
|
cmake --build . &&
|
||||||
ctest -j --output-on-failure -LE explicitonly &&
|
ctest --output-on-failure -LE explicitonly -j &&
|
||||||
make install &&
|
make install &&
|
||||||
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 &&
|
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 &&
|
||||||
mkdir testfindpackage &&
|
mkdir testfindpackage &&
|
||||||
|
|||||||
@@ -20,13 +20,13 @@ jobs:
|
|||||||
cd builddebug &&
|
cd builddebug &&
|
||||||
cmake -DCMAKE_BUILD_TYPE=Debug -DSIMDJSON_GOOGLE_BENCHMARKS=OFF -DSIMDJSON_ENABLE_THREADS=OFF -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=OFF .. &&
|
cmake -DCMAKE_BUILD_TYPE=Debug -DSIMDJSON_GOOGLE_BENCHMARKS=OFF -DSIMDJSON_ENABLE_THREADS=OFF -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=OFF .. &&
|
||||||
cmake --build . &&
|
cmake --build . &&
|
||||||
ctest -j --output-on-failure -LE explicitonly &&
|
ctest --output-on-failure -LE explicitonly -j &&
|
||||||
cd .. &&
|
cd .. &&
|
||||||
mkdir build &&
|
mkdir build &&
|
||||||
cd build &&
|
cd build &&
|
||||||
cmake -DSIMDJSON_DEVELOPER_MODE=ON -DSIMDJSON_GOOGLE_BENCHMARKS=ON -DSIMDJSON_ENABLE_THREADS=OFF -DBUILD_SHARED_LIBS=OFF -DCMAKE_INSTALL_PREFIX:PATH=destination .. &&
|
cmake -DSIMDJSON_DEVELOPER_MODE=ON -DSIMDJSON_GOOGLE_BENCHMARKS=ON -DSIMDJSON_ENABLE_THREADS=OFF -DBUILD_SHARED_LIBS=OFF -DCMAKE_INSTALL_PREFIX:PATH=destination .. &&
|
||||||
cmake --build . &&
|
cmake --build . &&
|
||||||
ctest -j --output-on-failure -LE explicitonly &&
|
ctest --output-on-failure -LE explicitonly -j &&
|
||||||
make install &&
|
make install &&
|
||||||
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 &&
|
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 &&
|
||||||
mkdir testfindpackage &&
|
mkdir testfindpackage &&
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ name: Ubuntu 20.04 CI (GCC 9) With Memory Sanitizer
|
|||||||
on: [push, pull_request]
|
on: [push, pull_request]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
ubuntu-build:
|
ubuntu-build-address-sanitizier:
|
||||||
if: >-
|
if: >-
|
||||||
! contains(toJSON(github.event.commits.*.message), '[skip ci]') &&
|
! contains(toJSON(github.event.commits.*.message), '[skip ci]') &&
|
||||||
! contains(toJSON(github.event.commits.*.message), '[skip github]')
|
! contains(toJSON(github.event.commits.*.message), '[skip github]')
|
||||||
@@ -20,11 +20,22 @@ jobs:
|
|||||||
cd builddebug &&
|
cd builddebug &&
|
||||||
cmake -DSIMDJSON_SANITIZE=ON -DCMAKE_BUILD_TYPE=Debug -DSIMDJSON_GOOGLE_BENCHMARKS=OFF -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=OFF .. &&
|
cmake -DSIMDJSON_SANITIZE=ON -DCMAKE_BUILD_TYPE=Debug -DSIMDJSON_GOOGLE_BENCHMARKS=OFF -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=OFF .. &&
|
||||||
cmake --build . &&
|
cmake --build . &&
|
||||||
ctest -j --output-on-failure -LE explicitonly
|
ctest --output-on-failure -LE explicitonly -j
|
||||||
|
ubuntu-build-undefined-sanitizer:
|
||||||
|
if: >-
|
||||||
|
! contains(toJSON(github.event.commits.*.message), '[skip ci]') &&
|
||||||
|
! contains(toJSON(github.event.commits.*.message), '[skip github]')
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: dependencies/.cache
|
||||||
|
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
|
||||||
- name: Use cmake with undefined sanitizer
|
- name: Use cmake with undefined sanitizer
|
||||||
run: |
|
run: |
|
||||||
mkdir builddebugundefsani &&
|
mkdir builddebugundefsani &&
|
||||||
cd builddebugundefsani &&
|
cd builddebugundefsani &&
|
||||||
cmake -DSIMDJSON_SANITIZE_UNDEFINED=ON -DCMAKE_BUILD_TYPE=Debug -DSIMDJSON_GOOGLE_BENCHMARKS=OFF -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=OFF .. &&
|
cmake -DSIMDJSON_SANITIZE_UNDEFINED=ON -DCMAKE_BUILD_TYPE=Debug -DSIMDJSON_GOOGLE_BENCHMARKS=OFF -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=OFF .. &&
|
||||||
cmake --build . &&
|
cmake --build . &&
|
||||||
ctest -j --output-on-failure -LE explicitonly
|
ctest --output-on-failure -LE explicitonly -j
|
||||||
|
|||||||
@@ -14,19 +14,33 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
path: dependencies/.cache
|
path: dependencies/.cache
|
||||||
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
|
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
|
||||||
|
- name: Use cmake to build just the library
|
||||||
|
run: |
|
||||||
|
mkdir buildjustlib &&
|
||||||
|
cd buildjustlib &&
|
||||||
|
cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DSIMDJSON_DEVELOPER_MODE=OFF -DCMAKE_INSTALL_PREFIX:PATH=destination .. &&
|
||||||
|
cmake --build . &&
|
||||||
|
cmake --install . &&
|
||||||
|
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 &&
|
||||||
|
cd ../tests/installation_tests/find &&
|
||||||
|
mkdir buildjustlib &&
|
||||||
|
cd buildjustlib &&
|
||||||
|
cmake -DCMAKE_INSTALL_PREFIX:PATH=../../../buildjustlib/destination .. &&
|
||||||
|
cmake --build .
|
||||||
- name: Use cmake
|
- name: Use cmake
|
||||||
run: |
|
run: |
|
||||||
mkdir builddebug &&
|
mkdir builddebug &&
|
||||||
cd builddebug &&
|
cd builddebug &&
|
||||||
cmake -DCMAKE_BUILD_TYPE=Debug -DSIMDJSON_GOOGLE_BENCHMARKS=OFF -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=OFF .. &&
|
cmake -DCMAKE_BUILD_TYPE=Debug -DSIMDJSON_GOOGLE_BENCHMARKS=OFF -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=OFF .. &&
|
||||||
cmake --build . &&
|
cmake --build . &&
|
||||||
ctest -j --output-on-failure -LE explicitonly &&
|
ctest --output-on-failure -LE explicitonly -j &&
|
||||||
cd .. &&
|
cd .. &&
|
||||||
mkdir build &&
|
mkdir build &&
|
||||||
cd build &&
|
cd build &&
|
||||||
cmake -DSIMDJSON_GOOGLE_BENCHMARKS=ON -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=OFF -DCMAKE_INSTALL_PREFIX:PATH=destination .. &&
|
cmake -DSIMDJSON_GOOGLE_BENCHMARKS=ON -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=OFF -DCMAKE_INSTALL_PREFIX:PATH=destination .. &&
|
||||||
cmake --build . &&
|
cmake --build . &&
|
||||||
ctest -j --output-on-failure -LE explicitonly &&
|
ctest --output-on-failure -LE explicitonly -j &&
|
||||||
cmake --install . &&
|
cmake --install . &&
|
||||||
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 &&
|
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 &&
|
||||||
cd ../tests/installation_tests/find &&
|
cd ../tests/installation_tests/find &&
|
||||||
|
|||||||
@@ -14,12 +14,10 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
path: dependencies/.cache
|
path: dependencies/.cache
|
||||||
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
|
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
|
||||||
- name: Install clang++-13
|
|
||||||
run: sudo apt-get install -y clang++-13
|
|
||||||
- name: Use cmake
|
- name: Use cmake
|
||||||
run: |
|
run: |
|
||||||
mkdir build &&
|
mkdir build &&
|
||||||
cd build &&
|
cd build &&
|
||||||
CXX=clang++-13 cmake -DSIMDJSON_DEVELOPER_MODE=ON .. &&
|
CXX=clang++-13 cmake -DSIMDJSON_DEVELOPER_MODE=ON .. &&
|
||||||
cmake --build . &&
|
cmake --build . &&
|
||||||
ctest -j --output-on-failure -LE explicitonly
|
ctest --output-on-failure -LE explicitonly -j
|
||||||
@@ -14,12 +14,10 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
path: dependencies/.cache
|
path: dependencies/.cache
|
||||||
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
|
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
|
||||||
- name: Install clang++-14
|
|
||||||
run: sudo apt-get install -y clang++-14
|
|
||||||
- name: Use cmake
|
- name: Use cmake
|
||||||
run: |
|
run: |
|
||||||
mkdir build &&
|
mkdir build &&
|
||||||
cd build &&
|
cd build &&
|
||||||
CXX=clang++-14 cmake -DSIMDJSON_DEVELOPER_MODE=ON .. &&
|
CXX=clang++-14 cmake -DSIMDJSON_DEVELOPER_MODE=ON .. &&
|
||||||
cmake --build . &&
|
cmake --build . &&
|
||||||
ctest -j --output-on-failure -LE explicitonly
|
ctest --output-on-failure -LE explicitonly -j
|
||||||
|
|||||||
@@ -20,13 +20,13 @@ jobs:
|
|||||||
cd builddebug &&
|
cd builddebug &&
|
||||||
CXX=g++-12 cmake -DSIMDJSON_CXX_STANDARD=20 -DCMAKE_BUILD_TYPE=Debug -DSIMDJSON_GOOGLE_BENCHMARKS=OFF -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=OFF .. &&
|
CXX=g++-12 cmake -DSIMDJSON_CXX_STANDARD=20 -DCMAKE_BUILD_TYPE=Debug -DSIMDJSON_GOOGLE_BENCHMARKS=OFF -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=OFF .. &&
|
||||||
cmake --build . &&
|
cmake --build . &&
|
||||||
ctest -j --output-on-failure -LE explicitonly &&
|
ctest --output-on-failure -LE explicitonly -j &&
|
||||||
cd .. &&
|
cd .. &&
|
||||||
mkdir build &&
|
mkdir build &&
|
||||||
cd build &&
|
cd build &&
|
||||||
CXX=g++-12 cmake -DSIMDJSON_CXX_STANDARD=20 -DSIMDJSON_GOOGLE_BENCHMARKS=ON -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=OFF -DCMAKE_INSTALL_PREFIX:PATH=destination .. &&
|
CXX=g++-12 cmake -DSIMDJSON_CXX_STANDARD=20 -DSIMDJSON_GOOGLE_BENCHMARKS=ON -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=OFF -DCMAKE_INSTALL_PREFIX:PATH=destination .. &&
|
||||||
cmake --build . &&
|
cmake --build . &&
|
||||||
ctest -j --output-on-failure -LE explicitonly &&
|
ctest --output-on-failure -LE explicitonly -j &&
|
||||||
cmake --install . &&
|
cmake --install . &&
|
||||||
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 &&
|
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 &&
|
||||||
cd ../tests/installation_tests/find &&
|
cd ../tests/installation_tests/find &&
|
||||||
|
|||||||
@@ -22,4 +22,4 @@ jobs:
|
|||||||
cd build &&
|
cd build &&
|
||||||
CXX=g++-12 cmake -DSIMDJSON_DEVELOPER_MODE=ON .. &&
|
CXX=g++-12 cmake -DSIMDJSON_DEVELOPER_MODE=ON .. &&
|
||||||
cmake --build . &&
|
cmake --build . &&
|
||||||
ctest -j --output-on-failure -LE explicitonly
|
ctest --output-on-failure -LE explicitonly -j
|
||||||
+2
-2
@@ -1,4 +1,4 @@
|
|||||||
name: Ubuntu 20.04 CI (GCC 9) with Thread Sanitizer
|
name: Ubuntu 22.04 CI (GCC 11) with Thread Sanitizer
|
||||||
|
|
||||||
on: [push, pull_request]
|
on: [push, pull_request]
|
||||||
|
|
||||||
@@ -7,7 +7,7 @@ jobs:
|
|||||||
if: >-
|
if: >-
|
||||||
! contains(toJSON(github.event.commits.*.message), '[skip ci]') &&
|
! contains(toJSON(github.event.commits.*.message), '[skip ci]') &&
|
||||||
! contains(toJSON(github.event.commits.*.message), '[skip github]')
|
! contains(toJSON(github.event.commits.*.message), '[skip github]')
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-22.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: actions/cache@v3
|
- uses: actions/cache@v3
|
||||||
@@ -14,19 +14,33 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
path: dependencies/.cache
|
path: dependencies/.cache
|
||||||
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
|
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
|
||||||
|
- name: Use cmake to build just the library
|
||||||
|
run: |
|
||||||
|
mkdir buildjustlib &&
|
||||||
|
cd buildjustlib &&
|
||||||
|
cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DSIMDJSON_DEVELOPER_MODE=OFF -DCMAKE_INSTALL_PREFIX:PATH=destination .. &&
|
||||||
|
cmake --build . &&
|
||||||
|
cmake --install . &&
|
||||||
|
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 &&
|
||||||
|
cd ../tests/installation_tests/find &&
|
||||||
|
mkdir buildjustlib &&
|
||||||
|
cd buildjustlib &&
|
||||||
|
cmake -DCMAKE_INSTALL_PREFIX:PATH=../../../buildjustlib/destination .. &&
|
||||||
|
cmake --build .
|
||||||
- name: Use cmake
|
- name: Use cmake
|
||||||
run: |
|
run: |
|
||||||
mkdir builddebug &&
|
mkdir builddebug &&
|
||||||
cd builddebug &&
|
cd builddebug &&
|
||||||
cmake -DCMAKE_BUILD_TYPE=Debug -DSIMDJSON_GOOGLE_BENCHMARKS=OFF -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=OFF .. &&
|
cmake -DCMAKE_BUILD_TYPE=Debug -DSIMDJSON_GOOGLE_BENCHMARKS=OFF -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=OFF .. &&
|
||||||
cmake --build . &&
|
cmake --build . &&
|
||||||
ctest -j --output-on-failure -LE explicitonly &&
|
ctest --output-on-failure -LE explicitonly -j &&
|
||||||
cd .. &&
|
cd .. &&
|
||||||
mkdir build &&
|
mkdir build &&
|
||||||
cd build &&
|
cd build &&
|
||||||
cmake -DSIMDJSON_GOOGLE_BENCHMARKS=ON -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=OFF -DCMAKE_INSTALL_PREFIX:PATH=destination .. &&
|
cmake -DSIMDJSON_GOOGLE_BENCHMARKS=ON -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=OFF -DCMAKE_INSTALL_PREFIX:PATH=destination .. &&
|
||||||
cmake --build . &&
|
cmake --build . &&
|
||||||
ctest -j --output-on-failure -LE explicitonly &&
|
ctest --output-on-failure -LE explicitonly -j &&
|
||||||
cmake --install . &&
|
cmake --install . &&
|
||||||
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 &&
|
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 &&
|
||||||
cd ../tests/installation_tests/find &&
|
cd ../tests/installation_tests/find &&
|
||||||
|
|||||||
@@ -104,3 +104,6 @@ objs
|
|||||||
!.vscode/tasks.json
|
!.vscode/tasks.json
|
||||||
!.vscode/launch.json
|
!.vscode/launch.json
|
||||||
!.vscode/extensions.json
|
!.vscode/extensions.json
|
||||||
|
|
||||||
|
# clangd
|
||||||
|
.cache
|
||||||
Vendored
+8
-3
@@ -4,10 +4,15 @@
|
|||||||
|
|
||||||
// List of extensions which should be recommended for users of this workspace.
|
// List of extensions which should be recommended for users of this workspace.
|
||||||
"recommendations": [
|
"recommendations": [
|
||||||
// Syntax
|
// C++
|
||||||
"ms-vscode.cpptools",
|
"llvm-vs-code-extensions.vscode-clangd",
|
||||||
"ms-vscode.cmake-tools",
|
"xaver.clang-format",
|
||||||
|
// Python
|
||||||
"ms-python.python",
|
"ms-python.python",
|
||||||
|
// .github/*
|
||||||
|
"github.vscode-github-actions",
|
||||||
|
// cmake
|
||||||
|
"ms-vscode.cmake-tools",
|
||||||
"twxs.cmake"
|
"twxs.cmake"
|
||||||
],
|
],
|
||||||
// List of extensions recommended by VS Code that should not be recommended for users of this workspace.
|
// List of extensions recommended by VS Code that should not be recommended for users of this workspace.
|
||||||
|
|||||||
Vendored
+1
@@ -5,6 +5,7 @@
|
|||||||
],
|
],
|
||||||
"files.trimTrailingWhitespace": true,
|
"files.trimTrailingWhitespace": true,
|
||||||
"files.associations": {
|
"files.associations": {
|
||||||
|
".clangd": "yaml",
|
||||||
"array": "cpp",
|
"array": "cpp",
|
||||||
"iterator": "cpp",
|
"iterator": "cpp",
|
||||||
"chrono": "cpp",
|
"chrono": "cpp",
|
||||||
|
|||||||
+32
-5
@@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.14)
|
|||||||
project(
|
project(
|
||||||
simdjson
|
simdjson
|
||||||
# The version number is modified by tools/release.py
|
# The version number is modified by tools/release.py
|
||||||
VERSION 3.2.1
|
VERSION 3.6.2
|
||||||
DESCRIPTION "Parsing gigabytes of JSON per second"
|
DESCRIPTION "Parsing gigabytes of JSON per second"
|
||||||
HOMEPAGE_URL "https://simdjson.org/"
|
HOMEPAGE_URL "https://simdjson.org/"
|
||||||
LANGUAGES CXX C
|
LANGUAGES CXX C
|
||||||
@@ -20,8 +20,10 @@ string(
|
|||||||
# ---- Options, variables ----
|
# ---- Options, variables ----
|
||||||
|
|
||||||
# These version numbers are modified by tools/release.py
|
# These version numbers are modified by tools/release.py
|
||||||
set(SIMDJSON_LIB_VERSION "16.0.0" CACHE STRING "simdjson library version")
|
set(SIMDJSON_LIB_VERSION "19.0.0" CACHE STRING "simdjson library version")
|
||||||
set(SIMDJSON_LIB_SOVERSION "16" CACHE STRING "simdjson library soversion")
|
set(SIMDJSON_LIB_SOVERSION "19" CACHE STRING "simdjson library soversion")
|
||||||
|
|
||||||
|
option(SIMDJSON_BUILD_STATIC_LIB "Build simdjson_static library along with simdjson" OFF)
|
||||||
|
|
||||||
option(SIMDJSON_ENABLE_THREADS "Link with thread support" ON)
|
option(SIMDJSON_ENABLE_THREADS "Link with thread support" ON)
|
||||||
|
|
||||||
@@ -56,8 +58,17 @@ include(cmake/developer-options.cmake)
|
|||||||
|
|
||||||
# ---- simdjson library ----
|
# ---- simdjson library ----
|
||||||
|
|
||||||
add_library(simdjson src/simdjson.cpp)
|
set(SIMDJSON_SOURCES src/simdjson.cpp)
|
||||||
|
|
||||||
|
add_library(simdjson ${SIMDJSON_SOURCES})
|
||||||
add_library(simdjson::simdjson ALIAS simdjson)
|
add_library(simdjson::simdjson ALIAS simdjson)
|
||||||
|
set(SIMDJSON_LIBRARIES simdjson)
|
||||||
|
|
||||||
|
if(SIMDJSON_BUILD_STATIC_LIB)
|
||||||
|
add_library(simdjson_static STATIC ${SIMDJSON_SOURCES})
|
||||||
|
add_library(simdjson::simdjson_static ALIAS simdjson_static)
|
||||||
|
list(APPEND SIMDJSON_LIBRARIES simdjson_static)
|
||||||
|
endif()
|
||||||
|
|
||||||
set_target_properties(
|
set_target_properties(
|
||||||
simdjson PROPERTIES
|
simdjson PROPERTIES
|
||||||
@@ -117,6 +128,9 @@ if(SIMDJSON_ENABLE_THREADS)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
simdjson_apply_props(simdjson)
|
simdjson_apply_props(simdjson)
|
||||||
|
if(SIMDJSON_BUILD_STATIC_LIB)
|
||||||
|
simdjson_apply_props(simdjson_static)
|
||||||
|
endif()
|
||||||
|
|
||||||
# ---- Install rules ----
|
# ---- Install rules ----
|
||||||
|
|
||||||
@@ -138,7 +152,6 @@ install(
|
|||||||
ARCHIVE COMPONENT simdjson_Development
|
ARCHIVE COMPONENT simdjson_Development
|
||||||
INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
|
INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
|
||||||
)
|
)
|
||||||
|
|
||||||
configure_file(cmake/simdjson-config.cmake.in simdjson-config.cmake @ONLY)
|
configure_file(cmake/simdjson-config.cmake.in simdjson-config.cmake @ONLY)
|
||||||
|
|
||||||
write_basic_package_version_file(
|
write_basic_package_version_file(
|
||||||
@@ -167,6 +180,20 @@ install(
|
|||||||
COMPONENT simdjson_Development
|
COMPONENT simdjson_Development
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if(SIMDJSON_BUILD_STATIC_LIB)
|
||||||
|
install(
|
||||||
|
TARGETS simdjson_static
|
||||||
|
EXPORT simdjson_staticTargets
|
||||||
|
ARCHIVE COMPONENT simdjson_Development
|
||||||
|
)
|
||||||
|
install(
|
||||||
|
EXPORT simdjson_staticTargets
|
||||||
|
NAMESPACE simdjson::
|
||||||
|
DESTINATION "${SIMDJSON_INSTALL_CMAKEDIR}"
|
||||||
|
COMPONENT simdjson_Development
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
# pkg-config
|
# pkg-config
|
||||||
include(cmake/JoinPaths.cmake)
|
include(cmake/JoinPaths.cmake)
|
||||||
join_paths(PKGCONFIG_INCLUDEDIR "\${prefix}" "${CMAKE_INSTALL_INCLUDEDIR}")
|
join_paths(PKGCONFIG_INCLUDEDIR "\${prefix}" "${CMAKE_INSTALL_INCLUDEDIR}")
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ PROJECT_NAME = simdjson
|
|||||||
# could be handy for archiving the generated documentation or if some version
|
# could be handy for archiving the generated documentation or if some version
|
||||||
# control system is used.
|
# control system is used.
|
||||||
|
|
||||||
PROJECT_NUMBER = "3.2.1"
|
PROJECT_NUMBER = "3.6.2"
|
||||||
|
|
||||||
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
||||||
# for a project that appears at the top of each page and should give viewer a
|
# for a project that appears at the top of each page and should give viewer a
|
||||||
|
|||||||
+23
-15
@@ -73,26 +73,34 @@ simdjson's source structure, from the top level, looks like this:
|
|||||||
|
|
||||||
* **CMakeLists.txt:** The main build system.
|
* **CMakeLists.txt:** The main build system.
|
||||||
* **include:** User-facing declarations and inline definitions (most user-facing functions are inlined).
|
* **include:** User-facing declarations and inline definitions (most user-facing functions are inlined).
|
||||||
* simdjson.h: A "main include" that includes files from include/simdjson/. This is equivalent to
|
* simdjson.h: the `simdjson` namespace. A "main include" that includes files from include/simdjson/. This is equivalent to
|
||||||
the distributed simdjson.h.
|
the distributed simdjson.h.
|
||||||
* simdjson/*.h: Declarations for public simdjson classes and functions.
|
* simdjson/*.h: Declarations for public simdjson classes and functions.
|
||||||
* simdjson/*-inl.h: Definitions for public simdjson classes and functions.
|
* simdjson/*-inl.h: Definitions for public simdjson classes and functions.
|
||||||
|
* simdjson/internal/*.h: the `simdjson::internal` namespace. Private classes and functions used by the rest of simdjson.
|
||||||
|
* simdjson/dom.h: the `simdjson::dom` namespace. Includes all public DOM classes.
|
||||||
|
* simdjson/dom/*.h: Declarations/definitions for individual DOM classes.
|
||||||
|
* simdjson/arm64|fallback|haswell|icelake|ppc64|westmere.h: `simdjson::<implementation>` namesapce. Common implementation-specific tools like number and string parsing, as well as minification.
|
||||||
|
* simdjson/arm64|fallback|haswell|icelake|ppc64|westmere/*.h: implementation-specific functions such as , etc.
|
||||||
|
* simdjson/generic/*.h: the bulk of the actual code, written generically and compiled for each implementation, using functions defined in the implementation's .h files.
|
||||||
|
* simdjson/generic/dependencies.h: dependencies on common, non-implementation-specific simdjson classes. This will be included before including amalgamated.h.
|
||||||
|
* simdjson/generic/amalgamated.h: all generic ondemand classes for an implementation.
|
||||||
|
* simdjson/ondemand.h: the `simdjson::ondemand` namespace. Includes all public ondemand classes.
|
||||||
|
* simdjson/builtin.h: the `simdjson::builtin` namespace. Aliased to the most universal implementation available.
|
||||||
|
* simdjson/builtin/ondemand.h: the `simdjson::builtin::ondemand` namespace.
|
||||||
|
* simdjson/arm64|fallback|haswell|icelake|ppc64|westmere/ondemand.h: the `simdjson::<implementation>::ondemand` namespace. on demand compiled for the specific implementation.
|
||||||
|
* simdjson/generic/ondemand/*.h: individual on demand classes, generically written.
|
||||||
|
* simdjson/generic/ondemand/dependencies.h: dependencies on common, non-implementation-specific simdjson classes. This will be included before including amalgamated.h.
|
||||||
|
* simdjson/generic/ondemand/amalgamated.h: all generic ondemand classes for an implementation.
|
||||||
* **src:** The source files for non-inlined functionality (e.g. the architecture-specific parser
|
* **src:** The source files for non-inlined functionality (e.g. the architecture-specific parser
|
||||||
implementations).
|
implementations).
|
||||||
* simdjson.cpp: A "main source" that includes all implementation files from src/. This is
|
* simdjson.cpp: A "main source" that includes all implementation files from src/. This is
|
||||||
equivalent to the distributed simdjson.cpp.
|
equivalent to the distributed simdjson.cpp.
|
||||||
* arm64/|fallback/|haswell/|ppc64/|westmere/: Architecture-specific implementations. All functions are
|
* *.cpp: other misc. implementations, such as `simdjson::implementation` and the minifier.
|
||||||
Each architecture defines its own namespace, e.g. simdjson::haswell.
|
* arm64|fallback|haswell|icelake|ppc64|westmere.cpp: Architecture-specific parser implementations.
|
||||||
* generic/: Generic implementations of the simdjson parser. These files may be included and
|
* generic/*.h: `simdjson::<implementation>` namespace. Generic implementation of the parser, particularly the `dom_parser_implementation`.
|
||||||
compiled multiple times, from whichever architectures use them. They assume they are already
|
* generic/stage1/*.h: `simdjson::<implementation>::stage1` namespace. Generic implementation of the simd-heavy tokenizer/indexer pass of the simdjson parser. Used for the On Demand interface
|
||||||
enclosed in a namespace, e.g.:
|
* generic/stage2/*.h: `simdjson::<implementation>::stage2` namespace. Generic implementation of the tape creator, which consumes the index from stage 1 and actually parses numbers and string and such. Used for the DOM interface.
|
||||||
```c++
|
|
||||||
namespace simdjson {
|
|
||||||
namespace haswell {
|
|
||||||
#include "generic/stage1/json_structural_indexer.h"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Other important files and directories:
|
Other important files and directories:
|
||||||
* **.drone.yml:** Definitions for Drone CI.
|
* **.drone.yml:** Definitions for Drone CI.
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
|
|
||||||
[/badge.svg)](https://simdjson.org/plots.html)
|
[/badge.svg)](https://simdjson.org/plots.html)
|
||||||

|
|
||||||
[](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:simdjson)
|
[](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:simdjson)
|
||||||

|
|
||||||
[![][license img]][license]
|
[![][license img]][license]
|
||||||
|
|
||||||
[](https://simdjson.github.io/simdjson/)
|
[](https://simdjson.github.io/simdjson/)
|
||||||
@@ -42,8 +40,10 @@ Table of Contents
|
|||||||
Real-world usage
|
Real-world usage
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
|
- [Node.js](https://nodejs.org/)
|
||||||
- [ClickHouse](https://github.com/ClickHouse/ClickHouse)
|
- [ClickHouse](https://github.com/ClickHouse/ClickHouse)
|
||||||
- [Facebook/Meta Velox](https://velox-lib.io)
|
- [Meta Velox](https://velox-lib.io)
|
||||||
|
- [Google Pax](https://github.com/google/paxml)
|
||||||
- [milvus](https://github.com/milvus-io/milvus)
|
- [milvus](https://github.com/milvus-io/milvus)
|
||||||
- [Clang Build Analyzer](https://github.com/aras-p/ClangBuildAnalyzer)
|
- [Clang Build Analyzer](https://github.com/aras-p/ClangBuildAnalyzer)
|
||||||
- [Shopify HeapProfiler](https://github.com/Shopify/heap-profiler)
|
- [Shopify HeapProfiler](https://github.com/Shopify/heap-profiler)
|
||||||
@@ -165,6 +165,7 @@ We distinguish between "bindings" (which just wrap the C++ code) and a port to a
|
|||||||
- [simdjzon](https://github.com/travisstaloch/simdjzon): zig port.
|
- [simdjzon](https://github.com/travisstaloch/simdjzon): zig port.
|
||||||
- [JSON-Simd](https://github.com/rawleyfowler/JSON-simd): Raku bindings.
|
- [JSON-Simd](https://github.com/rawleyfowler/JSON-simd): Raku bindings.
|
||||||
- [JSON::SIMD](https://metacpan.org/pod/JSON::SIMD): Perl bindings; fully-featured JSON module that uses simdjson for decoding.
|
- [JSON::SIMD](https://metacpan.org/pod/JSON::SIMD): Perl bindings; fully-featured JSON module that uses simdjson for decoding.
|
||||||
|
- [gemmaJSON](https://github.com/sainttttt/gemmaJSON): Nim json parser based on simdjson bindings.
|
||||||
|
|
||||||
About simdjson
|
About simdjson
|
||||||
--------------
|
--------------
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
+13
-9
@@ -445,7 +445,7 @@ struct benchmarker {
|
|||||||
return 100.0 * a / b;
|
return 100.0 * a / b;
|
||||||
}
|
}
|
||||||
|
|
||||||
void print(bool tabbed_output) const {
|
void print(bool tabbed_output, bool stage1_only) const {
|
||||||
if (tabbed_output) {
|
if (tabbed_output) {
|
||||||
char* filename_copy = reinterpret_cast<char*>(malloc(strlen(filename)+1));
|
char* filename_copy = reinterpret_cast<char*>(malloc(strlen(filename)+1));
|
||||||
SIMDJSON_PUSH_DISABLE_WARNINGS
|
SIMDJSON_PUSH_DISABLE_WARNINGS
|
||||||
@@ -503,17 +503,21 @@ struct benchmarker {
|
|||||||
stats->blocks_with_16_structurals_flipped, percent(stats->blocks_with_16_structurals_flipped, stats->blocks));
|
stats->blocks_with_16_structurals_flipped, percent(stats->blocks_with_16_structurals_flipped, stats->blocks));
|
||||||
}
|
}
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf("All Stages (excluding allocation)\n");
|
if(!stage1_only) {
|
||||||
print_aggregate("| " , all_stages_without_allocation.best);
|
printf("All Stages (excluding allocation)\n");
|
||||||
// frequently, allocation is a tiny fraction of the running time so we omit it
|
print_aggregate("| " , all_stages_without_allocation.best);
|
||||||
if(allocate_stage.best.elapsed_sec() > 0.01 * all_stages_without_allocation.best.elapsed_sec()) {
|
// frequently, allocation is a tiny fraction of the running time so we omit it
|
||||||
printf("|- Allocation\n");
|
if(allocate_stage.best.elapsed_sec() > 0.01 * all_stages_without_allocation.best.elapsed_sec()) {
|
||||||
print_aggregate("| ", allocate_stage.best);
|
printf("|- Allocation\n");
|
||||||
|
print_aggregate("| ", allocate_stage.best);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
printf("|- Stage 1\n");
|
printf("|- Stage 1\n");
|
||||||
print_aggregate("| ", stage1.best);
|
print_aggregate("| ", stage1.best);
|
||||||
printf("|- Stage 2\n");
|
if(!stage1_only) {
|
||||||
print_aggregate("| ", stage2.best);
|
printf("|- Stage 2\n");
|
||||||
|
print_aggregate("| ", stage2.best);
|
||||||
|
}
|
||||||
if (collector.has_events()) {
|
if (collector.has_events()) {
|
||||||
double freq1 = (stage1.best.cycles() / stage1.best.elapsed_sec()) / 1000000000.0;
|
double freq1 = (stage1.best.cycles() / stage1.best.elapsed_sec()) / 1000000000.0;
|
||||||
double freq2 = (stage2.best.cycles() / stage2.best.elapsed_sec()) / 1000000000.0;
|
double freq2 = (stage2.best.cycles() / stage2.best.elapsed_sec()) / 1000000000.0;
|
||||||
|
|||||||
@@ -218,7 +218,7 @@ int main(int argc, char *argv[]) {
|
|||||||
if (!options.verbose) { progress.erase(); }
|
if (!options.verbose) { progress.erase(); }
|
||||||
|
|
||||||
for (size_t i=0; i<options.files.size(); i++) {
|
for (size_t i=0; i<options.files.size(); i++) {
|
||||||
benchmarkers[i]->print(options.tabbed_output);
|
benchmarkers[i]->print(options.tabbed_output, options.stage1_only);
|
||||||
delete benchmarkers[i];
|
delete benchmarkers[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,11 +34,15 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "linux-perf-events.h"
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
|
#include "linux-perf-events.h"
|
||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if __APPLE__ && __aarch64__
|
||||||
|
#include "apple/apple_arm_events.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "simdjson.h"
|
#include "simdjson.h"
|
||||||
|
|
||||||
using std::string;
|
using std::string;
|
||||||
@@ -134,7 +138,7 @@ struct event_collector {
|
|||||||
|
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
LinuxEvents<PERF_TYPE_HARDWARE> linux_events;
|
LinuxEvents<PERF_TYPE_HARDWARE> linux_events;
|
||||||
event_collector(simdjson_unused bool quiet = false) : linux_events(vector<int>{
|
event_collector() : linux_events(vector<int>{
|
||||||
#if SIMDJSON_SIMPLE_PERFORMANCE_COUNTERS
|
#if SIMDJSON_SIMPLE_PERFORMANCE_COUNTERS
|
||||||
PERF_COUNT_HW_CPU_CYCLES,
|
PERF_COUNT_HW_CPU_CYCLES,
|
||||||
PERF_COUNT_HW_INSTRUCTIONS,
|
PERF_COUNT_HW_INSTRUCTIONS,
|
||||||
@@ -149,8 +153,17 @@ struct event_collector {
|
|||||||
bool has_events() {
|
bool has_events() {
|
||||||
return linux_events.is_working();
|
return linux_events.is_working();
|
||||||
}
|
}
|
||||||
|
#elif __APPLE__ && __aarch64__
|
||||||
|
AppleEvents apple_events;
|
||||||
|
performance_counters diff;
|
||||||
|
event_collector() : diff(0) {
|
||||||
|
apple_events.setup_performance_counters();
|
||||||
|
}
|
||||||
|
bool has_events() {
|
||||||
|
return apple_events.setup_performance_counters();
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
event_collector(simdjson_unused bool _quiet = false) {}
|
event_collector() {}
|
||||||
bool has_events() {
|
bool has_events() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -159,6 +172,8 @@ struct event_collector {
|
|||||||
simdjson_inline void start() {
|
simdjson_inline void start() {
|
||||||
#if defined(__linux)
|
#if defined(__linux)
|
||||||
linux_events.start();
|
linux_events.start();
|
||||||
|
#elif __APPLE__ && __aarch64__
|
||||||
|
if(has_events()) { diff = apple_events.get_counters(); }
|
||||||
#endif
|
#endif
|
||||||
start_clock = steady_clock::now();
|
start_clock = steady_clock::now();
|
||||||
}
|
}
|
||||||
@@ -166,6 +181,16 @@ struct event_collector {
|
|||||||
time_point<steady_clock> end_clock = steady_clock::now();
|
time_point<steady_clock> end_clock = steady_clock::now();
|
||||||
#if defined(__linux)
|
#if defined(__linux)
|
||||||
linux_events.end(count.event_counts);
|
linux_events.end(count.event_counts);
|
||||||
|
#elif __APPLE__ && __aarch64__
|
||||||
|
if(has_events()) {
|
||||||
|
performance_counters end = apple_events.get_counters();
|
||||||
|
diff = end - diff;
|
||||||
|
}
|
||||||
|
count.event_counts[0] = diff.cycles;
|
||||||
|
count.event_counts[1] = diff.instructions;
|
||||||
|
count.event_counts[2] = diff.missed_branches;
|
||||||
|
count.event_counts[3] = 0;
|
||||||
|
count.event_counts[4] = 0;
|
||||||
#endif
|
#endif
|
||||||
count.elapsed = end_clock - start_clock;
|
count.elapsed = end_clock - start_clock;
|
||||||
return count;
|
return count;
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ void maybe_display_implementation() {
|
|||||||
template<typename B, typename R> static void run_json_benchmark(benchmark::State &state) {
|
template<typename B, typename R> static void run_json_benchmark(benchmark::State &state) {
|
||||||
maybe_display_implementation();
|
maybe_display_implementation();
|
||||||
|
|
||||||
event_collector collector(true);
|
event_collector collector;
|
||||||
event_aggregate events;
|
event_aggregate events;
|
||||||
|
|
||||||
// Warmup and equality check (make sure the data is right!)
|
// Warmup and equality check (make sure the data is right!)
|
||||||
|
|||||||
@@ -114,10 +114,14 @@ set(SIMDJSON_CXX_STANDARD 17 CACHE STRING "the C++ standard to use for simdjson"
|
|||||||
set(CMAKE_CXX_STANDARD ${SIMDJSON_CXX_STANDARD})
|
set(CMAKE_CXX_STANDARD ${SIMDJSON_CXX_STANDARD})
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||||
set(CMAKE_MACOSX_RPATH OFF)
|
|
||||||
set(CMAKE_THREAD_PREFER_PTHREAD ON)
|
set(CMAKE_THREAD_PREFER_PTHREAD ON)
|
||||||
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||||
|
set(SIMDJSON_STRUCTURAL_INDEXER_STEP CACHE STRING "the SIMDJSON_STRUCTURAL_INDEXER_STEP variable")
|
||||||
|
|
||||||
|
if(SIMDJSON_STRUCTURAL_INDEXER_STEP)
|
||||||
|
message(STATUS "Setting SIMDJSON_STRUCTURAL_INDEXER_STEP to ${SIMDJSON_STRUCTURAL_INDEXER_STEP}.")
|
||||||
|
add_compile_definitions(SIMDJSON_STRUCTURAL_INDEXER_STEP=${SIMDJSON_STRUCTURAL_INDEXER_STEP})
|
||||||
|
endif()
|
||||||
# LTO seems to create all sorts of fun problems. Let us
|
# LTO seems to create all sorts of fun problems. Let us
|
||||||
# disable temporarily.
|
# disable temporarily.
|
||||||
#include(CheckIPOSupported)
|
#include(CheckIPOSupported)
|
||||||
|
|||||||
@@ -4,3 +4,4 @@ if("@SIMDJSON_ENABLE_THREADS@")
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
include("${CMAKE_CURRENT_LIST_DIR}/simdjsonTargets.cmake")
|
include("${CMAKE_CURRENT_LIST_DIR}/simdjsonTargets.cmake")
|
||||||
|
include("${CMAKE_CURRENT_LIST_DIR}/simdjson_staticTargets.cmake" OPTIONAL)
|
||||||
|
|||||||
+203
-46
@@ -30,6 +30,7 @@ An overview of what you need to know to use simdjson, with examples.
|
|||||||
- [Dynamic Number Types](#dynamic-number-types)
|
- [Dynamic Number Types](#dynamic-number-types)
|
||||||
- [Raw Strings](#raw-strings)
|
- [Raw Strings](#raw-strings)
|
||||||
- [General Direct Access to the Raw JSON String](#general-direct-access-to-the-raw-json-string)
|
- [General Direct Access to the Raw JSON String](#general-direct-access-to-the-raw-json-string)
|
||||||
|
- [Storing Directly into an Existing String Instance](#storing-directly-into-an-existing-string-instance)
|
||||||
- [Thread Safety](#thread-safety)
|
- [Thread Safety](#thread-safety)
|
||||||
- [Standard Compliance](#standard-compliance)
|
- [Standard Compliance](#standard-compliance)
|
||||||
- [Backwards Compatibility](#backwards-compatibility)
|
- [Backwards Compatibility](#backwards-compatibility)
|
||||||
@@ -85,7 +86,7 @@ include(FetchContent)
|
|||||||
FetchContent_Declare(
|
FetchContent_Declare(
|
||||||
simdjson
|
simdjson
|
||||||
GIT_REPOSITORY https://github.com/simdjson/simdjson.git
|
GIT_REPOSITORY https://github.com/simdjson/simdjson.git
|
||||||
GIT_TAG tags/v0.9.6
|
GIT_TAG tags/v3.6.0
|
||||||
GIT_SHALLOW TRUE)
|
GIT_SHALLOW TRUE)
|
||||||
|
|
||||||
FetchContent_MakeAvailable(simdjson)
|
FetchContent_MakeAvailable(simdjson)
|
||||||
@@ -179,8 +180,8 @@ strcpy(json, "[1]");
|
|||||||
ondemand::document doc = parser.iterate(json, strlen(json), sizeof(json));
|
ondemand::document doc = parser.iterate(json, strlen(json), sizeof(json));
|
||||||
```
|
```
|
||||||
|
|
||||||
The simdjson library will also accept `std::string` instances, as long as the `capacity()` of
|
The simdjson library will also accept `std::string` instances. If the provided
|
||||||
the string exceeds the `size()` by at least `SIMDJSON_PADDING`. You can increase the `capacity()` with the `reserve()` function of your strings.
|
reference is non-const, it will allocate padding as needed.
|
||||||
|
|
||||||
You can copy your data directly on a `simdjson::padded_string` as follows:
|
You can copy your data directly on a `simdjson::padded_string` as follows:
|
||||||
|
|
||||||
@@ -218,7 +219,8 @@ This means that while you iterate an array, or search for a field in an object,
|
|||||||
walking through the original JSON text, merrily reading commas and colons and brackets to make sure
|
walking through the original JSON text, merrily reading commas and colons and brackets to make sure
|
||||||
you get where you are going. This is the key to On Demand's performance: since it's just an iterator,
|
you get where you are going. This is the key to On Demand's performance: since it's just an iterator,
|
||||||
it lets you parse values as you use them. And particularly, it lets you *skip* values you do not want
|
it lets you parse values as you use them. And particularly, it lets you *skip* values you do not want
|
||||||
to use.
|
to use. On Demand is also ideally suited when you want to capture part of the document without parsing it
|
||||||
|
immediately (e.g., see [Raw Strings](#raw-strings)).
|
||||||
|
|
||||||
We refer to "On Demand" as a front-end component since it is an interface between the
|
We refer to "On Demand" as a front-end component since it is an interface between the
|
||||||
low-level parsing functions and the user. It hides much of the complexity of parsing JSON
|
low-level parsing functions and the user. It hides much of the complexity of parsing JSON
|
||||||
@@ -253,7 +255,8 @@ copy the data into their own favorite class instances (e.g., alternatives to `st
|
|||||||
|
|
||||||
A `std::string_view` instance is effectively just a pointer to a region in memory representing
|
A `std::string_view` instance is effectively just a pointer to a region in memory representing
|
||||||
a string. In simdjson, we return `std::string_view` instances that either point within the
|
a string. In simdjson, we return `std::string_view` instances that either point within the
|
||||||
input string you parsed, or to a temporary string buffer inside our parser class instances.
|
input string you parsed (when using [raw Strings](#raw-strings)), or to a temporary string buffer inside
|
||||||
|
our parser class instances that is valid until the parser object is destroyed or you use it to parse another document.
|
||||||
When using `std::string_view` instances, it is your responsibility to ensure that
|
When using `std::string_view` instances, it is your responsibility to ensure that
|
||||||
`std::string_view` instance does not outlive the pointed-to memory (e.g., either the input
|
`std::string_view` instance does not outlive the pointed-to memory (e.g., either the input
|
||||||
buffer or the parser instance). Furthermore, some operations reset the string buffer
|
buffer or the parser instance). Furthermore, some operations reset the string buffer
|
||||||
@@ -261,6 +264,7 @@ inside our parser instances: e.g., when we parse a new document. Thus a `std::st
|
|||||||
is often best viewed as a temporary string value that is tied to the document you are parsing.
|
is often best viewed as a temporary string value that is tied to the document you are parsing.
|
||||||
At the cost of some memory allocation, you may convert your `std::string_view` instances for long-term storage into `std::string` instances:
|
At the cost of some memory allocation, you may convert your `std::string_view` instances for long-term storage into `std::string` instances:
|
||||||
`std::string mycopy(view)` (C++17) or `std::string mycopy(view.begin(), view.end())` (prior to C++17).
|
`std::string mycopy(view)` (C++17) or `std::string mycopy(view.begin(), view.end())` (prior to C++17).
|
||||||
|
For convenience, we also allow [storing an escaped string directly into an existing string instance](#storing-directly-into-an-existing-string-instance).
|
||||||
|
|
||||||
The `std::string_view` class has become standard as part of C++17 but it is not always available
|
The `std::string_view` class has become standard as part of C++17 but it is not always available
|
||||||
on compilers which only supports C++11. When we detect that `string_view` is natively
|
on compilers which only supports C++11. When we detect that `string_view` is natively
|
||||||
@@ -355,7 +359,7 @@ support for users who avoid exceptions. See [the simdjson error handling documen
|
|||||||
* **Field Access:** To get the value of the "foo" field in an object, use `object["foo"]`. This will
|
* **Field Access:** To get the value of the "foo" field in an object, use `object["foo"]`. This will
|
||||||
scan through the object looking for the field with the matching string, doing a character-by-character
|
scan through the object looking for the field with the matching string, doing a character-by-character
|
||||||
comparison. It may generate the error `simdjson::NO_SUCH_FIELD` if there is no such key in the object, it may throw an exception (see [Error Handling](#error-handling)). For efficiency reason, you should avoid looking up the same field repeatedly: e.g., do
|
comparison. It may generate the error `simdjson::NO_SUCH_FIELD` if there is no such key in the object, it may throw an exception (see [Error Handling](#error-handling)). For efficiency reason, you should avoid looking up the same field repeatedly: e.g., do
|
||||||
not do `object["foo"]` followed by `object["foo"]` with the same `object` instance. Keep in mind that On Demand does not buffer or save the result of the parsing: if you repeatedly access `object["foo"]`, then it must repeatedly seek the key and parse the content. The library does not provide a distinct function to check if a key is present, instead we recommend you attempt to access the key: e.g., by doing `ondemand::value val{}; if(!object["foo"].get(val)) {...}`, you have that `val` contains the requested value inside the if clause. It is your responsibility as a user to temporarily keep a reference to the value (`auto v = object["foo"]`), or to consume the content and store it in your own data structures. If you consume an
|
not do `object["foo"]` followed by `object["foo"]` with the same `object` instance. For best performance, you should try to query the keys in the same order they appear in the document. If you need several keys and you cannot predict the order they will appear in, it is recommended to iterate through all keys `for(auto field : object) {...}`. Keep in mind that On Demand does not buffer or save the result of the parsing: if you repeatedly access `object["foo"]`, then it must repeatedly seek the key and parse the content. The library does not provide a distinct function to check if a key is present, instead we recommend you attempt to access the key: e.g., by doing `ondemand::value val{}; if (!object["foo"].get(val)) {...}`, you have that `val` contains the requested value inside the if clause. It is your responsibility as a user to temporarily keep a reference to the value (`auto v = object["foo"]`), or to consume the content and store it in your own data structures. If you consume an
|
||||||
object twice: `std::string_view(object["foo"]` followed by `std::string_view(object["foo"]` then your code
|
object twice: `std::string_view(object["foo"]` followed by `std::string_view(object["foo"]` then your code
|
||||||
is in error. Furthermore, you can only consume one field at a time, on the same object. The
|
is in error. Furthermore, you can only consume one field at a time, on the same object. The
|
||||||
value instance you get from `content["bids"]` becomes invalid when you call `content["asks"]`.
|
value instance you get from `content["bids"]` becomes invalid when you call `content["asks"]`.
|
||||||
@@ -370,7 +374,11 @@ support for users who avoid exceptions. See [the simdjson error handling documen
|
|||||||
> as a key, it will not be recognized. This is not generally a problem. Nevertheless, if you do need
|
> as a key, it will not be recognized. This is not generally a problem. Nevertheless, if you do need
|
||||||
> to support escaped keys, the method `unescaped_key()` provides the desired unescaped keys by
|
> to support escaped keys, the method `unescaped_key()` provides the desired unescaped keys by
|
||||||
> parsing and writing out the unescaped keys to a string buffer and returning a `std::string_view`
|
> parsing and writing out the unescaped keys to a string buffer and returning a `std::string_view`
|
||||||
> instance. You should expect a performance penalty when using `unescaped_key()`.
|
> instance. The `unescaped_key` takes an optional Boolean value: passing it true will decode invalid
|
||||||
|
> Unicode sequences with replacement, meaning that the decoding always succeeds but bogus Unicode
|
||||||
|
> replacement characters are inserted. In general, you should expect a performance penalty
|
||||||
|
> when using `unescaped_key()` compared to `key()` because of the string processing: the `key()`
|
||||||
|
> function just points inside the source JSON document.
|
||||||
>
|
>
|
||||||
> ```c++
|
> ```c++
|
||||||
> auto json = R"({"k\u0065y": 1})"_padded;
|
> auto json = R"({"k\u0065y": 1})"_padded;
|
||||||
@@ -381,7 +389,7 @@ support for users who avoid exceptions. See [the simdjson error handling documen
|
|||||||
> // parses and writes out the key, after unescaping it,
|
> // parses and writes out the key, after unescaping it,
|
||||||
> // to a string buffer. It causes a performance penalty.
|
> // to a string buffer. It causes a performance penalty.
|
||||||
> std::string_view keyv = field.unescaped_key();
|
> std::string_view keyv = field.unescaped_key();
|
||||||
> if(keyv == "key") { std::cout << uint64_t(field.value()); }
|
> if (keyv == "key") { std::cout << uint64_t(field.value()); }
|
||||||
> }
|
> }
|
||||||
> ```
|
> ```
|
||||||
>
|
>
|
||||||
@@ -414,8 +422,10 @@ support for users who avoid exceptions. See [the simdjson error handling documen
|
|||||||
step through each value in the JSON array.
|
step through each value in the JSON array.
|
||||||
|
|
||||||
If you know the type of the value, you can cast it right there, too! `for (double value : array) { ... }`.
|
If you know the type of the value, you can cast it right there, too! `for (double value : array) { ... }`.
|
||||||
* **Object Iteration:** You can iterate through an object's fields, as well: `for (auto field : object) { ... }`
|
|
||||||
- `field.unescaped_key()` will get you the unescaped key string.
|
You may also use explicit iterators: `for(auto i = array.begin(); i != array.end(); i++) {}`. You can check that an array is empty with the condition `auto i = array.begin(); if(i == array.end()) {...}`.
|
||||||
|
* **Object Iteration:** You can iterate through an object's fields, as well: `for (auto field : object) { ... }`. You may also use explicit iterators : `for(auto i = object.begin(); i != object.end(); i++) { auto field = *i; .... }`. You can check that an object is empty with the condition `auto i = object.begin(); if(i == object.end()) {...}`.
|
||||||
|
- `field.unescaped_key()` will get you the unescaped key string. E.g., the JSON string `"\u00e1"` becomes the Unicode string `á`. Optionally, you pass `true` as a parameter to the `unescaped_key` method if you want invalid escape sequences to be replaced by a default replacement character (e.g., `\ud800\ud801\ud811`): otherwise bad escape sequences lead to an immediate error.
|
||||||
- `field.value()` will get you the value, which you can then use all these other methods on.
|
- `field.value()` will get you the value, which you can then use all these other methods on.
|
||||||
* **Array Index:** Because it is forward-only, you cannot look up an array element by index by index. Instead,
|
* **Array Index:** Because it is forward-only, you cannot look up an array element by index by index. Instead,
|
||||||
you should iterate through the array and keep an index yourself.
|
you should iterate through the array and keep an index yourself.
|
||||||
@@ -445,7 +455,7 @@ support for users who avoid exceptions. See [the simdjson error handling documen
|
|||||||
> {
|
> {
|
||||||
> ondemand::parser parser;
|
> ondemand::parser parser;
|
||||||
> for (ondemand::object car : parser.iterate(cars_json)) {
|
> for (ondemand::object car : parser.iterate(cars_json)) {
|
||||||
> if(uint64_t(car["year"]) > 2000) {
|
> if (uint64_t(car["year"]) > 2000) {
|
||||||
> arrays.push_back(simdjson::to_json_string(car["tire_pressure"]));
|
> arrays.push_back(simdjson::to_json_string(car["tire_pressure"]));
|
||||||
> }
|
> }
|
||||||
> }
|
> }
|
||||||
@@ -454,7 +464,7 @@ support for users who avoid exceptions. See [the simdjson error handling documen
|
|||||||
> std::ostringstream oss;
|
> std::ostringstream oss;
|
||||||
> oss << "[";
|
> oss << "[";
|
||||||
> for(size_t i = 0; i < arrays.size(); i++) {
|
> for(size_t i = 0; i < arrays.size(); i++) {
|
||||||
> if(i>0) { oss << ","; }
|
> if (i>0) { oss << ","; }
|
||||||
> oss << arrays[i];
|
> oss << arrays[i];
|
||||||
> }
|
> }
|
||||||
> oss << "]";
|
> oss << "]";
|
||||||
@@ -535,9 +545,7 @@ support for users who avoid exceptions. See [the simdjson error handling documen
|
|||||||
* **Tree Walking and JSON Element Types:** Sometimes you don't necessarily have a document
|
* **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.
|
with a known type, and are trying to generically inspect or walk over JSON elements.
|
||||||
You can also represent arbitrary JSON values with
|
You can also represent arbitrary JSON values with
|
||||||
`ondemand::value` instances: it can represent anything except a scalar document (lone number, string, null or Boolean). You can check for scalar documents with the method `scalar()`.
|
`ondemand::value` instances: it can represent anything except a scalar document (lone number, string, null or Boolean). You can check for scalar documents with the method `scalar()`. You can cast a document that is either an array or an object to an `ondemand::value` instance immediately after you create the document instance: you cannot create a `ondemand::value` instance from a document that has already been accessed as it would mean that you would have two instances of the object or array simultaneously (see [rewinding](#rewinding)). You can query the type of a document or a value with the `type()` method. The `type()` method does not consume or validate documents and values, but it tells you whether they are
|
||||||
You can query the type of a document or a value with the `type()` method.
|
|
||||||
The `type()` method does not consume or validate documents and values, but it tells you whether they are
|
|
||||||
- arrays (`json_type::array`),
|
- arrays (`json_type::array`),
|
||||||
- objects (`json_type::object`)
|
- objects (`json_type::object`)
|
||||||
- numbers (`json_type::number`),
|
- numbers (`json_type::number`),
|
||||||
@@ -597,7 +605,7 @@ support for users who avoid exceptions. See [the simdjson error handling documen
|
|||||||
case ondemand::json_type::null:
|
case ondemand::json_type::null:
|
||||||
// We check that the value is indeed null
|
// We check that the value is indeed null
|
||||||
// otherwise: an error is thrown.
|
// otherwise: an error is thrown.
|
||||||
if(element.is_null()) {
|
if (element.is_null()) {
|
||||||
cout << "null";
|
cout << "null";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -910,11 +918,11 @@ bool simple_error_example() {
|
|||||||
ondemand::parser parser;
|
ondemand::parser parser;
|
||||||
auto json = R"({"bad number":3.14.1 })"_padded;
|
auto json = R"({"bad number":3.14.1 })"_padded;
|
||||||
ondemand::document doc;
|
ondemand::document doc;
|
||||||
if( parser.iterate(json).get(doc) != SUCCESS ) { return false; }
|
if (parser.iterate(json).get(doc) != SUCCESS) { return false; }
|
||||||
double x;
|
double x;
|
||||||
auto error = doc["bad number"].get_double().get(x);
|
auto error = doc["bad number"].get_double().get(x);
|
||||||
// returns "simdjson::NUMBER_ERROR"
|
// returns "simdjson::NUMBER_ERROR"
|
||||||
if(error != SUCCESS) {
|
if (error != SUCCESS) {
|
||||||
std::cout << error << std::endl;
|
std::cout << error << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -976,10 +984,10 @@ it selects the key `"count"` within that object.
|
|||||||
int main(void) {
|
int main(void) {
|
||||||
simdjson::ondemand::parser parser;
|
simdjson::ondemand::parser parser;
|
||||||
auto error = padded_string::load("twitter.json").get(json);
|
auto error = padded_string::load("twitter.json").get(json);
|
||||||
if(error) { std::cerr << error << std::endl; return EXIT_FAILURE; }
|
if (error) { std::cerr << error << std::endl; return EXIT_FAILURE; }
|
||||||
simdjson::ondemand::document tweets;
|
simdjson::ondemand::document tweets;
|
||||||
error = parser.iterate(json).get(tweets);
|
error = parser.iterate(json).get(tweets);
|
||||||
if( error ) { std::cerr << error << std::endl; return EXIT_FAILURE; }
|
if (error) { std::cerr << error << std::endl; return EXIT_FAILURE; }
|
||||||
simdjson::ondemand::value res;
|
simdjson::ondemand::value res;
|
||||||
error = tweets["search_metadata"]["count"].get(res);
|
error = tweets["search_metadata"]["count"].get(res);
|
||||||
if (error != SUCCESS) {
|
if (error != SUCCESS) {
|
||||||
@@ -1010,12 +1018,12 @@ int main(void) {
|
|||||||
simdjson::ondemand::document tweets;
|
simdjson::ondemand::document tweets;
|
||||||
padded_string json;
|
padded_string json;
|
||||||
auto error = padded_string::load("twitter.json").get(json);
|
auto error = padded_string::load("twitter.json").get(json);
|
||||||
if(error) { std::cerr << error << std::endl; return EXIT_FAILURE; }
|
if (error) { std::cerr << error << std::endl; return EXIT_FAILURE; }
|
||||||
error = parser.iterate(json).get(tweets);
|
error = parser.iterate(json).get(tweets);
|
||||||
if(error) { std::cerr << error << std::endl; return EXIT_FAILURE; }
|
if (error) { std::cerr << error << std::endl; return EXIT_FAILURE; }
|
||||||
uint64_t identifier;
|
uint64_t identifier;
|
||||||
error = tweets["statuses"].at(0)["id"].get(identifier);
|
error = tweets["statuses"].at(0)["id"].get(identifier);
|
||||||
if(error) { std::cerr << error << std::endl; return EXIT_FAILURE; }
|
if (error) { std::cerr << error << std::endl; return EXIT_FAILURE; }
|
||||||
std::cout << identifier << std::endl;
|
std::cout << identifier << std::endl;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -1039,40 +1047,40 @@ bool parse() {
|
|||||||
|
|
||||||
// Iterating through an array of objects
|
// Iterating through an array of objects
|
||||||
auto error = parser.iterate(cars_json).get(doc);
|
auto error = parser.iterate(cars_json).get(doc);
|
||||||
if(error) { std::cerr << error << std::endl; return false; }
|
if (error) { std::cerr << error << std::endl; return false; }
|
||||||
ondemand::array cars; // invalid until the get() succeeds
|
ondemand::array cars; // invalid until the get() succeeds
|
||||||
error = doc.get_array().get(cars);
|
error = doc.get_array().get(cars);
|
||||||
|
|
||||||
for (auto car_value : cars) {
|
for (auto car_value : cars) {
|
||||||
ondemand::object car; // invalid until the get() succeeds
|
ondemand::object car; // invalid until the get() succeeds
|
||||||
error = car_value.get_object().get(car);
|
error = car_value.get_object().get(car);
|
||||||
if(error) { std::cerr << error << std::endl; return false; }
|
if (error) { std::cerr << error << std::endl; return false; }
|
||||||
|
|
||||||
// Accessing a field by name
|
// Accessing a field by name
|
||||||
std::string_view make;
|
std::string_view make;
|
||||||
std::string_view model;
|
std::string_view model;
|
||||||
error = car["make"].get(make);
|
error = car["make"].get(make);
|
||||||
if(error) { std::cerr << error << std::endl; return false; }
|
if (error) { std::cerr << error << std::endl; return false; }
|
||||||
error = car["model"].get(model);
|
error = car["model"].get(model);
|
||||||
if(error) { std::cerr << error << std::endl; return false; }
|
if (error) { std::cerr << error << std::endl; return false; }
|
||||||
|
|
||||||
cout << "Make/Model: " << make << "/" << model << endl;
|
cout << "Make/Model: " << make << "/" << model << endl;
|
||||||
|
|
||||||
// Casting a JSON element to an integer
|
// Casting a JSON element to an integer
|
||||||
uint64_t year{};
|
uint64_t year{};
|
||||||
error = car["year"].get(year);
|
error = car["year"].get(year);
|
||||||
if(error) { std::cerr << error << std::endl; return false; }
|
if (error) { std::cerr << error << std::endl; return false; }
|
||||||
cout << "- This car is " << 2020 - year << " years old." << endl;
|
cout << "- This car is " << 2020 - year << " years old." << endl;
|
||||||
|
|
||||||
// Iterating through an array of floats
|
// Iterating through an array of floats
|
||||||
double total_tire_pressure = 0;
|
double total_tire_pressure = 0;
|
||||||
ondemand::array pressures;
|
ondemand::array pressures;
|
||||||
error = car["tire_pressure"].get_array().get(pressures);
|
error = car["tire_pressure"].get_array().get(pressures);
|
||||||
if(error) { std::cerr << error << std::endl; return false; }
|
if (error) { std::cerr << error << std::endl; return false; }
|
||||||
for (auto tire_pressure_value : pressures) {
|
for (auto tire_pressure_value : pressures) {
|
||||||
double tire_pressure;
|
double tire_pressure;
|
||||||
error = tire_pressure_value.get_double().get(tire_pressure);
|
error = tire_pressure_value.get_double().get(tire_pressure);
|
||||||
if(error) { std::cerr << error << std::endl; return false; }
|
if (error) { std::cerr << error << std::endl; return false; }
|
||||||
total_tire_pressure += tire_pressure;
|
total_tire_pressure += tire_pressure;
|
||||||
}
|
}
|
||||||
cout << "- Average tire pressure: " << (total_tire_pressure / 4) << endl;
|
cout << "- Average tire pressure: " << (total_tire_pressure / 4) << endl;
|
||||||
@@ -1088,7 +1096,7 @@ after you have initialized them and checked that there is no error:
|
|||||||
ondemand::object car; // invalid until the get() succeeds
|
ondemand::object car; // invalid until the get() succeeds
|
||||||
// the `car` instance should not use used before it is initialized
|
// the `car` instance should not use used before it is initialized
|
||||||
error = car_value.get_object().get(car);
|
error = car_value.get_object().get(car);
|
||||||
if(error) {
|
if (error) {
|
||||||
// the `car` instance should not use used
|
// the `car` instance should not use used
|
||||||
} else {
|
} else {
|
||||||
// the `car` instance can be safely used
|
// the `car` instance can be safely used
|
||||||
@@ -1102,20 +1110,20 @@ having to handle exceptions.
|
|||||||
ondemand::parser parser;
|
ondemand::parser parser;
|
||||||
ondemand::document doc;
|
ondemand::document doc;
|
||||||
auto error = parser.iterate(json).get(doc);
|
auto error = parser.iterate(json).get(doc);
|
||||||
if(error) { return false; }
|
if (error) { return false; }
|
||||||
ondemand::object object; // invalid until the get() succeeds
|
ondemand::object object; // invalid until the get() succeeds
|
||||||
error = doc.get_object().get(object);
|
error = doc.get_object().get(object);
|
||||||
if(error) { return false; }
|
if (error) { return false; }
|
||||||
for(auto field : object) {
|
for(auto field : object) {
|
||||||
// We could replace 'field.key() with field.unescaped_key(),
|
// We could replace 'field.key() with field.unescaped_key(),
|
||||||
// and ondemand::raw_json_string by std::string_view.
|
// and ondemand::raw_json_string by std::string_view.
|
||||||
ondemand::raw_json_string keyv;
|
ondemand::raw_json_string keyv;
|
||||||
error = field.key().get(keyv);
|
error = field.key().get(keyv);
|
||||||
if(error) { return false; }
|
if (error) { return false; }
|
||||||
if(keyv == "key") {
|
if (keyv == "key") {
|
||||||
uint64_t intvalue;
|
uint64_t intvalue;
|
||||||
error = field.value().get(intvalue);
|
error = field.value().get(intvalue);
|
||||||
if(error) { return false; }
|
if (error) { return false; }
|
||||||
std::cout << intvalue;
|
std::cout << intvalue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1294,7 +1302,7 @@ content.
|
|||||||
for (uint64_t values : array) {
|
for (uint64_t values : array) {
|
||||||
std::cout << values << std::endl;
|
std::cout << values << std::endl;
|
||||||
}
|
}
|
||||||
if(!doc.at_end()) {
|
if (!doc.at_end()) {
|
||||||
// In this instance, we will be left pointing at 'foo' since we have consumed the array [1,2].
|
// In this instance, we will be left pointing at 'foo' since we have consumed the array [1,2].
|
||||||
std::cerr << "trailing content at byte index " << doc.current_location() - json.data() << std::endl;
|
std::cerr << "trailing content at byte index " << doc.current_location() - json.data() << std::endl;
|
||||||
}
|
}
|
||||||
@@ -1324,7 +1332,7 @@ before printout the data.
|
|||||||
|
|
||||||
auto doc = parser.iterate(cars_json);
|
auto doc = parser.iterate(cars_json);
|
||||||
for (simdjson_unused ondemand::object car : doc) {
|
for (simdjson_unused ondemand::object car : doc) {
|
||||||
if(car["make"] == "Toyota") { count++; }
|
if (car["make"] == "Toyota") { count++; }
|
||||||
}
|
}
|
||||||
std::cout << "We have " << count << " Toyota cars.\n";
|
std::cout << "We have " << count << " Toyota cars.\n";
|
||||||
doc.rewind(); // requires simdjson 1.0 or better
|
doc.rewind(); // requires simdjson 1.0 or better
|
||||||
@@ -1392,18 +1400,18 @@ ondemand::parser parser;
|
|||||||
ondemand::document_stream stream;
|
ondemand::document_stream stream;
|
||||||
size_t counter{0};
|
size_t counter{0};
|
||||||
auto error = parser.iterate_many(json, 50).get(stream);
|
auto error = parser.iterate_many(json, 50).get(stream);
|
||||||
if( error ) { /* handle the error */ }
|
if (error) { /* handle the error */ }
|
||||||
for (auto doc: stream) {
|
for (auto doc: stream) {
|
||||||
if(counter < 6) {
|
if (counter < 6) {
|
||||||
int64_t val;
|
int64_t val;
|
||||||
error = doc.at_pointer("/4").get(val);
|
error = doc.at_pointer("/4").get(val);
|
||||||
if( error ) { /* handle the error */ }
|
if (error) { /* handle the error */ }
|
||||||
std::cout << "5 = " << val << std::endl;
|
std::cout << "5 = " << val << std::endl;
|
||||||
} else {
|
} else {
|
||||||
ondemand::value val;
|
ondemand::value val;
|
||||||
error = doc.at_pointer("/4").get(val);
|
error = doc.at_pointer("/4").get(val);
|
||||||
// error == simdjson::CAPACITY
|
// error == simdjson::CAPACITY
|
||||||
if(error) {
|
if (error) {
|
||||||
std::cerr << error << std::endl;
|
std::cerr << error << std::endl;
|
||||||
// We left 293 bytes unprocessed at the tail end of the input.
|
// We left 293 bytes unprocessed at the tail end of the input.
|
||||||
std::cout << " unprocessed bytes at the end: " << stream.truncated_bytes() << std::endl;
|
std::cout << " unprocessed bytes at the end: " << stream.truncated_bytes() << std::endl;
|
||||||
@@ -1647,7 +1655,7 @@ JSON string to a user-provided buffer:
|
|||||||
|
|
||||||
General Direct Access to the Raw JSON String
|
General Direct Access to the Raw JSON String
|
||||||
--------------------------------
|
--------------------------------
|
||||||
If your value is a string, the `raw_json_string` gives you direct access to the unprocess
|
If your value is a string, the `raw_json_string` you with `get_raw_json_string()` gives you direct access to the unprocessed
|
||||||
string. The simdjson library allows you to have access to the raw underlying JSON
|
string. The simdjson library allows you to have access to the raw underlying JSON
|
||||||
more generally.
|
more generally.
|
||||||
|
|
||||||
@@ -1682,9 +1690,9 @@ string_view token = obj["value"].raw_json_token();
|
|||||||
|
|
||||||
The `raw_json_token()` should be fast and free of allocation.
|
The `raw_json_token()` should be fast and free of allocation.
|
||||||
|
|
||||||
If you value is an array or an object, `raw_json_token()` returns effectively a single
|
If your value is an array or an object, `raw_json_token()` returns effectively a single
|
||||||
character (`[`) or (`}`) which is not very useful. For arrays and objects, we have another
|
character (`[`) or (`}`) which is not very useful. For arrays and objects, we have another
|
||||||
method called `raw_json()` which consumes (traverse) the array or the object.
|
method called `raw_json()` which consumes (traverses) the array or the object.
|
||||||
|
|
||||||
```C++
|
```C++
|
||||||
simdjson::ondemand::parser parser;
|
simdjson::ondemand::parser parser;
|
||||||
@@ -1716,6 +1724,82 @@ obj.reset(); // revise the object
|
|||||||
uint64_t x = obj["value"]; // gives me 123
|
uint64_t x = obj["value"]; // gives me 123
|
||||||
```
|
```
|
||||||
|
|
||||||
|
You can use `raw_json()` with the values inside an array and object. When
|
||||||
|
calling `raw_json()` on an untyped value, it acts as `raw_json()` when the
|
||||||
|
value is an array or an object. Otherwise, it acts as `raw_json_token()`.
|
||||||
|
It is useful if you do not care for the type of the value and just wants a
|
||||||
|
string representation.
|
||||||
|
|
||||||
|
```C++
|
||||||
|
auto json = R"( [1,2,"fds", {"a":1}, [1,344]] )"_padded;
|
||||||
|
ondemand::parser parser;
|
||||||
|
ondemand::document doc = parser.iterate(json);
|
||||||
|
size_t counter = 0;
|
||||||
|
for(auto array: doc) {
|
||||||
|
std::string_view raw = array.raw_json();
|
||||||
|
// will capture "1", "2", "\"fds\"", "{\"a\":1}", "[1,344]"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```C++
|
||||||
|
auto json = R"( {"key1":1,"key2":2,"key3":"fds", "key4":{"a":1}, "key5":[1,344]} )"_padded;
|
||||||
|
ondemand::parser parser;
|
||||||
|
ondemand::document doc = parser.iterate(json);
|
||||||
|
size_t counter = 0;
|
||||||
|
for(auto key_value: doc.get_object()) {
|
||||||
|
std::string_view raw = key_value.value().raw_json();
|
||||||
|
// will capture "1", "2", "\"fds\"", "{\"a\":1}", "[1,344]"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Storing Directly into an Existing String Instance
|
||||||
|
-----------------------------------------------------
|
||||||
|
|
||||||
|
The simdjson library favours the use of `std::string_view` instances because
|
||||||
|
it tends to lead to better performance due to causing fewer memory allocations.
|
||||||
|
However, they are cases where you need to store a string result in an `std::string``
|
||||||
|
instance. You can do so with a templated version of the `to_string()` method which takes as
|
||||||
|
a parameter a reference to an `std::string`.
|
||||||
|
|
||||||
|
```C++
|
||||||
|
auto json = R"({
|
||||||
|
"name": "Daniel",
|
||||||
|
"age": 42
|
||||||
|
})"_padded;
|
||||||
|
ondemand::parser parser;
|
||||||
|
ondemand::document doc = parser.iterate(json);
|
||||||
|
std::string name;
|
||||||
|
doc["name"].get_string(name);
|
||||||
|
```
|
||||||
|
|
||||||
|
The same routine can be written without exceptions handling:
|
||||||
|
|
||||||
|
```C++
|
||||||
|
std::string name;
|
||||||
|
auto err = doc["name"].get_string(name);
|
||||||
|
if(err) { /* handle error */ }
|
||||||
|
```
|
||||||
|
|
||||||
|
The `std::string` instance, once created, is independent. Unlike our `std::string_view` instances,
|
||||||
|
it does not point at data that is within our `parser` instance. The same caveat applies: you should
|
||||||
|
only consume a JSON string once.
|
||||||
|
|
||||||
|
Because `get_string()` is a template that requires a type that can be assigned an `std::string`, you
|
||||||
|
can use it with features such as `std::optional`:
|
||||||
|
|
||||||
|
```C++
|
||||||
|
auto json = R"({ "foo1": "3.1416" } )"_padded;
|
||||||
|
ondemand::parser parser;
|
||||||
|
ondemand::document doc = parser.iterate(json);
|
||||||
|
std::optional<std::string> value;
|
||||||
|
if(doc["foo1"].get_string(value)) { /* error */ }
|
||||||
|
// value was populated with "3.1416"
|
||||||
|
```
|
||||||
|
|
||||||
|
You should be mindful of the trade-off: allocating multiple
|
||||||
|
`std::string` instances can become expensive.
|
||||||
|
|
||||||
Thread Safety
|
Thread Safety
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
@@ -1944,6 +2028,79 @@ bool example() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
* Example 3: CRT
|
||||||
|
|
||||||
|
```C++
|
||||||
|
|
||||||
|
bool example() {
|
||||||
|
padded_string padded_input_json = R"([
|
||||||
|
{ "monitor": [
|
||||||
|
{ "id": "monitor", "type": "toggle", "label": "monitor" },
|
||||||
|
{ "id": "profile", "type": "selector", "label": "collection" },
|
||||||
|
{ "id": "overlay", "type": "selector", "label": "overlay" },
|
||||||
|
{ "id": "zoom", "type": "toggleSlider", "label": "zoom" }
|
||||||
|
] },
|
||||||
|
|
||||||
|
{ "crt": [
|
||||||
|
{ "id": "system", "type": "multi", "label": "system", "choices": "PAL, NTSC" },
|
||||||
|
{ "type": "spacer" },
|
||||||
|
{ "id": "brightness", "type": "slider", "icon": "brightness" },
|
||||||
|
{ "id": "contrast", "type": "slider", "icon": "contrast" },
|
||||||
|
{ "id": "saturation", "type": "slider", "icon": "saturation" },
|
||||||
|
{ "type": "spacer" },
|
||||||
|
{ "id": "overscan", "type": "toggleSlider", "label": "overscan" },
|
||||||
|
{ "type": "spacer" },
|
||||||
|
{ "id": "emulation", "type": "toggle", "label": "CRT emulation" },
|
||||||
|
{ "type": "spacer" },
|
||||||
|
{ "id": "curve", "type": "toggleSlider", "label": "curve" },
|
||||||
|
{ "id": "bleed", "type": "toggleSlider", "label": "bleed" },
|
||||||
|
{ "id": "vignette", "type": "toggleSlider", "label": "vignette" },
|
||||||
|
{ "id": "scanlines", "type": "toggleSlider", "label": "scanlines" },
|
||||||
|
{ "id": "gridlines", "type": "toggleSlider", "label": "gridlines" },
|
||||||
|
{ "id": "glow", "type": "toggleSlider", "label": "glow" },
|
||||||
|
{ "id": "flicker", "type": "toggleSlider", "label": "flicker" },
|
||||||
|
{ "id": "noise", "type": "toggleSlider", "label": "noise" },
|
||||||
|
{}
|
||||||
|
] }
|
||||||
|
])"_padded;
|
||||||
|
auto parser = ondemand::parser{};
|
||||||
|
auto doc = parser.iterate(padded_input_json);
|
||||||
|
auto root_array = doc.get_array();
|
||||||
|
// the root should be an object, not an array, but that's the JSON we are
|
||||||
|
// given.
|
||||||
|
for (ondemand::object node : root_array) {
|
||||||
|
// We know that we are going to have just one element in the object.
|
||||||
|
for (auto field : node) {
|
||||||
|
std::cout << "\n\ntop level:" << field.key() << std::endl;
|
||||||
|
// You can get a proper std::string_view for the key with:
|
||||||
|
// std::string_view key = field.unescaped_key();
|
||||||
|
// and second for-range loop to get child-elements here
|
||||||
|
for (ondemand::object inner_object : field.value()) {
|
||||||
|
auto i = inner_object.begin();
|
||||||
|
if (i == inner_object.end()) {
|
||||||
|
std::cout << "empty object" << std::endl;
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
for (; i != inner_object.end(); ++i) {
|
||||||
|
auto inner_field = *i;
|
||||||
|
std::cout << '"' << inner_field.key()
|
||||||
|
<< "\" : " << inner_field.value() << ", ";
|
||||||
|
// You can get proper std::string_view for the key and value with:
|
||||||
|
// std::string_view inner_key = field.unescaped_key();
|
||||||
|
// std::string_view value_str = field.value();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::cout << std::endl;
|
||||||
|
}
|
||||||
|
// You can break here if you only want just the first element.
|
||||||
|
// break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Performance Tips
|
Performance Tips
|
||||||
--------
|
--------
|
||||||
@@ -1969,4 +2126,4 @@ Performance Tips
|
|||||||
std::string_view year = data["year"];
|
std::string_view year = data["year"];
|
||||||
std::string_view rating = data["rating"];
|
std::string_view rating = data["rating"];
|
||||||
```
|
```
|
||||||
- To better understand the operation of your On Demand parser, and whether it is performing as well as you think it should be, there is a logger feature built in to simdjson! To use it, define the pre-processor directive `SIMDJSON_VERBOSE_LOGGING` prior to including the `simdjson.h` header, which enables logging in simdjson. Run your code. It may generate a lot of logging output; adding printouts from your application that show each section may be helpful. The log's output will show step-by-step information on state, buffer pointer position, depth, and key retrieval status. Importantly, unless `SIMDJSON_VERBOSE_LOGGING` is defined, logging is entirely disabled and thus carries no overhead.
|
- To better understand the operation of your On Demand parser, and whether it is performing as well as you think it should be, there is a logger feature built in to simdjson! To use it, define the pre-processor directive `SIMDJSON_VERBOSE_LOGGING` prior to including the `simdjson.h` header, which enables logging in simdjson. Run your code. It may generate a lot of logging output; adding printouts from your application that show each section may be helpful. The log's output will show step-by-step information on state, buffer pointer position, depth, and key retrieval status. Importantly, unless `SIMDJSON_VERBOSE_LOGGING` is defined, logging is entirely disabled and thus carries no overhead.
|
||||||
|
|||||||
+3
-3
@@ -105,7 +105,7 @@ Once you have an element, you can navigate it with idiomatic C++ iterators, oper
|
|||||||
with the `size()` method.
|
with the `size()` method.
|
||||||
* **Checking an Element Type:** You can check an element's type with `element.type()`. It
|
* **Checking an Element Type:** You can check an element's type with `element.type()`. It
|
||||||
returns an `element_type` with values such as `simdjson::dom::element_type::ARRAY`, `simdjson::dom::element_type::OBJECT`, `simdjson::dom::element_type::INT64`, `simdjson::dom::element_type::UINT64`,`simdjson::dom::element_type::DOUBLE`, `simdjson::dom::element_type::STRING`, `simdjson::dom::element_type::BOOL` or, `simdjson::dom::element_type::NULL_VALUE`.
|
returns an `element_type` with values such as `simdjson::dom::element_type::ARRAY`, `simdjson::dom::element_type::OBJECT`, `simdjson::dom::element_type::INT64`, `simdjson::dom::element_type::UINT64`,`simdjson::dom::element_type::DOUBLE`, `simdjson::dom::element_type::STRING`, `simdjson::dom::element_type::BOOL` or, `simdjson::dom::element_type::NULL_VALUE`.
|
||||||
* **Output to streams and strings:** Given a document or an element (or node) out of a JSON document, you can output a minified string version using the C++ stream idiom (`out << element`). You can also request the construction of a minified string version (`simdjson::minify(element)`). Numbers are serialized as 64-bit floating-point numbers (`double`).
|
* **Output to streams and strings:** Given a document or an element (or node) out of a JSON document, you can output a minified string version using the C++ stream idiom (`out << element`). You can also request the construction of a minified string version (`simdjson::minify(element)`) or a prettified string version (`simdjson::prettify(element)`). Numbers are serialized as 64-bit floating-point numbers (`double`).
|
||||||
|
|
||||||
### Examples
|
### Examples
|
||||||
|
|
||||||
@@ -329,10 +329,10 @@ int main(void) {
|
|||||||
simdjson::dom::parser parser;
|
simdjson::dom::parser parser;
|
||||||
simdjson::dom::element tweets; // invalid until the get() succeeds
|
simdjson::dom::element tweets; // invalid until the get() succeeds
|
||||||
auto error = parser.load("twitter.json").get(tweets);
|
auto error = parser.load("twitter.json").get(tweets);
|
||||||
if(error) { std::cerr << error << std::endl; return EXIT_FAILURE; }
|
if (error) { std::cerr << error << std::endl; return EXIT_FAILURE; }
|
||||||
uint64_t identifier;
|
uint64_t identifier;
|
||||||
error = tweets["statuses"].at(0)["id"].get(identifier);
|
error = tweets["statuses"].at(0)["id"].get(identifier);
|
||||||
if(error) { std::cerr << error << std::endl; return EXIT_FAILURE; }
|
if (error) { std::cerr << error << std::endl; return EXIT_FAILURE; }
|
||||||
std::cout << identifier << std::endl;
|
std::cout << identifier << std::endl;
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -101,8 +101,8 @@ by comparing it with the null pointer.
|
|||||||
|
|
||||||
```c++
|
```c++
|
||||||
auto my_implementation = simdjson::get_available_implementations()["haswell"];
|
auto my_implementation = simdjson::get_available_implementations()["haswell"];
|
||||||
if(! my_implementation) { exit(1); }
|
if (! my_implementation) { exit(1); }
|
||||||
if(! my_implementation->supported_by_runtime_system()) { exit(1); }
|
if (! my_implementation->supported_by_runtime_system()) { exit(1); }
|
||||||
simdjson::get_active_implementation() = my_implementation;
|
simdjson::get_active_implementation() = my_implementation;
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -113,7 +113,7 @@ You should call `supported_by_runtime_system()` to compare the processor's featu
|
|||||||
|
|
||||||
```c++
|
```c++
|
||||||
for (auto implementation : simdjson::get_available_implementations()) {
|
for (auto implementation : simdjson::get_available_implementations()) {
|
||||||
if(implementation->supported_by_runtime_system()) {
|
if (implementation->supported_by_runtime_system()) {
|
||||||
cout << implementation->name() << ": " << implementation->description() << endl;
|
cout << implementation->name() << ": " << implementation->description() << endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-4
@@ -17,6 +17,9 @@ Contents
|
|||||||
|
|
||||||
- [Motivations](#motivations)
|
- [Motivations](#motivations)
|
||||||
- [How it works](#how-it-works)
|
- [How it works](#how-it-works)
|
||||||
|
- [Context](#context)
|
||||||
|
- [Design](#design)
|
||||||
|
- [Threads](#threads)
|
||||||
- [Support](#support)
|
- [Support](#support)
|
||||||
- [API](#api)
|
- [API](#api)
|
||||||
- [Use cases](#use-cases)
|
- [Use cases](#use-cases)
|
||||||
@@ -193,12 +196,12 @@ Let us illustrate the idea with code:
|
|||||||
simdjson::ondemand::parser parser;
|
simdjson::ondemand::parser parser;
|
||||||
simdjson::ondemand::document_stream stream;
|
simdjson::ondemand::document_stream stream;
|
||||||
auto error = parser.iterate_many(json).get(stream);
|
auto error = parser.iterate_many(json).get(stream);
|
||||||
if( error ) { /* do something */ }
|
if (error) { /* do something */ }
|
||||||
auto i = stream.begin();
|
auto i = stream.begin();
|
||||||
size_t count{0};
|
size_t count{0};
|
||||||
for(; i != stream.end(); ++i) {
|
for(; i != stream.end(); ++i) {
|
||||||
auto doc = *i;
|
auto doc = *i;
|
||||||
if(!i.error()) {
|
if (!i.error()) {
|
||||||
std::cout << "got full document at " << i.current_index() << std::endl;
|
std::cout << "got full document at " << i.current_index() << std::endl;
|
||||||
std::cout << i.source() << std::endl;
|
std::cout << i.source() << std::endl;
|
||||||
count++;
|
count++;
|
||||||
@@ -234,7 +237,7 @@ Consider the following example where a truncated document (`{"key":"intentionall
|
|||||||
simdjson::ondemand::parser parser;
|
simdjson::ondemand::parser parser;
|
||||||
simdjson::ondemand::document_stream stream;
|
simdjson::ondemand::document_stream stream;
|
||||||
auto error = parser.iterate_many(json,json.size()).get(stream);
|
auto error = parser.iterate_many(json,json.size()).get(stream);
|
||||||
if(error) { std::cerr << error << std::endl; return; }
|
if (error) { std::cerr << error << std::endl; return; }
|
||||||
for(auto i = stream.begin(); i != stream.end(); ++i) {
|
for(auto i = stream.begin(); i != stream.end(); ++i) {
|
||||||
std::cout << i.source() << std::endl;
|
std::cout << i.source() << std::endl;
|
||||||
}
|
}
|
||||||
@@ -266,7 +269,7 @@ Example:
|
|||||||
// we pass 'true' to the allow_comma parameter, the batch size will be set to at least
|
// we pass 'true' to the allow_comma parameter, the batch size will be set to at least
|
||||||
// the document size.
|
// the document size.
|
||||||
auto error = parser.iterate_many(json, 32, true).get(doc_stream);
|
auto error = parser.iterate_many(json, 32, true).get(doc_stream);
|
||||||
if(error) { std::cerr << error << std::endl; return; }
|
if (error) { std::cerr << error << std::endl; return; }
|
||||||
for (auto doc : doc_stream) {
|
for (auto doc : doc_stream) {
|
||||||
std::cout << doc.type() << std::endl;
|
std::cout << doc.type() << std::endl;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -679,11 +679,11 @@ in production systems:
|
|||||||
ondemand::object c1 = parent["child1"];
|
ondemand::object c1 = parent["child1"];
|
||||||
// c1 owns the focus
|
// c1 owns the focus
|
||||||
//
|
//
|
||||||
if(std::string_view(c1["name"]) != "John") { ... }
|
if (std::string_view(c1["name"]) != "John") { ... }
|
||||||
// c2 attempts to grab the focus from parent but fails
|
// c2 attempts to grab the focus from parent but fails
|
||||||
ondemand::object c2 = parent["child2"];
|
ondemand::object c2 = parent["child2"];
|
||||||
// c2 is now in an unsafe state and the following line would be unsafe
|
// c2 is now in an unsafe state and the following line would be unsafe
|
||||||
// if(std::string_view(c2["name"]) != "Daniel") { return false; }
|
// if (std::string_view(c2["name"]) != "Daniel") { return false; }
|
||||||
```
|
```
|
||||||
|
|
||||||
A correct usage is given by the following example:
|
A correct usage is given by the following example:
|
||||||
@@ -697,7 +697,7 @@ in production systems:
|
|||||||
{
|
{
|
||||||
ondemand::object c1 = parent["child1"];
|
ondemand::object c1 = parent["child1"];
|
||||||
// c1 grabbed the focus from parent
|
// c1 grabbed the focus from parent
|
||||||
if(std::string_view(c1["name"]) != "John") { return false; }
|
if (std::string_view(c1["name"]) != "John") { return false; }
|
||||||
}
|
}
|
||||||
// c1 went out of scope, so its destructor was called and the focus
|
// c1 went out of scope, so its destructor was called and the focus
|
||||||
// was handed back to parent.
|
// was handed back to parent.
|
||||||
@@ -705,7 +705,7 @@ in production systems:
|
|||||||
ondemand::object c2 = parent["child2"];
|
ondemand::object c2 = parent["child2"];
|
||||||
// c2 grabbed the focus from parent
|
// c2 grabbed the focus from parent
|
||||||
// the following is safe:
|
// the following is safe:
|
||||||
if(std::string_view(c2["name"]) != "Daniel") { return false; }
|
if (std::string_view(c2["name"]) != "Daniel") { return false; }
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -184,12 +184,12 @@ Let us illustrate the idea with code:
|
|||||||
simdjson::dom::parser parser;
|
simdjson::dom::parser parser;
|
||||||
simdjson::dom::document_stream stream;
|
simdjson::dom::document_stream stream;
|
||||||
auto error = parser.parse_many(json).get(stream);
|
auto error = parser.parse_many(json).get(stream);
|
||||||
if( error ) { /* do something */ }
|
if (error) { /* do something */ }
|
||||||
auto i = stream.begin();
|
auto i = stream.begin();
|
||||||
size_t count{0};
|
size_t count{0};
|
||||||
for(; i != stream.end(); ++i) {
|
for(; i != stream.end(); ++i) {
|
||||||
auto doc = *i;
|
auto doc = *i;
|
||||||
if(!doc.error()) {
|
if (!doc.error()) {
|
||||||
std::cout << "got full document at " << i.current_index() << std::endl;
|
std::cout << "got full document at " << i.current_index() << std::endl;
|
||||||
std::cout << i.source() << std::endl;
|
std::cout << i.source() << std::endl;
|
||||||
count++;
|
count++;
|
||||||
@@ -225,7 +225,7 @@ Consider the following example where a truncated document (`{"key":"intentionall
|
|||||||
simdjson::dom::parser parser;
|
simdjson::dom::parser parser;
|
||||||
simdjson::dom::document_stream stream;
|
simdjson::dom::document_stream stream;
|
||||||
auto error = parser.parse_many(json,json.size()).get(stream);
|
auto error = parser.parse_many(json,json.size()).get(stream);
|
||||||
if(error) { std::cerr << error << std::endl; return; }
|
if (error) { std::cerr << error << std::endl; return; }
|
||||||
for(auto doc : stream) {
|
for(auto doc : stream) {
|
||||||
std::cout << doc << std::endl;
|
std::cout << doc << std::endl;
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-1
@@ -34,8 +34,24 @@
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "simdjson/common_defs.h"
|
||||||
|
|
||||||
|
// This provides the public API for simdjson.
|
||||||
|
// DOM and ondemand are amalgamated separately, in simdjson.h
|
||||||
#include "simdjson/simdjson_version.h"
|
#include "simdjson/simdjson_version.h"
|
||||||
|
|
||||||
|
#include "simdjson/base.h"
|
||||||
|
|
||||||
|
#include "simdjson/error.h"
|
||||||
|
#include "simdjson/error-inl.h"
|
||||||
|
#include "simdjson/implementation.h"
|
||||||
|
#include "simdjson/minify.h"
|
||||||
|
#include "simdjson/padded_string.h"
|
||||||
|
#include "simdjson/padded_string-inl.h"
|
||||||
|
#include "simdjson/padded_string_view.h"
|
||||||
|
#include "simdjson/padded_string_view-inl.h"
|
||||||
|
|
||||||
#include "simdjson/dom.h"
|
#include "simdjson/dom.h"
|
||||||
#include "simdjson/builtin.h"
|
#include "simdjson/ondemand.h"
|
||||||
|
|
||||||
#endif // SIMDJSON_H
|
#endif // SIMDJSON_H
|
||||||
|
|||||||
@@ -1,34 +1,8 @@
|
|||||||
#ifndef SIMDJSON_ARM64_H
|
#ifndef SIMDJSON_ARM64_H
|
||||||
#define SIMDJSON_ARM64_H
|
#define SIMDJSON_ARM64_H
|
||||||
|
|
||||||
#include "simdjson/implementation-base.h"
|
|
||||||
|
|
||||||
#if SIMDJSON_IMPLEMENTATION_ARM64
|
|
||||||
|
|
||||||
namespace simdjson {
|
|
||||||
/**
|
|
||||||
* Implementation for NEON (ARMv8).
|
|
||||||
*/
|
|
||||||
namespace arm64 {
|
|
||||||
} // namespace arm64
|
|
||||||
} // namespace simdjson
|
|
||||||
|
|
||||||
#include "simdjson/arm64/implementation.h"
|
|
||||||
|
|
||||||
#include "simdjson/arm64/begin.h"
|
#include "simdjson/arm64/begin.h"
|
||||||
|
#include "simdjson/generic/amalgamated.h"
|
||||||
// Declarations
|
|
||||||
#include "simdjson/generic/dom_parser_implementation.h"
|
|
||||||
#include "simdjson/arm64/intrinsics.h"
|
|
||||||
#include "simdjson/arm64/bitmanipulation.h"
|
|
||||||
#include "simdjson/arm64/bitmask.h"
|
|
||||||
#include "simdjson/arm64/simd.h"
|
|
||||||
#include "simdjson/generic/jsoncharutils.h"
|
|
||||||
#include "simdjson/generic/atomparsing.h"
|
|
||||||
#include "simdjson/arm64/stringparsing.h"
|
|
||||||
#include "simdjson/arm64/numberparsing.h"
|
|
||||||
#include "simdjson/arm64/end.h"
|
#include "simdjson/arm64/end.h"
|
||||||
|
|
||||||
#endif // SIMDJSON_IMPLEMENTATION_ARM64
|
#endif // SIMDJSON_ARM64_H
|
||||||
|
|
||||||
#endif // SIMDJSON_ARM64_H
|
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
#ifndef SIMDJSON_ARM64_BASE_H
|
||||||
|
#define SIMDJSON_ARM64_BASE_H
|
||||||
|
|
||||||
|
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
#include "simdjson/base.h"
|
||||||
|
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
|
||||||
|
namespace simdjson {
|
||||||
|
/**
|
||||||
|
* Implementation for NEON (ARMv8).
|
||||||
|
*/
|
||||||
|
namespace arm64 {
|
||||||
|
|
||||||
|
class implementation;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
namespace simd {
|
||||||
|
template <typename T> struct simd8;
|
||||||
|
template <typename T> struct simd8x64;
|
||||||
|
} // namespace simd
|
||||||
|
} // unnamed namespace
|
||||||
|
|
||||||
|
} // namespace arm64
|
||||||
|
} // namespace simdjson
|
||||||
|
|
||||||
|
#endif // SIMDJSON_ARM64_BASE_H
|
||||||
@@ -1 +1,10 @@
|
|||||||
#define SIMDJSON_IMPLEMENTATION arm64
|
#define SIMDJSON_IMPLEMENTATION arm64
|
||||||
|
#include "simdjson/arm64/base.h"
|
||||||
|
#include "simdjson/arm64/intrinsics.h"
|
||||||
|
#include "simdjson/arm64/bitmanipulation.h"
|
||||||
|
#include "simdjson/arm64/bitmask.h"
|
||||||
|
#include "simdjson/arm64/numberparsing_defs.h"
|
||||||
|
#include "simdjson/arm64/simd.h"
|
||||||
|
#include "simdjson/arm64/stringparsing_defs.h"
|
||||||
|
|
||||||
|
#define SIMDJSON_SKIP_BACKSLASH_SHORT_CIRCUIT 1
|
||||||
@@ -1,8 +1,13 @@
|
|||||||
#ifndef SIMDJSON_ARM64_BITMANIPULATION_H
|
#ifndef SIMDJSON_ARM64_BITMANIPULATION_H
|
||||||
#define SIMDJSON_ARM64_BITMANIPULATION_H
|
#define SIMDJSON_ARM64_BITMANIPULATION_H
|
||||||
|
|
||||||
|
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
#include "simdjson/arm64/base.h"
|
||||||
|
#include "simdjson/arm64/intrinsics.h"
|
||||||
|
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
|
||||||
namespace simdjson {
|
namespace simdjson {
|
||||||
namespace SIMDJSON_IMPLEMENTATION {
|
namespace arm64 {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
// We sometimes call trailing_zero on inputs that are zero,
|
// We sometimes call trailing_zero on inputs that are zero,
|
||||||
@@ -95,7 +100,7 @@ simdjson_inline bool add_overflow(uint64_t value1, uint64_t value2, uint64_t *re
|
|||||||
}
|
}
|
||||||
|
|
||||||
} // unnamed namespace
|
} // unnamed namespace
|
||||||
} // namespace SIMDJSON_IMPLEMENTATION
|
} // namespace arm64
|
||||||
} // namespace simdjson
|
} // namespace simdjson
|
||||||
|
|
||||||
#endif // SIMDJSON_ARM64_BITMANIPULATION_H
|
#endif // SIMDJSON_ARM64_BITMANIPULATION_H
|
||||||
|
|||||||
@@ -1,8 +1,12 @@
|
|||||||
#ifndef SIMDJSON_ARM64_BITMASK_H
|
#ifndef SIMDJSON_ARM64_BITMASK_H
|
||||||
#define SIMDJSON_ARM64_BITMASK_H
|
#define SIMDJSON_ARM64_BITMASK_H
|
||||||
|
|
||||||
|
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
#include "simdjson/arm64/base.h"
|
||||||
|
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
|
||||||
namespace simdjson {
|
namespace simdjson {
|
||||||
namespace SIMDJSON_IMPLEMENTATION {
|
namespace arm64 {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1 +1,6 @@
|
|||||||
|
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
#include "simdjson/arm64/base.h"
|
||||||
|
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
|
||||||
|
#undef SIMDJSON_SKIP_BACKSLASH_SHORT_CIRCUIT
|
||||||
#undef SIMDJSON_IMPLEMENTATION
|
#undef SIMDJSON_IMPLEMENTATION
|
||||||
|
|||||||
@@ -1,17 +1,15 @@
|
|||||||
#ifndef SIMDJSON_ARM64_IMPLEMENTATION_H
|
#ifndef SIMDJSON_ARM64_IMPLEMENTATION_H
|
||||||
#define SIMDJSON_ARM64_IMPLEMENTATION_H
|
#define SIMDJSON_ARM64_IMPLEMENTATION_H
|
||||||
|
|
||||||
|
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
#include "simdjson/base.h"
|
#include "simdjson/base.h"
|
||||||
#include "simdjson/internal/isadetection.h"
|
#include "simdjson/implementation.h"
|
||||||
|
#include "simdjson/internal/instruction_set.h"
|
||||||
|
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
|
||||||
namespace simdjson {
|
namespace simdjson {
|
||||||
namespace arm64 {
|
namespace arm64 {
|
||||||
|
|
||||||
namespace {
|
|
||||||
using namespace simdjson;
|
|
||||||
using namespace simdjson::dom;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
#ifndef SIMDJSON_ARM64_INTRINSICS_H
|
#ifndef SIMDJSON_ARM64_INTRINSICS_H
|
||||||
#define SIMDJSON_ARM64_INTRINSICS_H
|
#define SIMDJSON_ARM64_INTRINSICS_H
|
||||||
|
|
||||||
|
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
#include "simdjson/arm64/base.h"
|
||||||
|
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
|
||||||
// This should be the correct header whether
|
// This should be the correct header whether
|
||||||
// you use visual studio or other compilers.
|
// you use visual studio or other compilers.
|
||||||
#include <arm_neon.h>
|
#include <arm_neon.h>
|
||||||
|
|||||||
@@ -1,27 +0,0 @@
|
|||||||
#ifndef SIMDJSON_ARM64_NUMBERPARSING_H
|
|
||||||
#define SIMDJSON_ARM64_NUMBERPARSING_H
|
|
||||||
|
|
||||||
namespace simdjson {
|
|
||||||
namespace SIMDJSON_IMPLEMENTATION {
|
|
||||||
namespace numberparsing {
|
|
||||||
|
|
||||||
// we don't have SSE, so let us use a scalar function
|
|
||||||
// credit: https://johnnylee-sde.github.io/Fast-numeric-string-to-int/
|
|
||||||
/** @private */
|
|
||||||
static simdjson_inline uint32_t parse_eight_digits_unrolled(const uint8_t *chars) {
|
|
||||||
uint64_t val;
|
|
||||||
std::memcpy(&val, chars, sizeof(uint64_t));
|
|
||||||
val = (val & 0x0F0F0F0F0F0F0F0F) * 2561 >> 8;
|
|
||||||
val = (val & 0x00FF00FF00FF00FF) * 6553601 >> 16;
|
|
||||||
return uint32_t((val & 0x0000FFFF0000FFFF) * 42949672960001 >> 32);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace numberparsing
|
|
||||||
} // namespace SIMDJSON_IMPLEMENTATION
|
|
||||||
} // namespace simdjson
|
|
||||||
|
|
||||||
#define SIMDJSON_SWAR_NUMBER_PARSING 1
|
|
||||||
|
|
||||||
#include "simdjson/generic/numberparsing.h"
|
|
||||||
|
|
||||||
#endif // SIMDJSON_ARM64_NUMBERPARSING_H
|
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
#ifndef SIMDJSON_ARM64_NUMBERPARSING_DEFS_H
|
||||||
|
#define SIMDJSON_ARM64_NUMBERPARSING_DEFS_H
|
||||||
|
|
||||||
|
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
#include "simdjson/arm64/base.h"
|
||||||
|
#include "simdjson/arm64/intrinsics.h"
|
||||||
|
#include "simdjson/internal/numberparsing_tables.h"
|
||||||
|
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
#if _M_ARM64
|
||||||
|
// __umulh requires intrin.h
|
||||||
|
#include <intrin.h>
|
||||||
|
#endif // _M_ARM64
|
||||||
|
|
||||||
|
namespace simdjson {
|
||||||
|
namespace arm64 {
|
||||||
|
namespace numberparsing {
|
||||||
|
|
||||||
|
// we don't have SSE, so let us use a scalar function
|
||||||
|
// credit: https://johnnylee-sde.github.io/Fast-numeric-string-to-int/
|
||||||
|
/** @private */
|
||||||
|
static simdjson_inline uint32_t parse_eight_digits_unrolled(const uint8_t *chars) {
|
||||||
|
uint64_t val;
|
||||||
|
std::memcpy(&val, chars, sizeof(uint64_t));
|
||||||
|
val = (val & 0x0F0F0F0F0F0F0F0F) * 2561 >> 8;
|
||||||
|
val = (val & 0x00FF00FF00FF00FF) * 6553601 >> 16;
|
||||||
|
return uint32_t((val & 0x0000FFFF0000FFFF) * 42949672960001 >> 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
simdjson_inline internal::value128 full_multiplication(uint64_t value1, uint64_t value2) {
|
||||||
|
internal::value128 answer;
|
||||||
|
#if SIMDJSON_REGULAR_VISUAL_STUDIO || SIMDJSON_IS_32BITS
|
||||||
|
#ifdef _M_ARM64
|
||||||
|
// ARM64 has native support for 64-bit multiplications, no need to emultate
|
||||||
|
answer.high = __umulh(value1, value2);
|
||||||
|
answer.low = value1 * value2;
|
||||||
|
#else
|
||||||
|
answer.low = _umul128(value1, value2, &answer.high); // _umul128 not available on ARM64
|
||||||
|
#endif // _M_ARM64
|
||||||
|
#else // SIMDJSON_REGULAR_VISUAL_STUDIO || SIMDJSON_IS_32BITS
|
||||||
|
__uint128_t r = (static_cast<__uint128_t>(value1)) * value2;
|
||||||
|
answer.low = uint64_t(r);
|
||||||
|
answer.high = uint64_t(r >> 64);
|
||||||
|
#endif
|
||||||
|
return answer;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace numberparsing
|
||||||
|
} // namespace arm64
|
||||||
|
} // namespace simdjson
|
||||||
|
|
||||||
|
#define SIMDJSON_SWAR_NUMBER_PARSING 1
|
||||||
|
|
||||||
|
#endif // SIMDJSON_ARM64_NUMBERPARSING_DEFS_H
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
#ifndef SIMDJSON_ARM64_ONDEMAND_H
|
||||||
|
#define SIMDJSON_ARM64_ONDEMAND_H
|
||||||
|
|
||||||
|
#include "simdjson/arm64/begin.h"
|
||||||
|
#include "simdjson/generic/ondemand/amalgamated.h"
|
||||||
|
#include "simdjson/arm64/end.h"
|
||||||
|
|
||||||
|
#endif // SIMDJSON_ARM64_ONDEMAND_H
|
||||||
@@ -1,14 +1,14 @@
|
|||||||
#ifndef SIMDJSON_ARM64_SIMD_H
|
#ifndef SIMDJSON_ARM64_SIMD_H
|
||||||
#define SIMDJSON_ARM64_SIMD_H
|
#define SIMDJSON_ARM64_SIMD_H
|
||||||
|
|
||||||
#include "simdjson/base.h"
|
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
#include "simdjson/internal/simdprune_tables.h"
|
#include "simdjson/arm64/base.h"
|
||||||
#include "simdjson/arm64/bitmanipulation.h"
|
#include "simdjson/arm64/bitmanipulation.h"
|
||||||
#include <type_traits>
|
#include "simdjson/internal/simdprune_tables.h"
|
||||||
|
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
|
||||||
namespace simdjson {
|
namespace simdjson {
|
||||||
namespace SIMDJSON_IMPLEMENTATION {
|
namespace arm64 {
|
||||||
namespace {
|
namespace {
|
||||||
namespace simd {
|
namespace simd {
|
||||||
|
|
||||||
@@ -17,89 +17,53 @@ namespace {
|
|||||||
// Start of private section with Visual Studio workaround
|
// Start of private section with Visual Studio workaround
|
||||||
|
|
||||||
|
|
||||||
/**
|
#ifndef simdjson_make_uint8x16_t
|
||||||
* make_uint8x16_t initializes a SIMD register (uint8x16_t).
|
#define simdjson_make_uint8x16_t(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, \
|
||||||
* This is needed because, incredibly, the syntax uint8x16_t x = {1,2,3...}
|
x13, x14, x15, x16) \
|
||||||
* is not recognized under Visual Studio! This is a workaround.
|
([=]() { \
|
||||||
* Using a std::initializer_list<uint8_t> as a parameter resulted in
|
uint8_t array[16] = {x1, x2, x3, x4, x5, x6, x7, x8, \
|
||||||
* inefficient code. With the current approach, if the parameters are
|
x9, x10, x11, x12, x13, x14, x15, x16}; \
|
||||||
* compile-time constants,
|
return vld1q_u8(array); \
|
||||||
* GNU GCC compiles it to ldr, the same as uint8x16_t x = {1,2,3...}.
|
}())
|
||||||
* You should not use this function except for compile-time constants:
|
#endif
|
||||||
* it is not efficient.
|
#ifndef simdjson_make_int8x16_t
|
||||||
*/
|
#define simdjson_make_int8x16_t(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, \
|
||||||
simdjson_inline uint8x16_t make_uint8x16_t(uint8_t x1, uint8_t x2, uint8_t x3, uint8_t x4,
|
x13, x14, x15, x16) \
|
||||||
uint8_t x5, uint8_t x6, uint8_t x7, uint8_t x8,
|
([=]() { \
|
||||||
uint8_t x9, uint8_t x10, uint8_t x11, uint8_t x12,
|
int8_t array[16] = {x1, x2, x3, x4, x5, x6, x7, x8, \
|
||||||
uint8_t x13, uint8_t x14, uint8_t x15, uint8_t x16) {
|
x9, x10, x11, x12, x13, x14, x15, x16}; \
|
||||||
// Doing a load like so end ups generating worse code.
|
return vld1q_s8(array); \
|
||||||
// uint8_t array[16] = {x1, x2, x3, x4, x5, x6, x7, x8,
|
}())
|
||||||
// x9, x10,x11,x12,x13,x14,x15,x16};
|
#endif
|
||||||
// return vld1q_u8(array);
|
|
||||||
uint8x16_t x{};
|
|
||||||
// incredibly, Visual Studio does not allow x[0] = x1
|
|
||||||
x = vsetq_lane_u8(x1, x, 0);
|
|
||||||
x = vsetq_lane_u8(x2, x, 1);
|
|
||||||
x = vsetq_lane_u8(x3, x, 2);
|
|
||||||
x = vsetq_lane_u8(x4, x, 3);
|
|
||||||
x = vsetq_lane_u8(x5, x, 4);
|
|
||||||
x = vsetq_lane_u8(x6, x, 5);
|
|
||||||
x = vsetq_lane_u8(x7, x, 6);
|
|
||||||
x = vsetq_lane_u8(x8, x, 7);
|
|
||||||
x = vsetq_lane_u8(x9, x, 8);
|
|
||||||
x = vsetq_lane_u8(x10, x, 9);
|
|
||||||
x = vsetq_lane_u8(x11, x, 10);
|
|
||||||
x = vsetq_lane_u8(x12, x, 11);
|
|
||||||
x = vsetq_lane_u8(x13, x, 12);
|
|
||||||
x = vsetq_lane_u8(x14, x, 13);
|
|
||||||
x = vsetq_lane_u8(x15, x, 14);
|
|
||||||
x = vsetq_lane_u8(x16, x, 15);
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
simdjson_inline uint8x8_t make_uint8x8_t(uint8_t x1, uint8_t x2, uint8_t x3, uint8_t x4,
|
#ifndef simdjson_make_uint8x8_t
|
||||||
uint8_t x5, uint8_t x6, uint8_t x7, uint8_t x8) {
|
#define simdjson_make_uint8x8_t(x1, x2, x3, x4, x5, x6, x7, x8) \
|
||||||
uint8x8_t x{};
|
([=]() { \
|
||||||
x = vset_lane_u8(x1, x, 0);
|
uint8_t array[8] = {x1, x2, x3, x4, x5, x6, x7, x8}; \
|
||||||
x = vset_lane_u8(x2, x, 1);
|
return vld1_u8(array); \
|
||||||
x = vset_lane_u8(x3, x, 2);
|
}())
|
||||||
x = vset_lane_u8(x4, x, 3);
|
#endif
|
||||||
x = vset_lane_u8(x5, x, 4);
|
#ifndef simdjson_make_int8x8_t
|
||||||
x = vset_lane_u8(x6, x, 5);
|
#define simdjson_make_int8x8_t(x1, x2, x3, x4, x5, x6, x7, x8) \
|
||||||
x = vset_lane_u8(x7, x, 6);
|
([=]() { \
|
||||||
x = vset_lane_u8(x8, x, 7);
|
int8_t array[8] = {x1, x2, x3, x4, x5, x6, x7, x8}; \
|
||||||
return x;
|
return vld1_s8(array); \
|
||||||
}
|
}())
|
||||||
|
#endif
|
||||||
// We have to do the same work for make_int8x16_t
|
#ifndef simdjson_make_uint16x8_t
|
||||||
simdjson_inline int8x16_t make_int8x16_t(int8_t x1, int8_t x2, int8_t x3, int8_t x4,
|
#define simdjson_make_uint16x8_t(x1, x2, x3, x4, x5, x6, x7, x8) \
|
||||||
int8_t x5, int8_t x6, int8_t x7, int8_t x8,
|
([=]() { \
|
||||||
int8_t x9, int8_t x10, int8_t x11, int8_t x12,
|
uint16_t array[8] = {x1, x2, x3, x4, x5, x6, x7, x8}; \
|
||||||
int8_t x13, int8_t x14, int8_t x15, int8_t x16) {
|
return vld1q_u16(array); \
|
||||||
// Doing a load like so end ups generating worse code.
|
}())
|
||||||
// int8_t array[16] = {x1, x2, x3, x4, x5, x6, x7, x8,
|
#endif
|
||||||
// x9, x10,x11,x12,x13,x14,x15,x16};
|
#ifndef simdjson_make_int16x8_t
|
||||||
// return vld1q_s8(array);
|
#define simdjson_make_int16x8_t(x1, x2, x3, x4, x5, x6, x7, x8) \
|
||||||
int8x16_t x{};
|
([=]() { \
|
||||||
// incredibly, Visual Studio does not allow x[0] = x1
|
int16_t array[8] = {x1, x2, x3, x4, x5, x6, x7, x8}; \
|
||||||
x = vsetq_lane_s8(x1, x, 0);
|
return vld1q_s16(array); \
|
||||||
x = vsetq_lane_s8(x2, x, 1);
|
}())
|
||||||
x = vsetq_lane_s8(x3, x, 2);
|
#endif
|
||||||
x = vsetq_lane_s8(x4, x, 3);
|
|
||||||
x = vsetq_lane_s8(x5, x, 4);
|
|
||||||
x = vsetq_lane_s8(x6, x, 5);
|
|
||||||
x = vsetq_lane_s8(x7, x, 6);
|
|
||||||
x = vsetq_lane_s8(x8, x, 7);
|
|
||||||
x = vsetq_lane_s8(x9, x, 8);
|
|
||||||
x = vsetq_lane_s8(x10, x, 9);
|
|
||||||
x = vsetq_lane_s8(x11, x, 10);
|
|
||||||
x = vsetq_lane_s8(x12, x, 11);
|
|
||||||
x = vsetq_lane_s8(x13, x, 12);
|
|
||||||
x = vsetq_lane_s8(x14, x, 13);
|
|
||||||
x = vsetq_lane_s8(x15, x, 14);
|
|
||||||
x = vsetq_lane_s8(x16, x, 15);
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
// End of private section with Visual Studio workaround
|
// End of private section with Visual Studio workaround
|
||||||
} // namespace
|
} // namespace
|
||||||
@@ -158,7 +122,7 @@ simdjson_inline int8x16_t make_int8x16_t(int8_t x1, int8_t x2, int8_t x3, int
|
|||||||
// purposes (cutting it down to uint16_t costs performance in some compilers).
|
// purposes (cutting it down to uint16_t costs performance in some compilers).
|
||||||
simdjson_inline uint32_t to_bitmask() const {
|
simdjson_inline uint32_t to_bitmask() const {
|
||||||
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
|
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||||
const uint8x16_t bit_mask = make_uint8x16_t(0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80,
|
const uint8x16_t bit_mask = simdjson_make_uint8x16_t(0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80,
|
||||||
0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80);
|
0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80);
|
||||||
#else
|
#else
|
||||||
const uint8x16_t bit_mask = {0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80,
|
const uint8x16_t bit_mask = {0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80,
|
||||||
@@ -192,7 +156,7 @@ simdjson_inline int8x16_t make_int8x16_t(int8_t x1, int8_t x2, int8_t x3, int
|
|||||||
simdjson_inline simd8(
|
simdjson_inline simd8(
|
||||||
uint8_t v0, uint8_t v1, uint8_t v2, uint8_t v3, uint8_t v4, uint8_t v5, uint8_t v6, uint8_t v7,
|
uint8_t v0, uint8_t v1, uint8_t v2, uint8_t v3, uint8_t v4, uint8_t v5, uint8_t v6, uint8_t v7,
|
||||||
uint8_t v8, uint8_t v9, uint8_t v10, uint8_t v11, uint8_t v12, uint8_t v13, uint8_t v14, uint8_t v15
|
uint8_t v8, uint8_t v9, uint8_t v10, uint8_t v11, uint8_t v12, uint8_t v13, uint8_t v14, uint8_t v15
|
||||||
) : simd8(make_uint8x16_t(
|
) : simd8(simdjson_make_uint8x16_t(
|
||||||
v0, v1, v2, v3, v4, v5, v6, v7,
|
v0, v1, v2, v3, v4, v5, v6, v7,
|
||||||
v8, v9, v10,v11,v12,v13,v14,v15
|
v8, v9, v10,v11,v12,v13,v14,v15
|
||||||
)) {}
|
)) {}
|
||||||
@@ -283,7 +247,7 @@ simdjson_inline int8x16_t make_int8x16_t(int8_t x1, int8_t x2, int8_t x3, int
|
|||||||
uint8x16_t shufmask = vreinterpretq_u8_u64(shufmask64);
|
uint8x16_t shufmask = vreinterpretq_u8_u64(shufmask64);
|
||||||
// we increment by 0x08 the second half of the mask
|
// we increment by 0x08 the second half of the mask
|
||||||
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
|
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||||
uint8x16_t inc = make_uint8x16_t(0, 0, 0, 0, 0, 0, 0, 0, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08);
|
uint8x16_t inc = simdjson_make_uint8x16_t(0, 0, 0, 0, 0, 0, 0, 0, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08);
|
||||||
#else
|
#else
|
||||||
uint8x16_t inc = {0, 0, 0, 0, 0, 0, 0, 0, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08};
|
uint8x16_t inc = {0, 0, 0, 0, 0, 0, 0, 0, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08};
|
||||||
#endif
|
#endif
|
||||||
@@ -313,7 +277,7 @@ simdjson_inline int8x16_t make_int8x16_t(int8_t x1, int8_t x2, int8_t x3, int
|
|||||||
uint8x8_t compactmask2 = vcreate_u8(thintable_epi8[mask2]);
|
uint8x8_t compactmask2 = vcreate_u8(thintable_epi8[mask2]);
|
||||||
// we increment by 0x08 the second half of the mask
|
// we increment by 0x08 the second half of the mask
|
||||||
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
|
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||||
uint8x8_t inc = make_uint8x8_t(0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08);
|
uint8x8_t inc = simdjson_make_uint8x8_t(0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08);
|
||||||
#else
|
#else
|
||||||
uint8x8_t inc = {0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08};
|
uint8x8_t inc = {0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08};
|
||||||
#endif
|
#endif
|
||||||
@@ -368,7 +332,7 @@ simdjson_inline int8x16_t make_int8x16_t(int8_t x1, int8_t x2, int8_t x3, int
|
|||||||
simdjson_inline simd8(
|
simdjson_inline simd8(
|
||||||
int8_t v0, int8_t v1, int8_t v2, int8_t v3, int8_t v4, int8_t v5, int8_t v6, int8_t v7,
|
int8_t v0, int8_t v1, int8_t v2, int8_t v3, int8_t v4, int8_t v5, int8_t v6, int8_t v7,
|
||||||
int8_t v8, int8_t v9, int8_t v10, int8_t v11, int8_t v12, int8_t v13, int8_t v14, int8_t v15
|
int8_t v8, int8_t v9, int8_t v10, int8_t v11, int8_t v12, int8_t v13, int8_t v14, int8_t v15
|
||||||
) : simd8(make_int8x16_t(
|
) : simd8(simdjson_make_int8x16_t(
|
||||||
v0, v1, v2, v3, v4, v5, v6, v7,
|
v0, v1, v2, v3, v4, v5, v6, v7,
|
||||||
v8, v9, v10,v11,v12,v13,v14,v15
|
v8, v9, v10,v11,v12,v13,v14,v15
|
||||||
)) {}
|
)) {}
|
||||||
@@ -486,7 +450,7 @@ simdjson_inline int8x16_t make_int8x16_t(int8_t x1, int8_t x2, int8_t x3, int
|
|||||||
|
|
||||||
simdjson_inline uint64_t to_bitmask() const {
|
simdjson_inline uint64_t to_bitmask() const {
|
||||||
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
|
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||||
const uint8x16_t bit_mask = make_uint8x16_t(
|
const uint8x16_t bit_mask = simdjson_make_uint8x16_t(
|
||||||
0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80,
|
0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80,
|
||||||
0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80
|
0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80
|
||||||
);
|
);
|
||||||
@@ -527,7 +491,7 @@ simdjson_inline int8x16_t make_int8x16_t(int8_t x1, int8_t x2, int8_t x3, int
|
|||||||
|
|
||||||
} // namespace simd
|
} // namespace simd
|
||||||
} // unnamed namespace
|
} // unnamed namespace
|
||||||
} // namespace SIMDJSON_IMPLEMENTATION
|
} // namespace arm64
|
||||||
} // namespace simdjson
|
} // namespace simdjson
|
||||||
|
|
||||||
#endif // SIMDJSON_ARM64_SIMD_H
|
#endif // SIMDJSON_ARM64_SIMD_H
|
||||||
|
|||||||
+8
-6
@@ -1,12 +1,14 @@
|
|||||||
#ifndef SIMDJSON_ARM64_STRINGPARSING_H
|
#ifndef SIMDJSON_ARM64_STRINGPARSING_DEFS_H
|
||||||
#define SIMDJSON_ARM64_STRINGPARSING_H
|
#define SIMDJSON_ARM64_STRINGPARSING_DEFS_H
|
||||||
|
|
||||||
#include "simdjson/base.h"
|
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
#include "simdjson/arm64/base.h"
|
||||||
#include "simdjson/arm64/simd.h"
|
#include "simdjson/arm64/simd.h"
|
||||||
#include "simdjson/arm64/bitmanipulation.h"
|
#include "simdjson/arm64/bitmanipulation.h"
|
||||||
|
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
|
||||||
namespace simdjson {
|
namespace simdjson {
|
||||||
namespace SIMDJSON_IMPLEMENTATION {
|
namespace arm64 {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
using namespace simd;
|
using namespace simd;
|
||||||
@@ -45,7 +47,7 @@ simdjson_inline backslash_and_quote backslash_and_quote::copy_and_find(const uin
|
|||||||
}
|
}
|
||||||
|
|
||||||
} // unnamed namespace
|
} // unnamed namespace
|
||||||
} // namespace SIMDJSON_IMPLEMENTATION
|
} // namespace arm64
|
||||||
} // namespace simdjson
|
} // namespace simdjson
|
||||||
|
|
||||||
#endif // SIMDJSON_ARM64_STRINGPARSING_H
|
#endif // SIMDJSON_ARM64_STRINGPARSING_DEFS_H
|
||||||
+50
-16
@@ -1,26 +1,60 @@
|
|||||||
|
/**
|
||||||
|
* @file Base declarations for all simdjson headers
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
#ifndef SIMDJSON_BASE_H
|
#ifndef SIMDJSON_BASE_H
|
||||||
#define SIMDJSON_BASE_H
|
#define SIMDJSON_BASE_H
|
||||||
|
|
||||||
#include "simdjson/compiler_check.h"
|
|
||||||
#include "simdjson/common_defs.h"
|
#include "simdjson/common_defs.h"
|
||||||
|
#include "simdjson/compiler_check.h"
|
||||||
|
#include "simdjson/error.h"
|
||||||
#include "simdjson/portability.h"
|
#include "simdjson/portability.h"
|
||||||
|
|
||||||
SIMDJSON_PUSH_DISABLE_WARNINGS
|
/**
|
||||||
SIMDJSON_DISABLE_UNDESIRED_WARNINGS
|
* @brief The top level simdjson namespace, containing everything the library provides.
|
||||||
|
*/
|
||||||
|
namespace simdjson {
|
||||||
|
|
||||||
// Public API
|
SIMDJSON_PUSH_DISABLE_UNUSED_WARNINGS
|
||||||
#include "simdjson/simdjson_version.h"
|
|
||||||
#include "simdjson/error.h"
|
|
||||||
#include "simdjson/minify.h"
|
|
||||||
#include "simdjson/padded_string.h"
|
|
||||||
#include "simdjson/padded_string_view.h"
|
|
||||||
#include "simdjson/implementation.h"
|
|
||||||
|
|
||||||
// Inline functions
|
/** The maximum document size supported by simdjson. */
|
||||||
#include "simdjson/error-inl.h"
|
constexpr size_t SIMDJSON_MAXSIZE_BYTES = 0xFFFFFFFF;
|
||||||
#include "simdjson/padded_string-inl.h"
|
|
||||||
#include "simdjson/padded_string_view-inl.h"
|
|
||||||
|
|
||||||
SIMDJSON_POP_DISABLE_WARNINGS
|
/**
|
||||||
|
* The amount of padding needed in a buffer to parse JSON.
|
||||||
|
*
|
||||||
|
* The input buf should be readable up to buf + SIMDJSON_PADDING
|
||||||
|
* this is a stopgap; there should be a better description of the
|
||||||
|
* main loop and its behavior that abstracts over this
|
||||||
|
* See https://github.com/simdjson/simdjson/issues/174
|
||||||
|
*/
|
||||||
|
constexpr size_t SIMDJSON_PADDING = 64;
|
||||||
|
|
||||||
#endif // SIMDJSON_BASE_H
|
/**
|
||||||
|
* By default, simdjson supports this many nested objects and arrays.
|
||||||
|
*
|
||||||
|
* This is the default for parser::max_depth().
|
||||||
|
*/
|
||||||
|
constexpr size_t DEFAULT_MAX_DEPTH = 1024;
|
||||||
|
|
||||||
|
SIMDJSON_POP_DISABLE_UNUSED_WARNINGS
|
||||||
|
|
||||||
|
class implementation;
|
||||||
|
struct padded_string;
|
||||||
|
class padded_string_view;
|
||||||
|
enum class stage1_mode;
|
||||||
|
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class atomic_ptr;
|
||||||
|
class dom_parser_implementation;
|
||||||
|
class escape_json_string;
|
||||||
|
class tape_ref;
|
||||||
|
struct value128;
|
||||||
|
enum class tape_type;
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
} // namespace simdjson
|
||||||
|
|
||||||
|
#endif // SIMDJSON_BASE_H
|
||||||
|
|||||||
+20
-55
@@ -1,64 +1,29 @@
|
|||||||
#ifndef SIMDJSON_BUILTIN_H
|
#ifndef SIMDJSON_BUILTIN_H
|
||||||
#define SIMDJSON_BUILTIN_H
|
#define SIMDJSON_BUILTIN_H
|
||||||
|
|
||||||
#include "simdjson/implementations.h"
|
#include "simdjson/builtin/base.h"
|
||||||
|
#include "simdjson/builtin/implementation.h"
|
||||||
|
|
||||||
// Determine the best builtin implementation
|
#include "simdjson/generic/dependencies.h"
|
||||||
#ifndef SIMDJSON_BUILTIN_IMPLEMENTATION
|
|
||||||
#if SIMDJSON_CAN_ALWAYS_RUN_ICELAKE
|
#define SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
#define SIMDJSON_BUILTIN_IMPLEMENTATION icelake
|
|
||||||
#elif SIMDJSON_CAN_ALWAYS_RUN_HASWELL
|
#if SIMDJSON_BUILTIN_IMPLEMENTATION_IS(arm64)
|
||||||
#define SIMDJSON_BUILTIN_IMPLEMENTATION haswell
|
#include "simdjson/arm64.h"
|
||||||
#elif SIMDJSON_CAN_ALWAYS_RUN_WESTMERE
|
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(fallback)
|
||||||
#define SIMDJSON_BUILTIN_IMPLEMENTATION westmere
|
#include "simdjson/fallback.h"
|
||||||
#elif SIMDJSON_CAN_ALWAYS_RUN_ARM64
|
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(haswell)
|
||||||
#define SIMDJSON_BUILTIN_IMPLEMENTATION arm64
|
#include "simdjson/haswell.h"
|
||||||
#elif SIMDJSON_CAN_ALWAYS_RUN_PPC64
|
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(icelake)
|
||||||
#define SIMDJSON_BUILTIN_IMPLEMENTATION ppc64
|
#include "simdjson/icelake.h"
|
||||||
#elif SIMDJSON_CAN_ALWAYS_RUN_FALLBACK
|
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(ppc64)
|
||||||
#define SIMDJSON_BUILTIN_IMPLEMENTATION fallback
|
#include "simdjson/ppc64.h"
|
||||||
|
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(westmere)
|
||||||
|
#include "simdjson/westmere.h"
|
||||||
#else
|
#else
|
||||||
#error "All possible implementations (including fallback) have been disabled! simdjson will not run."
|
#error Unknown SIMDJSON_BUILTIN_IMPLEMENTATION
|
||||||
#endif
|
#endif
|
||||||
#endif // SIMDJSON_BUILTIN_IMPLEMENTATION
|
|
||||||
|
|
||||||
#define SIMDJSON_IMPLEMENTATION SIMDJSON_BUILTIN_IMPLEMENTATION
|
#undef SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
|
||||||
// ondemand is only compiled as part of the builtin implementation at present
|
|
||||||
|
|
||||||
// Interface declarations
|
|
||||||
#include "simdjson/generic/implementation_simdjson_result_base.h"
|
|
||||||
#include "simdjson/generic/ondemand.h"
|
|
||||||
|
|
||||||
// Inline definitions
|
|
||||||
#include "simdjson/generic/implementation_simdjson_result_base-inl.h"
|
|
||||||
#include "simdjson/generic/ondemand-inl.h"
|
|
||||||
|
|
||||||
#undef SIMDJSON_IMPLEMENTATION
|
|
||||||
|
|
||||||
namespace simdjson {
|
|
||||||
/**
|
|
||||||
* Represents the best statically linked simdjson implementation that can be used by the compiling
|
|
||||||
* program.
|
|
||||||
*
|
|
||||||
* Detects what options the program is compiled against, and picks the minimum implementation that
|
|
||||||
* will work on any computer that can run the program. For example, if you compile with g++
|
|
||||||
* -march=westmere, it will pick the westmere implementation. The haswell implementation will
|
|
||||||
* still be available, and can be selected at runtime, but the builtin implementation (and any
|
|
||||||
* code that uses it) will use westmere.
|
|
||||||
*/
|
|
||||||
namespace builtin = SIMDJSON_BUILTIN_IMPLEMENTATION;
|
|
||||||
/**
|
|
||||||
* @copydoc simdjson::SIMDJSON_BUILTIN_IMPLEMENTATION::ondemand
|
|
||||||
*/
|
|
||||||
namespace ondemand = SIMDJSON_BUILTIN_IMPLEMENTATION::ondemand;
|
|
||||||
/**
|
|
||||||
* Function which returns a pointer to an implementation matching the "builtin" implementation.
|
|
||||||
* The builtin implementation is the best statically linked simdjson implementation that can be used by the compiling
|
|
||||||
* program. If you compile with g++ -march=haswell, this will return the haswell implementation.
|
|
||||||
* It is handy to be able to check what builtin was used: builtin_implementation()->name().
|
|
||||||
*/
|
|
||||||
const implementation * builtin_implementation();
|
|
||||||
} // namespace simdjson
|
|
||||||
|
|
||||||
#endif // SIMDJSON_BUILTIN_H
|
#endif // SIMDJSON_BUILTIN_H
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
#ifndef SIMDJSON_BUILTIN_BASE_H
|
||||||
|
#define SIMDJSON_BUILTIN_BASE_H
|
||||||
|
|
||||||
|
#include "simdjson/base.h"
|
||||||
|
#include "simdjson/implementation_detection.h"
|
||||||
|
|
||||||
|
namespace simdjson {
|
||||||
|
#if SIMDJSON_BUILTIN_IMPLEMENTATION_IS(arm64)
|
||||||
|
namespace arm64 {}
|
||||||
|
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(fallback)
|
||||||
|
namespace fallback {}
|
||||||
|
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(haswell)
|
||||||
|
namespace haswell {}
|
||||||
|
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(icelake)
|
||||||
|
namespace icelake {}
|
||||||
|
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(ppc64)
|
||||||
|
namespace ppc64 {}
|
||||||
|
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(westmere)
|
||||||
|
namespace westmere {}
|
||||||
|
#else
|
||||||
|
#error Unknown SIMDJSON_BUILTIN_IMPLEMENTATION
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the best statically linked simdjson implementation that can be used by the compiling
|
||||||
|
* program.
|
||||||
|
*
|
||||||
|
* Detects what options the program is compiled against, and picks the minimum implementation that
|
||||||
|
* will work on any computer that can run the program. For example, if you compile with g++
|
||||||
|
* -march=westmere, it will pick the westmere implementation. The haswell implementation will
|
||||||
|
* still be available, and can be selected at runtime, but the builtin implementation (and any
|
||||||
|
* code that uses it) will use westmere.
|
||||||
|
*/
|
||||||
|
namespace builtin = SIMDJSON_BUILTIN_IMPLEMENTATION;
|
||||||
|
} // namespace simdjson
|
||||||
|
|
||||||
|
#endif // SIMDJSON_BUILTIN_BASE_H
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
#ifndef SIMDJSON_BUILTIN_IMPLEMENTATION_H
|
||||||
|
#define SIMDJSON_BUILTIN_IMPLEMENTATION_H
|
||||||
|
|
||||||
|
#include "simdjson/builtin/base.h"
|
||||||
|
|
||||||
|
#include "simdjson/generic/dependencies.h"
|
||||||
|
|
||||||
|
#define SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
|
||||||
|
#if SIMDJSON_BUILTIN_IMPLEMENTATION_IS(arm64)
|
||||||
|
#include "simdjson/arm64/implementation.h"
|
||||||
|
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(fallback)
|
||||||
|
#include "simdjson/fallback/implementation.h"
|
||||||
|
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(haswell)
|
||||||
|
#include "simdjson/haswell/implementation.h"
|
||||||
|
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(icelake)
|
||||||
|
#include "simdjson/icelake/implementation.h"
|
||||||
|
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(ppc64)
|
||||||
|
#include "simdjson/ppc64/implementation.h"
|
||||||
|
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(westmere)
|
||||||
|
#include "simdjson/westmere/implementation.h"
|
||||||
|
#else
|
||||||
|
#error Unknown SIMDJSON_BUILTIN_IMPLEMENTATION
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#undef SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
|
||||||
|
namespace simdjson {
|
||||||
|
/**
|
||||||
|
* Function which returns a pointer to an implementation matching the "builtin" implementation.
|
||||||
|
* The builtin implementation is the best statically linked simdjson implementation that can be used by the compiling
|
||||||
|
* program. If you compile with g++ -march=haswell, this will return the haswell implementation.
|
||||||
|
* It is handy to be able to check what builtin was used: builtin_implementation()->name().
|
||||||
|
*/
|
||||||
|
const implementation * builtin_implementation();
|
||||||
|
} // namespace simdjson
|
||||||
|
|
||||||
|
#endif // SIMDJSON_BUILTIN_IMPLEMENTATION_H
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
#ifndef SIMDJSON_BUILTIN_ONDEMAND_H
|
||||||
|
#define SIMDJSON_BUILTIN_ONDEMAND_H
|
||||||
|
|
||||||
|
#include "simdjson/builtin.h"
|
||||||
|
#include "simdjson/builtin/base.h"
|
||||||
|
|
||||||
|
#include "simdjson/generic/ondemand/dependencies.h"
|
||||||
|
|
||||||
|
#define SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
|
||||||
|
#if SIMDJSON_BUILTIN_IMPLEMENTATION_IS(arm64)
|
||||||
|
#include "simdjson/arm64/ondemand.h"
|
||||||
|
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(fallback)
|
||||||
|
#include "simdjson/fallback/ondemand.h"
|
||||||
|
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(haswell)
|
||||||
|
#include "simdjson/haswell/ondemand.h"
|
||||||
|
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(icelake)
|
||||||
|
#include "simdjson/icelake/ondemand.h"
|
||||||
|
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(ppc64)
|
||||||
|
#include "simdjson/ppc64/ondemand.h"
|
||||||
|
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(westmere)
|
||||||
|
#include "simdjson/westmere/ondemand.h"
|
||||||
|
#else
|
||||||
|
#error Unknown SIMDJSON_BUILTIN_IMPLEMENTATION
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#undef SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
|
||||||
|
namespace simdjson {
|
||||||
|
/**
|
||||||
|
* @copydoc simdjson::SIMDJSON_BUILTIN_IMPLEMENTATION::ondemand
|
||||||
|
*/
|
||||||
|
namespace ondemand = SIMDJSON_BUILTIN_IMPLEMENTATION::ondemand;
|
||||||
|
} // namespace simdjson
|
||||||
|
|
||||||
|
#endif // SIMDJSON_BUILTIN_ONDEMAND_H
|
||||||
@@ -2,10 +2,10 @@
|
|||||||
#define SIMDJSON_COMMON_DEFS_H
|
#define SIMDJSON_COMMON_DEFS_H
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include "simdjson/compiler_check.h"
|
||||||
#include "simdjson/portability.h"
|
#include "simdjson/portability.h"
|
||||||
|
|
||||||
namespace simdjson {
|
namespace simdjson {
|
||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
@@ -20,7 +20,6 @@ char *to_chars(char *first, const char *last, double value);
|
|||||||
*/
|
*/
|
||||||
double from_chars(const char *first) noexcept;
|
double from_chars(const char *first) noexcept;
|
||||||
double from_chars(const char *first, const char* end) noexcept;
|
double from_chars(const char *first, const char* end) noexcept;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef SIMDJSON_EXCEPTIONS
|
#ifndef SIMDJSON_EXCEPTIONS
|
||||||
@@ -31,26 +30,6 @@ double from_chars(const char *first, const char* end) noexcept;
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/** The maximum document size supported by simdjson. */
|
|
||||||
constexpr size_t SIMDJSON_MAXSIZE_BYTES = 0xFFFFFFFF;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The amount of padding needed in a buffer to parse JSON.
|
|
||||||
*
|
|
||||||
* The input buf should be readable up to buf + SIMDJSON_PADDING
|
|
||||||
* this is a stopgap; there should be a better description of the
|
|
||||||
* main loop and its behavior that abstracts over this
|
|
||||||
* See https://github.com/simdjson/simdjson/issues/174
|
|
||||||
*/
|
|
||||||
constexpr size_t SIMDJSON_PADDING = 64;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* By default, simdjson supports this many nested objects and arrays.
|
|
||||||
*
|
|
||||||
* This is the default for parser::max_depth().
|
|
||||||
*/
|
|
||||||
constexpr size_t DEFAULT_MAX_DEPTH = 1024;
|
|
||||||
|
|
||||||
} // namespace simdjson
|
} // namespace simdjson
|
||||||
|
|
||||||
#if defined(__GNUC__)
|
#if defined(__GNUC__)
|
||||||
@@ -105,6 +84,9 @@ constexpr size_t DEFAULT_MAX_DEPTH = 1024;
|
|||||||
#define SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING
|
#define SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING
|
||||||
#define SIMDJSON_POP_DISABLE_WARNINGS __pragma(warning( pop ))
|
#define SIMDJSON_POP_DISABLE_WARNINGS __pragma(warning( pop ))
|
||||||
|
|
||||||
|
#define SIMDJSON_PUSH_DISABLE_UNUSED_WARNINGS
|
||||||
|
#define SIMDJSON_POP_DISABLE_UNUSED_WARNINGS
|
||||||
|
|
||||||
#else // SIMDJSON_REGULAR_VISUAL_STUDIO
|
#else // SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||||
|
|
||||||
#define simdjson_really_inline inline __attribute__((always_inline))
|
#define simdjson_really_inline inline __attribute__((always_inline))
|
||||||
@@ -150,7 +132,8 @@ constexpr size_t DEFAULT_MAX_DEPTH = 1024;
|
|||||||
SIMDJSON_DISABLE_GCC_WARNING(-Wshadow) \
|
SIMDJSON_DISABLE_GCC_WARNING(-Wshadow) \
|
||||||
SIMDJSON_DISABLE_GCC_WARNING(-Wunused-parameter) \
|
SIMDJSON_DISABLE_GCC_WARNING(-Wunused-parameter) \
|
||||||
SIMDJSON_DISABLE_GCC_WARNING(-Wunused-variable) \
|
SIMDJSON_DISABLE_GCC_WARNING(-Wunused-variable) \
|
||||||
SIMDJSON_DISABLE_GCC_WARNING(-Wmaybe-uninitialized)
|
SIMDJSON_DISABLE_GCC_WARNING(-Wmaybe-uninitialized) \
|
||||||
|
SIMDJSON_DISABLE_GCC_WARNING(-Wformat-security)
|
||||||
#endif // __clang__
|
#endif // __clang__
|
||||||
|
|
||||||
#define SIMDJSON_PRAGMA(P) _Pragma(#P)
|
#define SIMDJSON_PRAGMA(P) _Pragma(#P)
|
||||||
@@ -164,6 +147,10 @@ constexpr size_t DEFAULT_MAX_DEPTH = 1024;
|
|||||||
#define SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING SIMDJSON_DISABLE_GCC_WARNING(-Wstrict-overflow)
|
#define SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING SIMDJSON_DISABLE_GCC_WARNING(-Wstrict-overflow)
|
||||||
#define SIMDJSON_POP_DISABLE_WARNINGS _Pragma("GCC diagnostic pop")
|
#define SIMDJSON_POP_DISABLE_WARNINGS _Pragma("GCC diagnostic pop")
|
||||||
|
|
||||||
|
#define SIMDJSON_PUSH_DISABLE_UNUSED_WARNINGS SIMDJSON_PUSH_DISABLE_WARNINGS \
|
||||||
|
SIMDJSON_DISABLE_GCC_WARNING(-Wunused)
|
||||||
|
#define SIMDJSON_POP_DISABLE_UNUSED_WARNINGS SIMDJSON_POP_DISABLE_WARNINGS
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif // MSC_VER
|
#endif // MSC_VER
|
||||||
@@ -322,7 +309,6 @@ namespace std {
|
|||||||
# define simdjson_fallthrough do {} while (0) /* fallthrough */
|
# define simdjson_fallthrough do {} while (0) /* fallthrough */
|
||||||
#endif // simdjson_fallthrough
|
#endif // simdjson_fallthrough
|
||||||
|
|
||||||
|
|
||||||
#if SIMDJSON_DEVELOPMENT_CHECKS
|
#if SIMDJSON_DEVELOPMENT_CHECKS
|
||||||
#define SIMDJSON_DEVELOPMENT_ASSERT(expr) do { assert ((expr)); } while (0)
|
#define SIMDJSON_DEVELOPMENT_ASSERT(expr) do { assert ((expr)); } while (0)
|
||||||
#else
|
#else
|
||||||
@@ -333,4 +319,25 @@ namespace std {
|
|||||||
#define SIMDJSON_UTF8VALIDATION 1
|
#define SIMDJSON_UTF8VALIDATION 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __has_include
|
||||||
|
// How do we detect that a compiler supports vbmi2?
|
||||||
|
// For sure if the following header is found, we are ok?
|
||||||
|
#if __has_include(<avx512vbmi2intrin.h>)
|
||||||
|
#define SIMDJSON_COMPILER_SUPPORTS_VBMI2 1
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#if _MSC_VER >= 1920
|
||||||
|
// Visual Studio 2019 and up support VBMI2 under x64 even if the header
|
||||||
|
// avx512vbmi2intrin.h is not found.
|
||||||
|
#define SIMDJSON_COMPILER_SUPPORTS_VBMI2 1
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// By default, we allow AVX512.
|
||||||
|
#ifndef SIMDJSON_AVX512_ALLOWED
|
||||||
|
#define SIMDJSON_AVX512_ALLOWED 1
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // SIMDJSON_COMMON_DEFS_H
|
#endif // SIMDJSON_COMMON_DEFS_H
|
||||||
|
|||||||
@@ -32,4 +32,12 @@
|
|||||||
#error simdjson requires a compiler compliant with the C++11 standard
|
#error simdjson requires a compiler compliant with the C++11 standard
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef SIMDJSON_IF_CONSTEXPR
|
||||||
|
#if SIMDJSON_CPLUSPLUS17
|
||||||
|
#define SIMDJSON_IF_CONSTEXPR if constexpr
|
||||||
|
#else
|
||||||
|
#define SIMDJSON_IF_CONSTEXPR if
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // SIMDJSON_COMPILER_CHECK_H
|
#endif // SIMDJSON_COMPILER_CHECK_H
|
||||||
|
|||||||
@@ -1,11 +1,7 @@
|
|||||||
#ifndef SIMDJSON_DOM_H
|
#ifndef SIMDJSON_DOM_H
|
||||||
#define SIMDJSON_DOM_H
|
#define SIMDJSON_DOM_H
|
||||||
|
|
||||||
#include "simdjson/base.h"
|
#include "simdjson/dom/base.h"
|
||||||
|
|
||||||
SIMDJSON_PUSH_DISABLE_WARNINGS
|
|
||||||
SIMDJSON_DISABLE_UNDESIRED_WARNINGS
|
|
||||||
|
|
||||||
#include "simdjson/dom/array.h"
|
#include "simdjson/dom/array.h"
|
||||||
#include "simdjson/dom/document_stream.h"
|
#include "simdjson/dom/document_stream.h"
|
||||||
#include "simdjson/dom/document.h"
|
#include "simdjson/dom/document.h"
|
||||||
@@ -30,6 +26,4 @@ SIMDJSON_DISABLE_UNDESIRED_WARNINGS
|
|||||||
#include "simdjson/internal/tape_ref-inl.h"
|
#include "simdjson/internal/tape_ref-inl.h"
|
||||||
#include "simdjson/dom/serialization-inl.h"
|
#include "simdjson/dom/serialization-inl.h"
|
||||||
|
|
||||||
SIMDJSON_POP_DISABLE_WARNINGS
|
|
||||||
|
|
||||||
#endif // SIMDJSON_DOM_H
|
#endif // SIMDJSON_DOM_H
|
||||||
|
|||||||
@@ -1,11 +1,15 @@
|
|||||||
#ifndef SIMDJSON_INLINE_ARRAY_H
|
#ifndef SIMDJSON_ARRAY_INL_H
|
||||||
#define SIMDJSON_INLINE_ARRAY_H
|
#define SIMDJSON_ARRAY_INL_H
|
||||||
|
|
||||||
// Inline implementations go in here.
|
#include <utility>
|
||||||
|
|
||||||
|
#include "simdjson/dom/base.h"
|
||||||
#include "simdjson/dom/array.h"
|
#include "simdjson/dom/array.h"
|
||||||
#include "simdjson/dom/element.h"
|
#include "simdjson/dom/element.h"
|
||||||
#include <utility>
|
#include "simdjson/error-inl.h"
|
||||||
|
#include "simdjson/internal/tape_ref-inl.h"
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
namespace simdjson {
|
namespace simdjson {
|
||||||
|
|
||||||
@@ -170,4 +174,4 @@ static_assert(std::ranges::sized_range<simdjson::simdjson_result<simdjson::dom::
|
|||||||
#endif // SIMDJSON_EXCEPTIONS
|
#endif // SIMDJSON_EXCEPTIONS
|
||||||
#endif // defined(__cpp_lib_ranges)
|
#endif // defined(__cpp_lib_ranges)
|
||||||
|
|
||||||
#endif // SIMDJSON_INLINE_ARRAY_H
|
#endif // SIMDJSON_ARRAY_INL_H
|
||||||
|
|||||||
@@ -1,21 +1,12 @@
|
|||||||
#ifndef SIMDJSON_DOM_ARRAY_H
|
#ifndef SIMDJSON_DOM_ARRAY_H
|
||||||
#define SIMDJSON_DOM_ARRAY_H
|
#define SIMDJSON_DOM_ARRAY_H
|
||||||
|
|
||||||
#include "simdjson/common_defs.h"
|
#include "simdjson/dom/base.h"
|
||||||
#include "simdjson/error.h"
|
|
||||||
#include "simdjson/internal/tape_ref.h"
|
#include "simdjson/internal/tape_ref.h"
|
||||||
|
|
||||||
namespace simdjson {
|
namespace simdjson {
|
||||||
|
|
||||||
namespace internal {
|
|
||||||
template<typename T>
|
|
||||||
class string_builder;
|
|
||||||
}
|
|
||||||
namespace dom {
|
namespace dom {
|
||||||
|
|
||||||
class document;
|
|
||||||
class element;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JSON array.
|
* JSON array.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
#ifndef SIMDJSON_DOM_BASE_H
|
||||||
|
#define SIMDJSON_DOM_BASE_H
|
||||||
|
|
||||||
|
#include "simdjson/base.h"
|
||||||
|
|
||||||
|
namespace simdjson {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A DOM API on top of the simdjson parser.
|
||||||
|
*/
|
||||||
|
namespace dom {
|
||||||
|
|
||||||
|
/** The default batch size for parser.parse_many() and parser.load_many() */
|
||||||
|
static constexpr size_t DEFAULT_BATCH_SIZE = 1000000;
|
||||||
|
/**
|
||||||
|
* Some adversary might try to set the batch size to 0 or 1, which might cause problems.
|
||||||
|
* We set a minimum of 32B since anything else is highly likely to be an error. In practice,
|
||||||
|
* most users will want a much larger batch size.
|
||||||
|
*
|
||||||
|
* All non-negative MINIMAL_BATCH_SIZE values should be 'safe' except that, obviously, no JSON
|
||||||
|
* document can ever span 0 or 1 byte and that very large values would create memory allocation issues.
|
||||||
|
*/
|
||||||
|
static constexpr size_t MINIMAL_BATCH_SIZE = 32;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* It is wasteful to allocate memory for tiny documents (e.g., 4 bytes).
|
||||||
|
*/
|
||||||
|
static constexpr size_t MINIMAL_DOCUMENT_CAPACITY = 32;
|
||||||
|
|
||||||
|
class array;
|
||||||
|
class document;
|
||||||
|
class document_stream;
|
||||||
|
class element;
|
||||||
|
class key_value_pair;
|
||||||
|
class object;
|
||||||
|
class parser;
|
||||||
|
|
||||||
|
#ifdef SIMDJSON_THREADS_ENABLED
|
||||||
|
struct stage1_worker;
|
||||||
|
#endif // SIMDJSON_THREADS_ENABLED
|
||||||
|
|
||||||
|
} // namespace dom
|
||||||
|
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class string_builder;
|
||||||
|
class tape_ref;
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
|
||||||
|
} // namespace simdjson
|
||||||
|
|
||||||
|
#endif // SIMDJSON_DOM_BASE_H
|
||||||
@@ -1,13 +1,14 @@
|
|||||||
#ifndef SIMDJSON_INLINE_DOCUMENT_H
|
#ifndef SIMDJSON_DOCUMENT_INL_H
|
||||||
#define SIMDJSON_INLINE_DOCUMENT_H
|
#define SIMDJSON_DOCUMENT_INL_H
|
||||||
|
|
||||||
// Inline implementations go in here.
|
// Inline implementations go in here.
|
||||||
|
|
||||||
|
#include "simdjson/dom/base.h"
|
||||||
#include "simdjson/dom/document.h"
|
#include "simdjson/dom/document.h"
|
||||||
#include "simdjson/dom/element.h"
|
#include "simdjson/dom/element-inl.h"
|
||||||
#include "simdjson/internal/tape_ref.h"
|
#include "simdjson/internal/tape_ref-inl.h"
|
||||||
#include "simdjson/internal/jsonformatutils.h"
|
#include "simdjson/internal/jsonformatutils.h"
|
||||||
#include <ostream>
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
namespace simdjson {
|
namespace simdjson {
|
||||||
@@ -155,4 +156,4 @@ inline bool document::dump_raw_tape(std::ostream &os) const noexcept {
|
|||||||
} // namespace dom
|
} // namespace dom
|
||||||
} // namespace simdjson
|
} // namespace simdjson
|
||||||
|
|
||||||
#endif // SIMDJSON_INLINE_DOCUMENT_H
|
#endif // SIMDJSON_DOCUMENT_INL_H
|
||||||
|
|||||||
@@ -1,15 +1,13 @@
|
|||||||
#ifndef SIMDJSON_DOM_DOCUMENT_H
|
#ifndef SIMDJSON_DOM_DOCUMENT_H
|
||||||
#define SIMDJSON_DOM_DOCUMENT_H
|
#define SIMDJSON_DOM_DOCUMENT_H
|
||||||
|
|
||||||
#include "simdjson/common_defs.h"
|
#include "simdjson/dom/base.h"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <ostream>
|
|
||||||
|
|
||||||
namespace simdjson {
|
namespace simdjson {
|
||||||
namespace dom {
|
namespace dom {
|
||||||
|
|
||||||
class element;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A parsed JSON document.
|
* A parsed JSON document.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,14 +1,18 @@
|
|||||||
#ifndef SIMDJSON_INLINE_DOCUMENT_STREAM_H
|
#ifndef SIMDJSON_DOCUMENT_STREAM_INL_H
|
||||||
#define SIMDJSON_INLINE_DOCUMENT_STREAM_H
|
#define SIMDJSON_DOCUMENT_STREAM_INL_H
|
||||||
|
|
||||||
|
#include "simdjson/dom/base.h"
|
||||||
#include "simdjson/dom/document_stream.h"
|
#include "simdjson/dom/document_stream.h"
|
||||||
#include <algorithm>
|
#include "simdjson/dom/element-inl.h"
|
||||||
#include <limits>
|
#include "simdjson/dom/parser-inl.h"
|
||||||
#include <stdexcept>
|
#include "simdjson/error-inl.h"
|
||||||
|
#include "simdjson/internal/dom_parser_implementation.h"
|
||||||
|
|
||||||
namespace simdjson {
|
namespace simdjson {
|
||||||
namespace dom {
|
namespace dom {
|
||||||
|
|
||||||
#ifdef SIMDJSON_THREADS_ENABLED
|
#ifdef SIMDJSON_THREADS_ENABLED
|
||||||
|
|
||||||
inline void stage1_worker::finish() {
|
inline void stage1_worker::finish() {
|
||||||
// After calling "run" someone would call finish() to wait
|
// After calling "run" someone would call finish() to wait
|
||||||
// for the end of the processing.
|
// for the end of the processing.
|
||||||
@@ -337,4 +341,4 @@ simdjson_inline dom::document_stream::iterator simdjson_result<dom::document_str
|
|||||||
#endif // SIMDJSON_EXCEPTIONS
|
#endif // SIMDJSON_EXCEPTIONS
|
||||||
|
|
||||||
} // namespace simdjson
|
} // namespace simdjson
|
||||||
#endif // SIMDJSON_INLINE_DOCUMENT_STREAM_H
|
#endif // SIMDJSON_DOCUMENT_STREAM_INL_H
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
#ifndef SIMDJSON_DOCUMENT_STREAM_H
|
#ifndef SIMDJSON_DOCUMENT_STREAM_H
|
||||||
#define SIMDJSON_DOCUMENT_STREAM_H
|
#define SIMDJSON_DOCUMENT_STREAM_H
|
||||||
|
|
||||||
#include "simdjson/common_defs.h"
|
#include "simdjson/dom/base.h"
|
||||||
#include "simdjson/dom/parser.h"
|
#include "simdjson/dom/parser.h"
|
||||||
#include "simdjson/error.h"
|
|
||||||
#ifdef SIMDJSON_THREADS_ENABLED
|
#ifdef SIMDJSON_THREADS_ENABLED
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
@@ -13,7 +13,6 @@
|
|||||||
namespace simdjson {
|
namespace simdjson {
|
||||||
namespace dom {
|
namespace dom {
|
||||||
|
|
||||||
|
|
||||||
#ifdef SIMDJSON_THREADS_ENABLED
|
#ifdef SIMDJSON_THREADS_ENABLED
|
||||||
/** @private Custom worker class **/
|
/** @private Custom worker class **/
|
||||||
struct stage1_worker {
|
struct stage1_worker {
|
||||||
@@ -225,8 +224,7 @@ private:
|
|||||||
* Parse the next document found in the buffer previously given to document_stream.
|
* Parse the next document found in the buffer previously given to document_stream.
|
||||||
*
|
*
|
||||||
* The content should be a valid JSON document encoded as UTF-8. If there is a
|
* The content should be a valid JSON document encoded as UTF-8. If there is a
|
||||||
* UTF-8 BOM, the caller is responsible for omitting it, UTF-8 BOM are
|
* UTF-8 BOM, the parser skips it.
|
||||||
* discouraged.
|
|
||||||
*
|
*
|
||||||
* You do NOT need to pre-allocate a parser. This function takes care of
|
* You do NOT need to pre-allocate a parser. This function takes care of
|
||||||
* pre-allocating a capacity defined by the batch_size defined when creating the
|
* pre-allocating a capacity defined by the batch_size defined when creating the
|
||||||
|
|||||||
@@ -1,11 +1,17 @@
|
|||||||
#ifndef SIMDJSON_INLINE_ELEMENT_H
|
#ifndef SIMDJSON_ELEMENT_INL_H
|
||||||
#define SIMDJSON_INLINE_ELEMENT_H
|
#define SIMDJSON_ELEMENT_INL_H
|
||||||
|
|
||||||
#include "simdjson/dom/array.h"
|
#include "simdjson/dom/base.h"
|
||||||
#include "simdjson/dom/element.h"
|
#include "simdjson/dom/element.h"
|
||||||
|
#include "simdjson/dom/document.h"
|
||||||
#include "simdjson/dom/object.h"
|
#include "simdjson/dom/object.h"
|
||||||
#include <cstring>
|
#include "simdjson/internal/tape_type.h"
|
||||||
#include <utility>
|
|
||||||
|
#include "simdjson/dom/object-inl.h"
|
||||||
|
#include "simdjson/error-inl.h"
|
||||||
|
|
||||||
|
#include <ostream>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
namespace simdjson {
|
namespace simdjson {
|
||||||
|
|
||||||
@@ -404,6 +410,12 @@ inline simdjson_result<element> element::at_key(std::string_view key) const noex
|
|||||||
inline simdjson_result<element> element::at_key_case_insensitive(std::string_view key) const noexcept {
|
inline simdjson_result<element> element::at_key_case_insensitive(std::string_view key) const noexcept {
|
||||||
return get<object>().at_key_case_insensitive(key);
|
return get<object>().at_key_case_insensitive(key);
|
||||||
}
|
}
|
||||||
|
inline bool element::operator<(const element &other) const noexcept {
|
||||||
|
return tape.json_index < other.tape.json_index;
|
||||||
|
}
|
||||||
|
inline bool element::operator==(const element &other) const noexcept {
|
||||||
|
return tape.json_index == other.tape.json_index;
|
||||||
|
}
|
||||||
|
|
||||||
inline bool element::dump_raw_tape(std::ostream &out) const noexcept {
|
inline bool element::dump_raw_tape(std::ostream &out) const noexcept {
|
||||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||||
@@ -438,4 +450,4 @@ inline std::ostream& operator<<(std::ostream& out, element_type type) {
|
|||||||
|
|
||||||
} // namespace simdjson
|
} // namespace simdjson
|
||||||
|
|
||||||
#endif // SIMDJSON_INLINE_ELEMENT_H
|
#endif // SIMDJSON_ELEMENT_INL_H
|
||||||
|
|||||||
@@ -1,20 +1,11 @@
|
|||||||
#ifndef SIMDJSON_DOM_ELEMENT_H
|
#ifndef SIMDJSON_DOM_ELEMENT_H
|
||||||
#define SIMDJSON_DOM_ELEMENT_H
|
#define SIMDJSON_DOM_ELEMENT_H
|
||||||
|
|
||||||
#include "simdjson/common_defs.h"
|
#include "simdjson/dom/base.h"
|
||||||
#include "simdjson/error.h"
|
#include "simdjson/dom/array.h"
|
||||||
#include "simdjson/internal/tape_ref.h"
|
|
||||||
#include <ostream>
|
|
||||||
|
|
||||||
namespace simdjson {
|
namespace simdjson {
|
||||||
namespace internal {
|
|
||||||
template<typename T>
|
|
||||||
class string_builder;
|
|
||||||
}
|
|
||||||
namespace dom {
|
namespace dom {
|
||||||
class array;
|
|
||||||
class document;
|
|
||||||
class object;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The actual concrete type of a JSON element
|
* The actual concrete type of a JSON element
|
||||||
@@ -220,7 +211,11 @@ public:
|
|||||||
inline simdjson_result<T> get() const noexcept {
|
inline simdjson_result<T> get() const noexcept {
|
||||||
// Unless the simdjson library provides an inline implementation, calling this method should
|
// Unless the simdjson library provides an inline implementation, calling this method should
|
||||||
// immediately fail.
|
// immediately fail.
|
||||||
static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library.");
|
static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. "
|
||||||
|
"The supported types are Boolean (bool), numbers (double, uint64_t, int64_t), "
|
||||||
|
"strings (std::string_view, const char *), arrays (dom::array) and objects (dom::object). "
|
||||||
|
"We recommand you use get_double(), get_bool(), get_uint64(), get_int64(), "
|
||||||
|
"get_object(), get_array() or get_string() instead of the get template.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -460,6 +455,22 @@ public:
|
|||||||
*/
|
*/
|
||||||
inline simdjson_result<element> at_key_case_insensitive(std::string_view key) const noexcept;
|
inline simdjson_result<element> at_key_case_insensitive(std::string_view key) const noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* operator< defines a total order for element allowing to use them in
|
||||||
|
* ordered C++ STL containers
|
||||||
|
*
|
||||||
|
* @return TRUE if the key appears before the other one in the tape
|
||||||
|
*/
|
||||||
|
inline bool operator<(const element &other) const noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* operator== allows to verify if two element values reference the
|
||||||
|
* same JSON item
|
||||||
|
*
|
||||||
|
* @return TRUE if the two values references the same JSON element
|
||||||
|
*/
|
||||||
|
inline bool operator==(const element &other) const noexcept;
|
||||||
|
|
||||||
/** @private for debugging. Prints out the root element. */
|
/** @private for debugging. Prints out the root element. */
|
||||||
inline bool dump_raw_tape(std::ostream &out) const noexcept;
|
inline bool dump_raw_tape(std::ostream &out) const noexcept;
|
||||||
|
|
||||||
@@ -537,7 +548,6 @@ public:
|
|||||||
#endif // SIMDJSON_EXCEPTIONS
|
#endif // SIMDJSON_EXCEPTIONS
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace simdjson
|
} // namespace simdjson
|
||||||
|
|
||||||
#endif // SIMDJSON_DOM_DOCUMENT_H
|
#endif // SIMDJSON_DOM_DOCUMENT_H
|
||||||
|
|||||||
@@ -3,9 +3,11 @@
|
|||||||
#ifndef SIMDJSON_DOM_JSONPARSER_H
|
#ifndef SIMDJSON_DOM_JSONPARSER_H
|
||||||
#define SIMDJSON_DOM_JSONPARSER_H
|
#define SIMDJSON_DOM_JSONPARSER_H
|
||||||
|
|
||||||
#include "simdjson/dom/document.h"
|
#include "simdjson/dom/base.h"
|
||||||
#include "simdjson/dom/parsedjson.h"
|
#include "simdjson/dom/parser.h"
|
||||||
#include "simdjson/jsonioutil.h"
|
#include "simdjson/dom/element.h"
|
||||||
|
|
||||||
|
#include "simdjson/dom/parser-inl.h"
|
||||||
|
|
||||||
namespace simdjson {
|
namespace simdjson {
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
#ifndef SIMDJSON_INLINE_OBJECT_H
|
#ifndef SIMDJSON_OBJECT_INL_H
|
||||||
#define SIMDJSON_INLINE_OBJECT_H
|
#define SIMDJSON_OBJECT_INL_H
|
||||||
|
|
||||||
#include "simdjson/dom/element.h"
|
#include "simdjson/dom/base.h"
|
||||||
#include "simdjson/dom/object.h"
|
#include "simdjson/dom/object.h"
|
||||||
#include "simdjson/portability.h"
|
#include "simdjson/dom/document.h"
|
||||||
|
|
||||||
|
#include "simdjson/dom/element-inl.h"
|
||||||
|
#include "simdjson/error-inl.h"
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace simdjson {
|
namespace simdjson {
|
||||||
|
|
||||||
@@ -253,4 +256,4 @@ static_assert(std::ranges::sized_range<simdjson::simdjson_result<simdjson::dom::
|
|||||||
#endif // SIMDJSON_EXCEPTIONS
|
#endif // SIMDJSON_EXCEPTIONS
|
||||||
#endif // defined(__cpp_lib_ranges)
|
#endif // defined(__cpp_lib_ranges)
|
||||||
|
|
||||||
#endif // SIMDJSON_INLINE_OBJECT_H
|
#endif // SIMDJSON_OBJECT_INL_H
|
||||||
|
|||||||
@@ -1,21 +1,13 @@
|
|||||||
#ifndef SIMDJSON_DOM_OBJECT_H
|
#ifndef SIMDJSON_DOM_OBJECT_H
|
||||||
#define SIMDJSON_DOM_OBJECT_H
|
#define SIMDJSON_DOM_OBJECT_H
|
||||||
|
|
||||||
#include "simdjson/common_defs.h"
|
#include "simdjson/dom/base.h"
|
||||||
#include "simdjson/error.h"
|
#include "simdjson/dom/element.h"
|
||||||
#include "simdjson/internal/tape_ref.h"
|
#include "simdjson/internal/tape_ref.h"
|
||||||
|
|
||||||
namespace simdjson {
|
namespace simdjson {
|
||||||
namespace internal {
|
|
||||||
template<typename T>
|
|
||||||
class string_builder;
|
|
||||||
}
|
|
||||||
namespace dom {
|
namespace dom {
|
||||||
|
|
||||||
class document;
|
|
||||||
class element;
|
|
||||||
class key_value_pair;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JSON object.
|
* JSON object.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
#ifndef SIMDJSON_DOM_PARSEDJSON_H
|
#ifndef SIMDJSON_DOM_PARSEDJSON_H
|
||||||
#define SIMDJSON_DOM_PARSEDJSON_H
|
#define SIMDJSON_DOM_PARSEDJSON_H
|
||||||
|
|
||||||
#include "simdjson/dom/document.h"
|
#include "simdjson/dom/base.h"
|
||||||
|
|
||||||
namespace simdjson {
|
namespace simdjson {
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,17 @@
|
|||||||
#ifndef SIMDJSON_INLINE_PARSEDJSON_ITERATOR_H
|
#ifndef SIMDJSON_PARSEDJSON_ITERATOR_INL_H
|
||||||
#define SIMDJSON_INLINE_PARSEDJSON_ITERATOR_H
|
#define SIMDJSON_PARSEDJSON_ITERATOR_INL_H
|
||||||
|
|
||||||
|
#include "simdjson/dom/base.h"
|
||||||
#include "simdjson/dom/parsedjson_iterator.h"
|
#include "simdjson/dom/parsedjson_iterator.h"
|
||||||
#include "simdjson/portability.h"
|
#include "simdjson/internal/jsonformatutils.h"
|
||||||
|
|
||||||
|
#include "simdjson/dom/parser-inl.h"
|
||||||
|
#include "simdjson/internal/tape_ref-inl.h"
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <iterator>
|
||||||
|
#include <limits>
|
||||||
|
#include <ostream>
|
||||||
|
|
||||||
#ifndef SIMDJSON_DISABLE_DEPRECATED_API
|
#ifndef SIMDJSON_DISABLE_DEPRECATED_API
|
||||||
|
|
||||||
@@ -197,6 +205,12 @@ void dom::parser::Iterator::to_start_scope() {
|
|||||||
current_type = uint8_t(current_val >> 56);
|
current_type = uint8_t(current_val >> 56);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void dom::parser::Iterator::rewind() {
|
||||||
|
while (up())
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool dom::parser::Iterator::next() {
|
bool dom::parser::Iterator::next() {
|
||||||
size_t npos;
|
size_t npos;
|
||||||
if ((current_type == '[') || (current_type == '{')) {
|
if ((current_type == '[') || (current_type == '{')) {
|
||||||
@@ -365,6 +379,48 @@ bool dom::parser::Iterator::move_to(const char *pointer,
|
|||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool dom::parser::Iterator::move_to(const std::string &pointer) {
|
||||||
|
return move_to(pointer.c_str(), uint32_t(pointer.length()));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int64_t dom::parser::Iterator::get_integer() const {
|
||||||
|
if (location + 1 >= tape_length) {
|
||||||
|
return 0; // default value in case of error
|
||||||
|
}
|
||||||
|
return static_cast<int64_t>(doc.tape[location + 1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint64_t dom::parser::Iterator::get_unsigned_integer() const {
|
||||||
|
if (location + 1 >= tape_length) {
|
||||||
|
return 0; // default value in case of error
|
||||||
|
}
|
||||||
|
return doc.tape[location + 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const char * dom::parser::Iterator::get_string() const {
|
||||||
|
return reinterpret_cast<const char *>(
|
||||||
|
doc.string_buf.get() + (current_val & internal::JSON_VALUE_MASK) + sizeof(uint32_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint32_t dom::parser::Iterator::get_string_length() const {
|
||||||
|
uint32_t answer;
|
||||||
|
std::memcpy(&answer,
|
||||||
|
reinterpret_cast<const char *>(doc.string_buf.get() +
|
||||||
|
(current_val & internal::JSON_VALUE_MASK)),
|
||||||
|
sizeof(uint32_t));
|
||||||
|
return answer;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline double dom::parser::Iterator::get_double() const {
|
||||||
|
if (location + 1 >= tape_length) {
|
||||||
|
return std::numeric_limits<double>::quiet_NaN(); // default value in
|
||||||
|
// case of error
|
||||||
|
}
|
||||||
|
double answer;
|
||||||
|
std::memcpy(&answer, &doc.tape[location + 1], sizeof(answer));
|
||||||
|
return answer;
|
||||||
|
}
|
||||||
|
|
||||||
bool dom::parser::Iterator::relative_move_to(const char *pointer,
|
bool dom::parser::Iterator::relative_move_to(const char *pointer,
|
||||||
uint32_t length) {
|
uint32_t length) {
|
||||||
if (length == 0) {
|
if (length == 0) {
|
||||||
@@ -486,4 +542,4 @@ SIMDJSON_POP_DISABLE_WARNINGS
|
|||||||
#endif // SIMDJSON_DISABLE_DEPRECATED_API
|
#endif // SIMDJSON_DISABLE_DEPRECATED_API
|
||||||
|
|
||||||
|
|
||||||
#endif // SIMDJSON_INLINE_PARSEDJSON_ITERATOR_H
|
#endif // SIMDJSON_PARSEDJSON_ITERATOR_INL_H
|
||||||
|
|||||||
@@ -3,16 +3,8 @@
|
|||||||
#ifndef SIMDJSON_DOM_PARSEDJSON_ITERATOR_H
|
#ifndef SIMDJSON_DOM_PARSEDJSON_ITERATOR_H
|
||||||
#define SIMDJSON_DOM_PARSEDJSON_ITERATOR_H
|
#define SIMDJSON_DOM_PARSEDJSON_ITERATOR_H
|
||||||
|
|
||||||
#include <cstring>
|
#include "simdjson/dom/base.h"
|
||||||
#include <string>
|
#include "simdjson/dom/parser.h"
|
||||||
#include <ostream>
|
|
||||||
#include <iterator>
|
|
||||||
#include <limits>
|
|
||||||
#include <stdexcept>
|
|
||||||
|
|
||||||
#include "simdjson/dom/document.h"
|
|
||||||
#include "simdjson/dom/parsedjson.h"
|
|
||||||
#include "simdjson/internal/jsonformatutils.h"
|
|
||||||
|
|
||||||
#ifndef SIMDJSON_DISABLE_DEPRECATED_API
|
#ifndef SIMDJSON_DISABLE_DEPRECATED_API
|
||||||
|
|
||||||
@@ -52,51 +44,23 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// get the int64_t value at this node; valid only if get_type is "l"
|
// get the int64_t value at this node; valid only if get_type is "l"
|
||||||
inline int64_t get_integer() const {
|
inline int64_t get_integer() const;
|
||||||
if (location + 1 >= tape_length) {
|
|
||||||
return 0; // default value in case of error
|
|
||||||
}
|
|
||||||
return static_cast<int64_t>(doc.tape[location + 1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// get the value as uint64; valid only if if get_type is "u"
|
// get the value as uint64; valid only if if get_type is "u"
|
||||||
inline uint64_t get_unsigned_integer() const {
|
inline uint64_t get_unsigned_integer() const;
|
||||||
if (location + 1 >= tape_length) {
|
|
||||||
return 0; // default value in case of error
|
|
||||||
}
|
|
||||||
return doc.tape[location + 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
// get the string value at this node (NULL ended); valid only if get_type is "
|
// get the string value at this node (NULL ended); valid only if get_type is "
|
||||||
// note that tabs, and line endings are escaped in the returned value (see
|
// note that tabs, and line endings are escaped in the returned value (see
|
||||||
// print_with_escapes) return value is valid UTF-8, it may contain NULL chars
|
// print_with_escapes) return value is valid UTF-8, it may contain NULL chars
|
||||||
// within the string: get_string_length determines the true string length.
|
// within the string: get_string_length determines the true string length.
|
||||||
inline const char *get_string() const {
|
inline const char *get_string() const;
|
||||||
return reinterpret_cast<const char *>(
|
|
||||||
doc.string_buf.get() + (current_val & internal::JSON_VALUE_MASK) + sizeof(uint32_t));
|
|
||||||
}
|
|
||||||
|
|
||||||
// return the length of the string in bytes
|
// return the length of the string in bytes
|
||||||
inline uint32_t get_string_length() const {
|
inline uint32_t get_string_length() const;
|
||||||
uint32_t answer;
|
|
||||||
std::memcpy(&answer,
|
|
||||||
reinterpret_cast<const char *>(doc.string_buf.get() +
|
|
||||||
(current_val & internal::JSON_VALUE_MASK)),
|
|
||||||
sizeof(uint32_t));
|
|
||||||
return answer;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get the double value at this node; valid only if
|
// get the double value at this node; valid only if
|
||||||
// get_type() is "d"
|
// get_type() is "d"
|
||||||
inline double get_double() const {
|
inline double get_double() const;
|
||||||
if (location + 1 >= tape_length) {
|
|
||||||
return std::numeric_limits<double>::quiet_NaN(); // default value in
|
|
||||||
// case of error
|
|
||||||
}
|
|
||||||
double answer;
|
|
||||||
std::memcpy(&answer, &doc.tape[location + 1], sizeof(answer));
|
|
||||||
return answer;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool is_object_or_array() const { return is_object() || is_array(); }
|
inline bool is_object_or_array() const { return is_object() || is_array(); }
|
||||||
|
|
||||||
@@ -190,9 +154,7 @@ public:
|
|||||||
// "If a referenced member name is not unique in an object, the member that
|
// "If a referenced member name is not unique in an object, the member that
|
||||||
// is referenced is undefined, and evaluation fails". Here we just return
|
// is referenced is undefined, and evaluation fails". Here we just return
|
||||||
// the first corresponding value.
|
// the first corresponding value.
|
||||||
inline bool move_to(const std::string &pointer) {
|
inline bool move_to(const std::string &pointer);
|
||||||
return move_to(pointer.c_str(), uint32_t(pointer.length()));
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Almost the same as move_to(), except it searches from the current
|
// Almost the same as move_to(), except it searches from the current
|
||||||
@@ -240,10 +202,7 @@ public:
|
|||||||
// a scope is a series of nodes at the same level
|
// a scope is a series of nodes at the same level
|
||||||
inline void to_start_scope();
|
inline void to_start_scope();
|
||||||
|
|
||||||
inline void rewind() {
|
inline void rewind();
|
||||||
while (up())
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,18 @@
|
|||||||
#ifndef SIMDJSON_INLINE_PARSER_H
|
#ifndef SIMDJSON_PARSER_INL_H
|
||||||
#define SIMDJSON_INLINE_PARSER_H
|
#define SIMDJSON_PARSER_INL_H
|
||||||
|
|
||||||
|
#include "simdjson/dom/base.h"
|
||||||
#include "simdjson/dom/document_stream.h"
|
#include "simdjson/dom/document_stream.h"
|
||||||
#include "simdjson/dom/parser.h"
|
|
||||||
#include "simdjson/implementation.h"
|
#include "simdjson/implementation.h"
|
||||||
#include "simdjson/internal/jsonformatutils.h"
|
#include "simdjson/internal/dom_parser_implementation.h"
|
||||||
#include "simdjson/portability.h"
|
|
||||||
#include <cstdio>
|
#include "simdjson/error-inl.h"
|
||||||
|
#include "simdjson/padded_string-inl.h"
|
||||||
|
#include "simdjson/dom/document_stream-inl.h"
|
||||||
|
#include "simdjson/dom/element-inl.h"
|
||||||
|
|
||||||
#include <climits>
|
#include <climits>
|
||||||
|
#include <cstring> /* memcmp */
|
||||||
|
|
||||||
namespace simdjson {
|
namespace simdjson {
|
||||||
namespace dom {
|
namespace dom {
|
||||||
@@ -116,8 +121,14 @@ inline simdjson_result<element> parser::parse_into_document(document& provided_d
|
|||||||
_loaded_bytes_capacity = len;
|
_loaded_bytes_capacity = len;
|
||||||
}
|
}
|
||||||
std::memcpy(static_cast<void *>(loaded_bytes.get()), buf, len);
|
std::memcpy(static_cast<void *>(loaded_bytes.get()), buf, len);
|
||||||
|
buf = reinterpret_cast<const uint8_t*>(loaded_bytes.get());
|
||||||
}
|
}
|
||||||
_error = implementation->parse(realloc_if_needed ? reinterpret_cast<const uint8_t*>(loaded_bytes.get()): buf, len, provided_doc);
|
|
||||||
|
if((len >= 3) && (std::memcmp(buf, "\xEF\xBB\xBF", 3) == 0)) {
|
||||||
|
buf += 3;
|
||||||
|
len -= 3;
|
||||||
|
}
|
||||||
|
_error = implementation->parse(buf, len, provided_doc);
|
||||||
|
|
||||||
if (_error) { return _error; }
|
if (_error) { return _error; }
|
||||||
|
|
||||||
@@ -154,6 +165,10 @@ simdjson_inline simdjson_result<element> parser::parse(const padded_string_view
|
|||||||
|
|
||||||
inline simdjson_result<document_stream> parser::parse_many(const uint8_t *buf, size_t len, size_t batch_size) noexcept {
|
inline simdjson_result<document_stream> parser::parse_many(const uint8_t *buf, size_t len, size_t batch_size) noexcept {
|
||||||
if(batch_size < MINIMAL_BATCH_SIZE) { batch_size = MINIMAL_BATCH_SIZE; }
|
if(batch_size < MINIMAL_BATCH_SIZE) { batch_size = MINIMAL_BATCH_SIZE; }
|
||||||
|
if((len >= 3) && (std::memcmp(buf, "\xEF\xBB\xBF", 3) == 0)) {
|
||||||
|
buf += 3;
|
||||||
|
len -= 3;
|
||||||
|
}
|
||||||
return document_stream(*this, buf, len, batch_size);
|
return document_stream(*this, buf, len, batch_size);
|
||||||
}
|
}
|
||||||
inline simdjson_result<document_stream> parser::parse_many(const char *buf, size_t len, size_t batch_size) noexcept {
|
inline simdjson_result<document_stream> parser::parse_many(const char *buf, size_t len, size_t batch_size) noexcept {
|
||||||
@@ -236,4 +251,4 @@ simdjson_inline void parser::set_max_capacity(size_t max_capacity) noexcept {
|
|||||||
} // namespace dom
|
} // namespace dom
|
||||||
} // namespace simdjson
|
} // namespace simdjson
|
||||||
|
|
||||||
#endif // SIMDJSON_INLINE_PARSER_H
|
#endif // SIMDJSON_PARSER_INL_H
|
||||||
|
|||||||
@@ -1,41 +1,13 @@
|
|||||||
#ifndef SIMDJSON_DOM_PARSER_H
|
#ifndef SIMDJSON_DOM_PARSER_H
|
||||||
#define SIMDJSON_DOM_PARSER_H
|
#define SIMDJSON_DOM_PARSER_H
|
||||||
|
|
||||||
#include "simdjson/common_defs.h"
|
#include "simdjson/dom/base.h"
|
||||||
#include "simdjson/dom/document.h"
|
#include "simdjson/dom/document.h"
|
||||||
#include "simdjson/error.h"
|
|
||||||
#include "simdjson/internal/dom_parser_implementation.h"
|
|
||||||
#include "simdjson/internal/tape_ref.h"
|
|
||||||
#include "simdjson/padded_string.h"
|
|
||||||
#include "simdjson/portability.h"
|
|
||||||
#include <memory>
|
|
||||||
#include <ostream>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace simdjson {
|
namespace simdjson {
|
||||||
|
|
||||||
namespace dom {
|
namespace dom {
|
||||||
|
|
||||||
class document_stream;
|
|
||||||
class element;
|
|
||||||
|
|
||||||
/** The default batch size for parser.parse_many() and parser.load_many() */
|
|
||||||
static constexpr size_t DEFAULT_BATCH_SIZE = 1000000;
|
|
||||||
/**
|
|
||||||
* Some adversary might try to set the batch size to 0 or 1, which might cause problems.
|
|
||||||
* We set a minimum of 32B since anything else is highly likely to be an error. In practice,
|
|
||||||
* most users will want a much larger batch size.
|
|
||||||
*
|
|
||||||
* All non-negative MINIMAL_BATCH_SIZE values should be 'safe' except that, obviously, no JSON
|
|
||||||
* document can ever span 0 or 1 byte and that very large values would create memory allocation issues.
|
|
||||||
*/
|
|
||||||
static constexpr size_t MINIMAL_BATCH_SIZE = 32;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* It is wasteful to allocate memory for tiny documents (e.g., 4 bytes).
|
|
||||||
*/
|
|
||||||
static constexpr size_t MINIMAL_DOCUMENT_CAPACITY = 32;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A persistent document parser.
|
* A persistent document parser.
|
||||||
*
|
*
|
||||||
@@ -282,6 +254,8 @@ public:
|
|||||||
* And, possibly, no document many have been parsed when the `parser.load_many(path)` function
|
* And, possibly, no document many have been parsed when the `parser.load_many(path)` function
|
||||||
* returned.
|
* returned.
|
||||||
*
|
*
|
||||||
|
* If there is a UTF-8 BOM, the parser skips it.
|
||||||
|
*
|
||||||
* ### Format
|
* ### Format
|
||||||
*
|
*
|
||||||
* The file must contain a series of one or more JSON documents, concatenated into a single
|
* The file must contain a series of one or more JSON documents, concatenated into a single
|
||||||
@@ -374,6 +348,8 @@ public:
|
|||||||
* cout << std::string(doc["title"]) << endl;
|
* cout << std::string(doc["title"]) << endl;
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
|
* If there is a UTF-8 BOM, the parser skips it.
|
||||||
|
*
|
||||||
* ### Format
|
* ### Format
|
||||||
*
|
*
|
||||||
* The buffer must contain a series of one or more JSON documents, concatenated into a single
|
* The buffer must contain a series of one or more JSON documents, concatenated into a single
|
||||||
|
|||||||
@@ -2,10 +2,16 @@
|
|||||||
#ifndef SIMDJSON_SERIALIZATION_INL_H
|
#ifndef SIMDJSON_SERIALIZATION_INL_H
|
||||||
#define SIMDJSON_SERIALIZATION_INL_H
|
#define SIMDJSON_SERIALIZATION_INL_H
|
||||||
|
|
||||||
|
#include "simdjson/dom/base.h"
|
||||||
#include "simdjson/dom/serialization.h"
|
#include "simdjson/dom/serialization.h"
|
||||||
|
#include "simdjson/dom/parser.h"
|
||||||
|
#include "simdjson/internal/tape_type.h"
|
||||||
|
|
||||||
#include <cinttypes>
|
#include "simdjson/dom/array-inl.h"
|
||||||
#include <type_traits>
|
#include "simdjson/dom/object-inl.h"
|
||||||
|
#include "simdjson/internal/tape_ref-inl.h"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
namespace simdjson {
|
namespace simdjson {
|
||||||
namespace dom {
|
namespace dom {
|
||||||
@@ -17,12 +23,46 @@ inline bool parser::print_json(std::ostream &os) const noexcept {
|
|||||||
os << answer;
|
os << answer;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline std::ostream& operator<<(std::ostream& out, simdjson::dom::element value) {
|
||||||
|
simdjson::internal::string_builder<> sb;
|
||||||
|
sb.append(value);
|
||||||
|
return (out << sb.str());
|
||||||
}
|
}
|
||||||
|
#if SIMDJSON_EXCEPTIONS
|
||||||
|
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::dom::element> x) {
|
||||||
|
if (x.error()) { throw simdjson::simdjson_error(x.error()); }
|
||||||
|
return (out << x.value());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
inline std::ostream& operator<<(std::ostream& out, simdjson::dom::array value) {
|
||||||
|
simdjson::internal::string_builder<> sb;
|
||||||
|
sb.append(value);
|
||||||
|
return (out << sb.str());
|
||||||
|
}
|
||||||
|
#if SIMDJSON_EXCEPTIONS
|
||||||
|
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::dom::array> x) {
|
||||||
|
if (x.error()) { throw simdjson::simdjson_error(x.error()); }
|
||||||
|
return (out << x.value());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
inline std::ostream& operator<<(std::ostream& out, simdjson::dom::object value) {
|
||||||
|
simdjson::internal::string_builder<> sb;
|
||||||
|
sb.append(value);
|
||||||
|
return (out << sb.str());
|
||||||
|
}
|
||||||
|
#if SIMDJSON_EXCEPTIONS
|
||||||
|
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::dom::object> x) {
|
||||||
|
if (x.error()) { throw simdjson::simdjson_error(x.error()); }
|
||||||
|
return (out << x.value());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} // namespace dom
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* Number utility functions
|
* Number utility functions
|
||||||
**/
|
**/
|
||||||
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
/**@private
|
/**@private
|
||||||
* Escape sequence like \b or \u0001
|
* Escape sequence like \b or \u0001
|
||||||
@@ -41,7 +81,7 @@ struct escape_sequence {
|
|||||||
* adds the to_chars functions which would do as well, but
|
* adds the to_chars functions which would do as well, but
|
||||||
* we want to support C++11.
|
* we want to support C++11.
|
||||||
*/
|
*/
|
||||||
char *fast_itoa(char *output, int64_t value) noexcept {
|
static char *fast_itoa(char *output, int64_t value) noexcept {
|
||||||
// This is a standard implementation of itoa.
|
// This is a standard implementation of itoa.
|
||||||
char buffer[20];
|
char buffer[20];
|
||||||
uint64_t value_positive;
|
uint64_t value_positive;
|
||||||
@@ -83,7 +123,7 @@ char *fast_itoa(char *output, int64_t value) noexcept {
|
|||||||
* adds the to_chars functions which would do as well, but
|
* adds the to_chars functions which would do as well, but
|
||||||
* we want to support C++11.
|
* we want to support C++11.
|
||||||
*/
|
*/
|
||||||
char *fast_itoa(char *output, uint64_t value) noexcept {
|
static char *fast_itoa(char *output, uint64_t value) noexcept {
|
||||||
// This is a standard implementation of itoa.
|
// This is a standard implementation of itoa.
|
||||||
char buffer[20];
|
char buffer[20];
|
||||||
const char *const end_buffer = buffer + 20;
|
const char *const end_buffer = buffer + 20;
|
||||||
@@ -100,6 +140,8 @@ char *fast_itoa(char *output, uint64_t value) noexcept {
|
|||||||
std::memcpy(output, write_pointer, len);
|
std::memcpy(output, write_pointer, len);
|
||||||
return output + len;
|
return output + len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
@@ -107,19 +149,22 @@ namespace internal {
|
|||||||
* Minifier/formatter code.
|
* Minifier/formatter code.
|
||||||
**/
|
**/
|
||||||
|
|
||||||
simdjson_inline void mini_formatter::number(uint64_t x) {
|
template<class formatter>
|
||||||
|
simdjson_inline void base_formatter<formatter>::number(uint64_t x) {
|
||||||
char number_buffer[24];
|
char number_buffer[24];
|
||||||
char *newp = fast_itoa(number_buffer, x);
|
char *newp = fast_itoa(number_buffer, x);
|
||||||
buffer.insert(buffer.end(), number_buffer, newp);
|
buffer.insert(buffer.end(), number_buffer, newp);
|
||||||
}
|
}
|
||||||
|
|
||||||
simdjson_inline void mini_formatter::number(int64_t x) {
|
template<class formatter>
|
||||||
|
simdjson_inline void base_formatter<formatter>::number(int64_t x) {
|
||||||
char number_buffer[24];
|
char number_buffer[24];
|
||||||
char *newp = fast_itoa(number_buffer, x);
|
char *newp = fast_itoa(number_buffer, x);
|
||||||
buffer.insert(buffer.end(), number_buffer, newp);
|
buffer.insert(buffer.end(), number_buffer, newp);
|
||||||
}
|
}
|
||||||
|
|
||||||
simdjson_inline void mini_formatter::number(double x) {
|
template<class formatter>
|
||||||
|
simdjson_inline void base_formatter<formatter>::number(double x) {
|
||||||
char number_buffer[24];
|
char number_buffer[24];
|
||||||
// Currently, passing the nullptr to the second argument is
|
// Currently, passing the nullptr to the second argument is
|
||||||
// safe because our implementation does not check the second
|
// safe because our implementation does not check the second
|
||||||
@@ -128,31 +173,51 @@ simdjson_inline void mini_formatter::number(double x) {
|
|||||||
buffer.insert(buffer.end(), number_buffer, newp);
|
buffer.insert(buffer.end(), number_buffer, newp);
|
||||||
}
|
}
|
||||||
|
|
||||||
simdjson_inline void mini_formatter::start_array() { one_char('['); }
|
template<class formatter>
|
||||||
simdjson_inline void mini_formatter::end_array() { one_char(']'); }
|
simdjson_inline void base_formatter<formatter>::start_array() { one_char('['); }
|
||||||
simdjson_inline void mini_formatter::start_object() { one_char('{'); }
|
|
||||||
simdjson_inline void mini_formatter::end_object() { one_char('}'); }
|
|
||||||
simdjson_inline void mini_formatter::comma() { one_char(','); }
|
|
||||||
|
|
||||||
|
|
||||||
simdjson_inline void mini_formatter::true_atom() {
|
template<class formatter>
|
||||||
|
simdjson_inline void base_formatter<formatter>::end_array() { one_char(']'); }
|
||||||
|
|
||||||
|
template<class formatter>
|
||||||
|
simdjson_inline void base_formatter<formatter>::start_object() { one_char('{'); }
|
||||||
|
|
||||||
|
template<class formatter>
|
||||||
|
simdjson_inline void base_formatter<formatter>::end_object() { one_char('}'); }
|
||||||
|
|
||||||
|
template<class formatter>
|
||||||
|
simdjson_inline void base_formatter<formatter>::comma() { one_char(','); }
|
||||||
|
|
||||||
|
template<class formatter>
|
||||||
|
simdjson_inline void base_formatter<formatter>::true_atom() {
|
||||||
const char * s = "true";
|
const char * s = "true";
|
||||||
buffer.insert(buffer.end(), s, s + 4);
|
buffer.insert(buffer.end(), s, s + 4);
|
||||||
}
|
}
|
||||||
simdjson_inline void mini_formatter::false_atom() {
|
|
||||||
|
template<class formatter>
|
||||||
|
simdjson_inline void base_formatter<formatter>::false_atom() {
|
||||||
const char * s = "false";
|
const char * s = "false";
|
||||||
buffer.insert(buffer.end(), s, s + 5);
|
buffer.insert(buffer.end(), s, s + 5);
|
||||||
}
|
}
|
||||||
simdjson_inline void mini_formatter::null_atom() {
|
|
||||||
|
template<class formatter>
|
||||||
|
simdjson_inline void base_formatter<formatter>::null_atom() {
|
||||||
const char * s = "null";
|
const char * s = "null";
|
||||||
buffer.insert(buffer.end(), s, s + 4);
|
buffer.insert(buffer.end(), s, s + 4);
|
||||||
}
|
}
|
||||||
simdjson_inline void mini_formatter::one_char(char c) { buffer.push_back(c); }
|
|
||||||
simdjson_inline void mini_formatter::key(std::string_view unescaped) {
|
template<class formatter>
|
||||||
|
simdjson_inline void base_formatter<formatter>::one_char(char c) { buffer.push_back(c); }
|
||||||
|
|
||||||
|
template<class formatter>
|
||||||
|
simdjson_inline void base_formatter<formatter>::key(std::string_view unescaped) {
|
||||||
string(unescaped);
|
string(unescaped);
|
||||||
one_char(':');
|
one_char(':');
|
||||||
}
|
}
|
||||||
simdjson_inline void mini_formatter::string(std::string_view unescaped) {
|
|
||||||
|
template<class formatter>
|
||||||
|
simdjson_inline void base_formatter<formatter>::string(std::string_view unescaped) {
|
||||||
one_char('\"');
|
one_char('\"');
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
// Fast path for the case where we have no control character, no ", and no backslash.
|
// Fast path for the case where we have no control character, no ", and no backslash.
|
||||||
@@ -231,14 +296,46 @@ simdjson_inline void mini_formatter::string(std::string_view unescaped) {
|
|||||||
one_char('\"');
|
one_char('\"');
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void mini_formatter::clear() {
|
|
||||||
|
template<class formatter>
|
||||||
|
inline void base_formatter<formatter>::clear() {
|
||||||
buffer.clear();
|
buffer.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
simdjson_inline std::string_view mini_formatter::str() const {
|
template<class formatter>
|
||||||
|
simdjson_inline std::string_view base_formatter<formatter>::str() const {
|
||||||
return std::string_view(buffer.data(), buffer.size());
|
return std::string_view(buffer.data(), buffer.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
simdjson_inline void mini_formatter::print_newline() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
simdjson_inline void mini_formatter::print_indents(size_t depth) {
|
||||||
|
(void)depth;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
simdjson_inline void mini_formatter::print_space() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
simdjson_inline void pretty_formatter::print_newline() {
|
||||||
|
one_char('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
simdjson_inline void pretty_formatter::print_indents(size_t depth) {
|
||||||
|
if(this->indent_step <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for(size_t i = 0; i < this->indent_step * depth; i++) {
|
||||||
|
one_char(' ');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
simdjson_inline void pretty_formatter::print_space() {
|
||||||
|
one_char(' ');
|
||||||
|
}
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* String building code.
|
* String building code.
|
||||||
@@ -258,11 +355,16 @@ inline void string_builder<serializer>::append(simdjson::dom::element value) {
|
|||||||
// print commas after each value
|
// print commas after each value
|
||||||
if (after_value) {
|
if (after_value) {
|
||||||
format.comma();
|
format.comma();
|
||||||
|
format.print_newline();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
format.print_indents(depth);
|
||||||
|
|
||||||
// If we are in an object, print the next key and :, and skip to the next
|
// If we are in an object, print the next key and :, and skip to the next
|
||||||
// value.
|
// value.
|
||||||
if (is_object[depth]) {
|
if (is_object[depth]) {
|
||||||
format.key(iter.get_string_view());
|
format.key(iter.get_string_view());
|
||||||
|
format.print_space();
|
||||||
iter.json_index++;
|
iter.json_index++;
|
||||||
}
|
}
|
||||||
switch (iter.tape_ref_type()) {
|
switch (iter.tape_ref_type()) {
|
||||||
@@ -291,6 +393,7 @@ inline void string_builder<serializer>::append(simdjson::dom::element value) {
|
|||||||
|
|
||||||
is_object[depth] = false;
|
is_object[depth] = false;
|
||||||
after_value = false;
|
after_value = false;
|
||||||
|
format.print_newline();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -318,6 +421,7 @@ inline void string_builder<serializer>::append(simdjson::dom::element value) {
|
|||||||
|
|
||||||
is_object[depth] = true;
|
is_object[depth] = true;
|
||||||
after_value = false;
|
after_value = false;
|
||||||
|
format.print_newline();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -362,17 +466,21 @@ inline void string_builder<serializer>::append(simdjson::dom::element value) {
|
|||||||
// Handle multiple ends in a row
|
// Handle multiple ends in a row
|
||||||
while (depth != 0 && (iter.tape_ref_type() == tape_type::END_ARRAY ||
|
while (depth != 0 && (iter.tape_ref_type() == tape_type::END_ARRAY ||
|
||||||
iter.tape_ref_type() == tape_type::END_OBJECT)) {
|
iter.tape_ref_type() == tape_type::END_OBJECT)) {
|
||||||
|
format.print_newline();
|
||||||
|
depth--;
|
||||||
|
format.print_indents(depth);
|
||||||
if (iter.tape_ref_type() == tape_type::END_ARRAY) {
|
if (iter.tape_ref_type() == tape_type::END_ARRAY) {
|
||||||
format.end_array();
|
format.end_array();
|
||||||
} else {
|
} else {
|
||||||
format.end_object();
|
format.end_object();
|
||||||
}
|
}
|
||||||
depth--;
|
|
||||||
iter.json_index++;
|
iter.json_index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stop when we're at depth 0
|
// Stop when we're at depth 0
|
||||||
} while (depth != 0);
|
} while (depth != 0);
|
||||||
|
|
||||||
|
format.print_newline();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class serializer>
|
template <class serializer>
|
||||||
|
|||||||
@@ -1,13 +1,10 @@
|
|||||||
#ifndef SIMDJSON_SERIALIZATION_H
|
#ifndef SIMDJSON_SERIALIZATION_H
|
||||||
#define SIMDJSON_SERIALIZATION_H
|
#define SIMDJSON_SERIALIZATION_H
|
||||||
|
|
||||||
#include "simdjson/common_defs.h"
|
#include "simdjson/dom/base.h"
|
||||||
#include "simdjson/dom/document.h"
|
#include "simdjson/dom/element.h"
|
||||||
#include "simdjson/error.h"
|
#include "simdjson/dom/object.h"
|
||||||
#include "simdjson/internal/dom_parser_implementation.h"
|
|
||||||
#include "simdjson/internal/tape_ref.h"
|
|
||||||
#include "simdjson/padded_string.h"
|
|
||||||
#include "simdjson/portability.h"
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace simdjson {
|
namespace simdjson {
|
||||||
@@ -19,7 +16,90 @@ namespace simdjson {
|
|||||||
*/
|
*/
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
class mini_formatter;
|
template<class formatter>
|
||||||
|
class base_formatter {
|
||||||
|
public:
|
||||||
|
/** Add a comma **/
|
||||||
|
simdjson_inline void comma();
|
||||||
|
/** Start an array, prints [ **/
|
||||||
|
simdjson_inline void start_array();
|
||||||
|
/** End an array, prints ] **/
|
||||||
|
simdjson_inline void end_array();
|
||||||
|
/** Start an array, prints { **/
|
||||||
|
simdjson_inline void start_object();
|
||||||
|
/** Start an array, prints } **/
|
||||||
|
simdjson_inline void end_object();
|
||||||
|
/** Prints a true **/
|
||||||
|
simdjson_inline void true_atom();
|
||||||
|
/** Prints a false **/
|
||||||
|
simdjson_inline void false_atom();
|
||||||
|
/** Prints a null **/
|
||||||
|
simdjson_inline void null_atom();
|
||||||
|
/** Prints a number **/
|
||||||
|
simdjson_inline void number(int64_t x);
|
||||||
|
/** Prints a number **/
|
||||||
|
simdjson_inline void number(uint64_t x);
|
||||||
|
/** Prints a number **/
|
||||||
|
simdjson_inline void number(double x);
|
||||||
|
/** Prints a key (string + colon) **/
|
||||||
|
simdjson_inline void key(std::string_view unescaped);
|
||||||
|
/** Prints a string. The string is escaped as needed. **/
|
||||||
|
simdjson_inline void string(std::string_view unescaped);
|
||||||
|
/** Clears out the content. **/
|
||||||
|
simdjson_inline void clear();
|
||||||
|
/**
|
||||||
|
* Get access to the buffer, it is owned by the instance, but
|
||||||
|
* the user can make a copy.
|
||||||
|
**/
|
||||||
|
simdjson_inline std::string_view str() const;
|
||||||
|
|
||||||
|
/** Prints one character **/
|
||||||
|
simdjson_inline void one_char(char c);
|
||||||
|
|
||||||
|
simdjson_inline void call_print_newline() {
|
||||||
|
this->print_newline();
|
||||||
|
}
|
||||||
|
|
||||||
|
simdjson_inline void call_print_indents(size_t depth) {
|
||||||
|
this->print_indents(depth);
|
||||||
|
}
|
||||||
|
|
||||||
|
simdjson_inline void call_print_space() {
|
||||||
|
this->print_space();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// implementation details (subject to change)
|
||||||
|
/** Backing buffer **/
|
||||||
|
std::vector<char> buffer{}; // not ideal!
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private This is the class that we expect to use with the string_builder
|
||||||
|
* template. It tries to produce a compact version of the JSON element
|
||||||
|
* as quickly as possible.
|
||||||
|
*/
|
||||||
|
class mini_formatter : public base_formatter<mini_formatter> {
|
||||||
|
public:
|
||||||
|
simdjson_inline void print_newline();
|
||||||
|
|
||||||
|
simdjson_inline void print_indents(size_t depth);
|
||||||
|
|
||||||
|
simdjson_inline void print_space();
|
||||||
|
};
|
||||||
|
|
||||||
|
class pretty_formatter : public base_formatter<pretty_formatter> {
|
||||||
|
public:
|
||||||
|
simdjson_inline void print_newline();
|
||||||
|
|
||||||
|
simdjson_inline void print_indents(size_t depth);
|
||||||
|
|
||||||
|
simdjson_inline void print_space();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
int indent_step = 4;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private The string_builder template allows us to construct
|
* @private The string_builder template allows us to construct
|
||||||
@@ -55,56 +135,6 @@ private:
|
|||||||
formatter format{};
|
formatter format{};
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* @private This is the class that we expect to use with the string_builder
|
|
||||||
* template. It tries to produce a compact version of the JSON element
|
|
||||||
* as quickly as possible.
|
|
||||||
*/
|
|
||||||
class mini_formatter {
|
|
||||||
public:
|
|
||||||
mini_formatter() = default;
|
|
||||||
/** Add a comma **/
|
|
||||||
simdjson_inline void comma();
|
|
||||||
/** Start an array, prints [ **/
|
|
||||||
simdjson_inline void start_array();
|
|
||||||
/** End an array, prints ] **/
|
|
||||||
simdjson_inline void end_array();
|
|
||||||
/** Start an array, prints { **/
|
|
||||||
simdjson_inline void start_object();
|
|
||||||
/** Start an array, prints } **/
|
|
||||||
simdjson_inline void end_object();
|
|
||||||
/** Prints a true **/
|
|
||||||
simdjson_inline void true_atom();
|
|
||||||
/** Prints a false **/
|
|
||||||
simdjson_inline void false_atom();
|
|
||||||
/** Prints a null **/
|
|
||||||
simdjson_inline void null_atom();
|
|
||||||
/** Prints a number **/
|
|
||||||
simdjson_inline void number(int64_t x);
|
|
||||||
/** Prints a number **/
|
|
||||||
simdjson_inline void number(uint64_t x);
|
|
||||||
/** Prints a number **/
|
|
||||||
simdjson_inline void number(double x);
|
|
||||||
/** Prints a key (string + colon) **/
|
|
||||||
simdjson_inline void key(std::string_view unescaped);
|
|
||||||
/** Prints a string. The string is escaped as needed. **/
|
|
||||||
simdjson_inline void string(std::string_view unescaped);
|
|
||||||
/** Clears out the content. **/
|
|
||||||
simdjson_inline void clear();
|
|
||||||
/**
|
|
||||||
* Get access to the buffer, it is owned by the instance, but
|
|
||||||
* the user can make a copy.
|
|
||||||
**/
|
|
||||||
simdjson_inline std::string_view str() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
// implementation details (subject to change)
|
|
||||||
/** Prints one character **/
|
|
||||||
simdjson_inline void one_char(char c);
|
|
||||||
/** Backing buffer **/
|
|
||||||
std::vector<char> buffer{}; // not ideal!
|
|
||||||
};
|
|
||||||
|
|
||||||
} // internal
|
} // internal
|
||||||
|
|
||||||
namespace dom {
|
namespace dom {
|
||||||
@@ -116,16 +146,9 @@ namespace dom {
|
|||||||
* @param value The element.
|
* @param value The element.
|
||||||
* @throw if there is an error with the underlying output stream. simdjson itself will not throw.
|
* @throw if there is an error with the underlying output stream. simdjson itself will not throw.
|
||||||
*/
|
*/
|
||||||
inline std::ostream& operator<<(std::ostream& out, simdjson::dom::element value) {
|
inline std::ostream& operator<<(std::ostream& out, simdjson::dom::element value);
|
||||||
simdjson::internal::string_builder<> sb;
|
|
||||||
sb.append(value);
|
|
||||||
return (out << sb.str());
|
|
||||||
}
|
|
||||||
#if SIMDJSON_EXCEPTIONS
|
#if SIMDJSON_EXCEPTIONS
|
||||||
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::dom::element> x) {
|
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::dom::element> x);
|
||||||
if (x.error()) { throw simdjson::simdjson_error(x.error()); }
|
|
||||||
return (out << x.value());
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
/**
|
/**
|
||||||
* Print JSON to an output stream.
|
* Print JSON to an output stream.
|
||||||
@@ -134,16 +157,9 @@ inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<sim
|
|||||||
* @param value The array.
|
* @param value The array.
|
||||||
* @throw if there is an error with the underlying output stream. simdjson itself will not throw.
|
* @throw if there is an error with the underlying output stream. simdjson itself will not throw.
|
||||||
*/
|
*/
|
||||||
inline std::ostream& operator<<(std::ostream& out, simdjson::dom::array value) {
|
inline std::ostream& operator<<(std::ostream& out, simdjson::dom::array value);
|
||||||
simdjson::internal::string_builder<> sb;
|
|
||||||
sb.append(value);
|
|
||||||
return (out << sb.str());
|
|
||||||
}
|
|
||||||
#if SIMDJSON_EXCEPTIONS
|
#if SIMDJSON_EXCEPTIONS
|
||||||
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::dom::array> x) {
|
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::dom::array> x);
|
||||||
if (x.error()) { throw simdjson::simdjson_error(x.error()); }
|
|
||||||
return (out << x.value());
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
/**
|
/**
|
||||||
* Print JSON to an output stream.
|
* Print JSON to an output stream.
|
||||||
@@ -152,16 +168,9 @@ inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<sim
|
|||||||
* @param value The object.
|
* @param value The object.
|
||||||
* @throw if there is an error with the underlying output stream. simdjson itself will not throw.
|
* @throw if there is an error with the underlying output stream. simdjson itself will not throw.
|
||||||
*/
|
*/
|
||||||
inline std::ostream& operator<<(std::ostream& out, simdjson::dom::object value) {
|
inline std::ostream& operator<<(std::ostream& out, simdjson::dom::object value);
|
||||||
simdjson::internal::string_builder<> sb;
|
|
||||||
sb.append(value);
|
|
||||||
return (out << sb.str());
|
|
||||||
}
|
|
||||||
#if SIMDJSON_EXCEPTIONS
|
#if SIMDJSON_EXCEPTIONS
|
||||||
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::dom::object> x) {
|
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::dom::object> x);
|
||||||
if (x.error()) { throw simdjson::simdjson_error(x.error()); }
|
|
||||||
return (out << x.value());
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
|
|
||||||
@@ -212,6 +221,38 @@ std::string minify(simdjson_result<T> x) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prettifies a JSON element or document, printing the valid JSON with indentation.
|
||||||
|
*
|
||||||
|
* dom::parser parser;
|
||||||
|
* element doc = parser.parse(" [ 1 , 2 , 3 ] "_padded);
|
||||||
|
*
|
||||||
|
* // Prints:
|
||||||
|
* // {
|
||||||
|
* // [
|
||||||
|
* // 1,
|
||||||
|
* // 2,
|
||||||
|
* // 3
|
||||||
|
* // ]
|
||||||
|
* // }
|
||||||
|
* cout << prettify(doc) << endl;
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
template <class T>
|
||||||
|
std::string prettify(T x) {
|
||||||
|
simdjson::internal::string_builder<simdjson::internal::pretty_formatter> sb;
|
||||||
|
sb.append(x);
|
||||||
|
std::string_view answer = sb.str();
|
||||||
|
return std::string(answer.data(), answer.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
#if SIMDJSON_EXCEPTIONS
|
||||||
|
template <class T>
|
||||||
|
std::string prettify(simdjson_result<T> x) {
|
||||||
|
if (x.error()) { throw simdjson_error(x.error()); }
|
||||||
|
return to_string(x.value());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
} // namespace simdjson
|
} // namespace simdjson
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
#ifndef SIMDJSON_INLINE_ERROR_H
|
#ifndef SIMDJSON_ERROR_INL_H
|
||||||
#define SIMDJSON_INLINE_ERROR_H
|
#define SIMDJSON_ERROR_INL_H
|
||||||
|
|
||||||
#include <cstring>
|
|
||||||
#include <string>
|
|
||||||
#include <utility>
|
|
||||||
#include "simdjson/error.h"
|
#include "simdjson/error.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
namespace simdjson {
|
namespace simdjson {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
// We store the error code so we can validate the error message is associated with the right code
|
// We store the error code so we can validate the error message is associated with the right code
|
||||||
@@ -182,4 +181,4 @@ simdjson_inline simdjson_result<T>::simdjson_result() noexcept
|
|||||||
|
|
||||||
} // namespace simdjson
|
} // namespace simdjson
|
||||||
|
|
||||||
#endif // SIMDJSON_INLINE_ERROR_H
|
#endif // SIMDJSON_ERROR_INL_H
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
#ifndef SIMDJSON_ERROR_H
|
#ifndef SIMDJSON_ERROR_H
|
||||||
#define SIMDJSON_ERROR_H
|
#define SIMDJSON_ERROR_H
|
||||||
|
|
||||||
#include "simdjson/common_defs.h"
|
#include "simdjson/base.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <ostream>
|
||||||
|
|
||||||
namespace simdjson {
|
namespace simdjson {
|
||||||
|
|
||||||
@@ -40,7 +42,7 @@ enum error_code {
|
|||||||
INVALID_URI_FRAGMENT, ///< Invalid URI fragment
|
INVALID_URI_FRAGMENT, ///< Invalid URI fragment
|
||||||
UNEXPECTED_ERROR, ///< indicative of a bug in simdjson
|
UNEXPECTED_ERROR, ///< indicative of a bug in simdjson
|
||||||
PARSER_IN_USE, ///< parser is already in use.
|
PARSER_IN_USE, ///< parser is already in use.
|
||||||
OUT_OF_ORDER_ITERATION, ///< tried to iterate an array or object out of order
|
OUT_OF_ORDER_ITERATION, ///< tried to iterate an array or object out of order (checked when SIMDJSON_DEVELOPMENT_CHECKS=1)
|
||||||
INSUFFICIENT_PADDING, ///< The JSON doesn't have enough padding for simdjson to safely parse it.
|
INSUFFICIENT_PADDING, ///< The JSON doesn't have enough padding for simdjson to safely parse it.
|
||||||
INCOMPLETE_ARRAY_OR_OBJECT, ///< The document ends early.
|
INCOMPLETE_ARRAY_OR_OBJECT, ///< The document ends early.
|
||||||
SCALAR_DOCUMENT_AS_VALUE, ///< A scalar document is treated as a value.
|
SCALAR_DOCUMENT_AS_VALUE, ///< A scalar document is treated as a value.
|
||||||
@@ -49,6 +51,13 @@ enum error_code {
|
|||||||
NUM_ERROR_CODES
|
NUM_ERROR_CODES
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* It is the convention throughout the code that the macro SIMDJSON_DEVELOPMENT_CHECKS determines whether
|
||||||
|
* we check for OUT_OF_ORDER_ITERATION. The logic behind it is that these errors only occurs when the code
|
||||||
|
* that was written while breaking some simdjson::ondemand requirement. They should not occur in released
|
||||||
|
* code after these issues were fixed.
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the error message for the given error code.
|
* Get the error message for the given error code.
|
||||||
*
|
*
|
||||||
@@ -208,11 +217,11 @@ struct simdjson_result : public internal::simdjson_result_base<T> {
|
|||||||
*/
|
*/
|
||||||
simdjson_inline simdjson_result() noexcept;
|
simdjson_inline simdjson_result() noexcept;
|
||||||
/**
|
/**
|
||||||
* @private Create a new error result.
|
* @private Create a new successful result.
|
||||||
*/
|
*/
|
||||||
simdjson_inline simdjson_result(T &&value) noexcept;
|
simdjson_inline simdjson_result(T &&value) noexcept;
|
||||||
/**
|
/**
|
||||||
* @private Create a new successful result.
|
* @private Create a new error result.
|
||||||
*/
|
*/
|
||||||
simdjson_inline simdjson_result(error_code error_code) noexcept;
|
simdjson_inline simdjson_result(error_code error_code) noexcept;
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,30 +1,8 @@
|
|||||||
#ifndef SIMDJSON_FALLBACK_H
|
#ifndef SIMDJSON_FALLBACK_H
|
||||||
#define SIMDJSON_FALLBACK_H
|
#define SIMDJSON_FALLBACK_H
|
||||||
|
|
||||||
#include "simdjson/implementation-base.h"
|
|
||||||
|
|
||||||
#if SIMDJSON_IMPLEMENTATION_FALLBACK
|
|
||||||
|
|
||||||
namespace simdjson {
|
|
||||||
/**
|
|
||||||
* Fallback implementation (runs on any machine).
|
|
||||||
*/
|
|
||||||
namespace fallback {
|
|
||||||
} // namespace fallback
|
|
||||||
} // namespace simdjson
|
|
||||||
|
|
||||||
#include "simdjson/fallback/implementation.h"
|
|
||||||
|
|
||||||
#include "simdjson/fallback/begin.h"
|
#include "simdjson/fallback/begin.h"
|
||||||
|
#include "simdjson/generic/amalgamated.h"
|
||||||
// Declarations
|
|
||||||
#include "simdjson/generic/dom_parser_implementation.h"
|
|
||||||
#include "simdjson/fallback/bitmanipulation.h"
|
|
||||||
#include "simdjson/generic/jsoncharutils.h"
|
|
||||||
#include "simdjson/generic/atomparsing.h"
|
|
||||||
#include "simdjson/fallback/stringparsing.h"
|
|
||||||
#include "simdjson/fallback/numberparsing.h"
|
|
||||||
#include "simdjson/fallback/end.h"
|
#include "simdjson/fallback/end.h"
|
||||||
|
|
||||||
#endif // SIMDJSON_IMPLEMENTATION_FALLBACK
|
#endif // SIMDJSON_FALLBACK_H
|
||||||
#endif // SIMDJSON_FALLBACK_H
|
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
#ifndef SIMDJSON_FALLBACK_BASE_H
|
||||||
|
#define SIMDJSON_FALLBACK_BASE_H
|
||||||
|
|
||||||
|
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
#include "simdjson/base.h"
|
||||||
|
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
|
||||||
|
namespace simdjson {
|
||||||
|
/**
|
||||||
|
* Fallback implementation (runs on any machine).
|
||||||
|
*/
|
||||||
|
namespace fallback {
|
||||||
|
|
||||||
|
class implementation;
|
||||||
|
|
||||||
|
} // namespace fallback
|
||||||
|
} // namespace simdjson
|
||||||
|
|
||||||
|
#endif // SIMDJSON_FALLBACK_BASE_H
|
||||||
@@ -1 +1,5 @@
|
|||||||
#define SIMDJSON_IMPLEMENTATION fallback
|
#define SIMDJSON_IMPLEMENTATION fallback
|
||||||
|
#include "simdjson/fallback/base.h"
|
||||||
|
#include "simdjson/fallback/bitmanipulation.h"
|
||||||
|
#include "simdjson/fallback/stringparsing_defs.h"
|
||||||
|
#include "simdjson/fallback/numberparsing_defs.h"
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
#ifndef SIMDJSON_FALLBACK_BITMANIPULATION_H
|
#ifndef SIMDJSON_FALLBACK_BITMANIPULATION_H
|
||||||
#define SIMDJSON_FALLBACK_BITMANIPULATION_H
|
#define SIMDJSON_FALLBACK_BITMANIPULATION_H
|
||||||
|
|
||||||
#include "simdjson/base.h"
|
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
#include <limits>
|
#include "simdjson/fallback/base.h"
|
||||||
|
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
|
||||||
namespace simdjson {
|
namespace simdjson {
|
||||||
namespace SIMDJSON_IMPLEMENTATION {
|
namespace fallback {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
#if defined(_MSC_VER) && !defined(_M_ARM64) && !defined(_M_X64)
|
#if defined(_MSC_VER) && !defined(_M_ARM64) && !defined(_M_X64)
|
||||||
@@ -41,7 +42,7 @@ simdjson_inline int leading_zeroes(uint64_t input_num) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
} // unnamed namespace
|
} // unnamed namespace
|
||||||
} // namespace SIMDJSON_IMPLEMENTATION
|
} // namespace fallback
|
||||||
} // namespace simdjson
|
} // namespace simdjson
|
||||||
|
|
||||||
#endif // SIMDJSON_FALLBACK_BITMANIPULATION_H
|
#endif // SIMDJSON_FALLBACK_BITMANIPULATION_H
|
||||||
|
|||||||
@@ -1 +1,5 @@
|
|||||||
|
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
#include "simdjson/fallback/base.h"
|
||||||
|
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
|
||||||
#undef SIMDJSON_IMPLEMENTATION
|
#undef SIMDJSON_IMPLEMENTATION
|
||||||
|
|||||||
@@ -1,16 +1,14 @@
|
|||||||
#ifndef SIMDJSON_FALLBACK_IMPLEMENTATION_H
|
#ifndef SIMDJSON_FALLBACK_IMPLEMENTATION_H
|
||||||
#define SIMDJSON_FALLBACK_IMPLEMENTATION_H
|
#define SIMDJSON_FALLBACK_IMPLEMENTATION_H
|
||||||
|
|
||||||
|
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
#include "simdjson/fallback/base.h"
|
||||||
#include "simdjson/implementation.h"
|
#include "simdjson/implementation.h"
|
||||||
|
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
|
||||||
namespace simdjson {
|
namespace simdjson {
|
||||||
namespace fallback {
|
namespace fallback {
|
||||||
|
|
||||||
namespace {
|
|
||||||
using namespace simdjson;
|
|
||||||
using namespace simdjson::dom;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
@@ -24,7 +22,7 @@ public:
|
|||||||
simdjson_warn_unused error_code create_dom_parser_implementation(
|
simdjson_warn_unused error_code create_dom_parser_implementation(
|
||||||
size_t capacity,
|
size_t capacity,
|
||||||
size_t max_length,
|
size_t max_length,
|
||||||
std::unique_ptr<internal::dom_parser_implementation>& dst
|
std::unique_ptr<simdjson::internal::dom_parser_implementation>& dst
|
||||||
) const noexcept final;
|
) const noexcept final;
|
||||||
simdjson_warn_unused error_code minify(const uint8_t *buf, size_t len, uint8_t *dst, size_t &dst_len) const noexcept final;
|
simdjson_warn_unused error_code minify(const uint8_t *buf, size_t len, uint8_t *dst, size_t &dst_len) const noexcept final;
|
||||||
simdjson_warn_unused bool validate_utf8(const char *buf, size_t len) const noexcept final;
|
simdjson_warn_unused bool validate_utf8(const char *buf, size_t len) const noexcept final;
|
||||||
|
|||||||
@@ -1,36 +0,0 @@
|
|||||||
#ifndef SIMDJSON_FALLBACK_NUMBERPARSING_H
|
|
||||||
#define SIMDJSON_FALLBACK_NUMBERPARSING_H
|
|
||||||
|
|
||||||
#ifdef JSON_TEST_NUMBERS // for unit testing
|
|
||||||
void found_invalid_number(const uint8_t *buf);
|
|
||||||
void found_integer(int64_t result, const uint8_t *buf);
|
|
||||||
void found_unsigned_integer(uint64_t result, const uint8_t *buf);
|
|
||||||
void found_float(double result, const uint8_t *buf);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace simdjson {
|
|
||||||
namespace SIMDJSON_IMPLEMENTATION {
|
|
||||||
namespace numberparsing {
|
|
||||||
// credit: https://johnnylee-sde.github.io/Fast-numeric-string-to-int/
|
|
||||||
/** @private */
|
|
||||||
static simdjson_inline uint32_t parse_eight_digits_unrolled(const char *chars) {
|
|
||||||
uint64_t val;
|
|
||||||
memcpy(&val, chars, sizeof(uint64_t));
|
|
||||||
val = (val & 0x0F0F0F0F0F0F0F0F) * 2561 >> 8;
|
|
||||||
val = (val & 0x00FF00FF00FF00FF) * 6553601 >> 16;
|
|
||||||
return uint32_t((val & 0x0000FFFF0000FFFF) * 42949672960001 >> 32);
|
|
||||||
}
|
|
||||||
/** @private */
|
|
||||||
static simdjson_inline uint32_t parse_eight_digits_unrolled(const uint8_t *chars) {
|
|
||||||
return parse_eight_digits_unrolled(reinterpret_cast<const char *>(chars));
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace numberparsing
|
|
||||||
} // namespace SIMDJSON_IMPLEMENTATION
|
|
||||||
} // namespace simdjson
|
|
||||||
|
|
||||||
#define SIMDJSON_SWAR_NUMBER_PARSING 1
|
|
||||||
|
|
||||||
#include "simdjson/generic/numberparsing.h"
|
|
||||||
|
|
||||||
#endif // SIMDJSON_FALLBACK_NUMBERPARSING_H
|
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
#ifndef SIMDJSON_FALLBACK_NUMBERPARSING_DEFS_H
|
||||||
|
#define SIMDJSON_FALLBACK_NUMBERPARSING_DEFS_H
|
||||||
|
|
||||||
|
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
#include "simdjson/fallback/base.h"
|
||||||
|
#include "simdjson/internal/numberparsing_tables.h"
|
||||||
|
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
#ifdef JSON_TEST_NUMBERS // for unit testing
|
||||||
|
void found_invalid_number(const uint8_t *buf);
|
||||||
|
void found_integer(int64_t result, const uint8_t *buf);
|
||||||
|
void found_unsigned_integer(uint64_t result, const uint8_t *buf);
|
||||||
|
void found_float(double result, const uint8_t *buf);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace simdjson {
|
||||||
|
namespace fallback {
|
||||||
|
namespace numberparsing {
|
||||||
|
|
||||||
|
// credit: https://johnnylee-sde.github.io/Fast-numeric-string-to-int/
|
||||||
|
/** @private */
|
||||||
|
static simdjson_inline uint32_t parse_eight_digits_unrolled(const char *chars) {
|
||||||
|
uint64_t val;
|
||||||
|
memcpy(&val, chars, sizeof(uint64_t));
|
||||||
|
val = (val & 0x0F0F0F0F0F0F0F0F) * 2561 >> 8;
|
||||||
|
val = (val & 0x00FF00FF00FF00FF) * 6553601 >> 16;
|
||||||
|
return uint32_t((val & 0x0000FFFF0000FFFF) * 42949672960001 >> 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @private */
|
||||||
|
static simdjson_inline uint32_t parse_eight_digits_unrolled(const uint8_t *chars) {
|
||||||
|
return parse_eight_digits_unrolled(reinterpret_cast<const char *>(chars));
|
||||||
|
}
|
||||||
|
|
||||||
|
#if SIMDJSON_IS_32BITS // _umul128 for x86, arm
|
||||||
|
// this is a slow emulation routine for 32-bit
|
||||||
|
//
|
||||||
|
static simdjson_inline uint64_t __emulu(uint32_t x, uint32_t y) {
|
||||||
|
return x * (uint64_t)y;
|
||||||
|
}
|
||||||
|
static simdjson_inline uint64_t _umul128(uint64_t ab, uint64_t cd, uint64_t *hi) {
|
||||||
|
uint64_t ad = __emulu((uint32_t)(ab >> 32), (uint32_t)cd);
|
||||||
|
uint64_t bd = __emulu((uint32_t)ab, (uint32_t)cd);
|
||||||
|
uint64_t adbc = ad + __emulu((uint32_t)ab, (uint32_t)(cd >> 32));
|
||||||
|
uint64_t adbc_carry = !!(adbc < ad);
|
||||||
|
uint64_t lo = bd + (adbc << 32);
|
||||||
|
*hi = __emulu((uint32_t)(ab >> 32), (uint32_t)(cd >> 32)) + (adbc >> 32) +
|
||||||
|
(adbc_carry << 32) + !!(lo < bd);
|
||||||
|
return lo;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** @private */
|
||||||
|
simdjson_inline internal::value128 full_multiplication(uint64_t value1, uint64_t value2) {
|
||||||
|
internal::value128 answer;
|
||||||
|
#if SIMDJSON_REGULAR_VISUAL_STUDIO || SIMDJSON_IS_32BITS
|
||||||
|
#ifdef _M_ARM64
|
||||||
|
// ARM64 has native support for 64-bit multiplications, no need to emultate
|
||||||
|
answer.high = __umulh(value1, value2);
|
||||||
|
answer.low = value1 * value2;
|
||||||
|
#else
|
||||||
|
answer.low = _umul128(value1, value2, &answer.high); // _umul128 not available on ARM64
|
||||||
|
#endif // _M_ARM64
|
||||||
|
#else // SIMDJSON_REGULAR_VISUAL_STUDIO || SIMDJSON_IS_32BITS
|
||||||
|
__uint128_t r = (static_cast<__uint128_t>(value1)) * value2;
|
||||||
|
answer.low = uint64_t(r);
|
||||||
|
answer.high = uint64_t(r >> 64);
|
||||||
|
#endif
|
||||||
|
return answer;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace numberparsing
|
||||||
|
} // namespace fallback
|
||||||
|
} // namespace simdjson
|
||||||
|
|
||||||
|
#define SIMDJSON_SWAR_NUMBER_PARSING 1
|
||||||
|
|
||||||
|
#endif // SIMDJSON_FALLBACK_NUMBERPARSING_DEFS_H
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
#ifndef SIMDJSON_FALLBACK_ONDEMAND_H
|
||||||
|
#define SIMDJSON_FALLBACK_ONDEMAND_H
|
||||||
|
|
||||||
|
#include "simdjson/fallback/begin.h"
|
||||||
|
#include "simdjson/generic/ondemand/amalgamated.h"
|
||||||
|
#include "simdjson/fallback/end.h"
|
||||||
|
|
||||||
|
#endif // SIMDJSON_FALLBACK_ONDEMAND_H
|
||||||
+8
-6
@@ -1,10 +1,12 @@
|
|||||||
#ifndef SIMDJSON_FALLBACK_STRINGPARSING_H
|
#ifndef SIMDJSON_FALLBACK_STRINGPARSING_DEFS_H
|
||||||
#define SIMDJSON_FALLBACK_STRINGPARSING_H
|
#define SIMDJSON_FALLBACK_STRINGPARSING_DEFS_H
|
||||||
|
|
||||||
#include "simdjson/base.h"
|
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
#include "simdjson/fallback/base.h"
|
||||||
|
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
|
||||||
namespace simdjson {
|
namespace simdjson {
|
||||||
namespace SIMDJSON_IMPLEMENTATION {
|
namespace fallback {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
// Holds backslashes and quotes locations.
|
// Holds backslashes and quotes locations.
|
||||||
@@ -28,7 +30,7 @@ simdjson_inline backslash_and_quote backslash_and_quote::copy_and_find(const uin
|
|||||||
}
|
}
|
||||||
|
|
||||||
} // unnamed namespace
|
} // unnamed namespace
|
||||||
} // namespace SIMDJSON_IMPLEMENTATION
|
} // namespace fallback
|
||||||
} // namespace simdjson
|
} // namespace simdjson
|
||||||
|
|
||||||
#endif // SIMDJSON_FALLBACK_STRINGPARSING_H
|
#endif // SIMDJSON_FALLBACK_STRINGPARSING_DEFS_H
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
#if defined(SIMDJSON_CONDITIONAL_INCLUDE) && !defined(SIMDJSON_GENERIC_DEPENDENCIES_H)
|
||||||
|
#error simdjson/generic/dependencies.h must be included before simdjson/generic/amalgamated.h!
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "simdjson/generic/base.h"
|
||||||
|
#include "simdjson/generic/jsoncharutils.h"
|
||||||
|
#include "simdjson/generic/atomparsing.h"
|
||||||
|
#include "simdjson/generic/dom_parser_implementation.h"
|
||||||
|
#include "simdjson/generic/implementation_simdjson_result_base.h"
|
||||||
|
#include "simdjson/generic/numberparsing.h"
|
||||||
|
|
||||||
|
#include "simdjson/generic/implementation_simdjson_result_base-inl.h"
|
||||||
@@ -1,3 +1,13 @@
|
|||||||
|
#ifndef SIMDJSON_GENERIC_ATOMPARSING_H
|
||||||
|
|
||||||
|
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
#define SIMDJSON_GENERIC_ATOMPARSING_H
|
||||||
|
#include "simdjson/generic/base.h"
|
||||||
|
#include "simdjson/generic/jsoncharutils.h"
|
||||||
|
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
namespace simdjson {
|
namespace simdjson {
|
||||||
namespace SIMDJSON_IMPLEMENTATION {
|
namespace SIMDJSON_IMPLEMENTATION {
|
||||||
namespace {
|
namespace {
|
||||||
@@ -63,3 +73,5 @@ simdjson_inline bool is_valid_null_atom(const uint8_t *src, size_t len) {
|
|||||||
} // unnamed namespace
|
} // unnamed namespace
|
||||||
} // namespace SIMDJSON_IMPLEMENTATION
|
} // namespace SIMDJSON_IMPLEMENTATION
|
||||||
} // namespace simdjson
|
} // namespace simdjson
|
||||||
|
|
||||||
|
#endif // SIMDJSON_GENERIC_ATOMPARSING_H
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
#ifndef SIMDJSON_GENERIC_BASE_H
|
||||||
|
|
||||||
|
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
#define SIMDJSON_GENERIC_BASE_H
|
||||||
|
#include "simdjson/base.h"
|
||||||
|
// If we haven't got an implementation yet, we're in the editor, editing a generic file! Just
|
||||||
|
// use the most advanced one we can so the most possible stuff can be tested.
|
||||||
|
#ifndef SIMDJSON_IMPLEMENTATION
|
||||||
|
#include "simdjson/implementation_detection.h"
|
||||||
|
#if SIMDJSON_IMPLEMENTATION_ICELAKE
|
||||||
|
#include "simdjson/icelake/begin.h"
|
||||||
|
#elif SIMDJSON_IMPLEMENTATION_HASWELL
|
||||||
|
#include "simdjson/haswell/begin.h"
|
||||||
|
#elif SIMDJSON_IMPLEMENTATION_WESTMERE
|
||||||
|
#include "simdjson/westmere/begin.h"
|
||||||
|
#elif SIMDJSON_IMPLEMENTATION_ARM64
|
||||||
|
#include "simdjson/arm64/begin.h"
|
||||||
|
#elif SIMDJSON_IMPLEMENTATION_PPC64
|
||||||
|
#include "simdjson/ppc64/begin.h"
|
||||||
|
#elif SIMDJSON_IMPLEMENTATION_FALLBACK
|
||||||
|
#include "simdjson/fallback/begin.h"
|
||||||
|
#else
|
||||||
|
#error "All possible implementations (including fallback) have been disabled! simdjson will not run."
|
||||||
|
#endif
|
||||||
|
#endif // SIMDJSON_IMPLEMENTATION
|
||||||
|
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
|
||||||
|
namespace simdjson {
|
||||||
|
namespace SIMDJSON_IMPLEMENTATION {
|
||||||
|
|
||||||
|
struct open_container;
|
||||||
|
class dom_parser_implementation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type of a JSON number
|
||||||
|
*/
|
||||||
|
enum class number_type {
|
||||||
|
floating_point_number=1, /// a binary64 number
|
||||||
|
signed_integer, /// a signed integer that fits in a 64-bit word using two's complement
|
||||||
|
unsigned_integer /// a positive integer larger or equal to 1<<63
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace SIMDJSON_IMPLEMENTATION
|
||||||
|
} // namespace simdjson
|
||||||
|
|
||||||
|
#endif // SIMDJSON_GENERIC_BASE_H
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
#ifdef SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
#error simdjson/generic/dependencies.h must be included before defining SIMDJSON_CONDITIONAL_INCLUDE!
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SIMDJSON_GENERIC_DEPENDENCIES_H
|
||||||
|
#define SIMDJSON_GENERIC_DEPENDENCIES_H
|
||||||
|
|
||||||
|
// Internal headers needed for generics.
|
||||||
|
// All includes referencing simdjson headers *not* under simdjson/generic must be here!
|
||||||
|
// Otherwise, amalgamation will fail.
|
||||||
|
#include "simdjson/base.h"
|
||||||
|
#include "simdjson/implementation.h"
|
||||||
|
#include "simdjson/implementation_detection.h"
|
||||||
|
#include "simdjson/internal/instruction_set.h"
|
||||||
|
#include "simdjson/internal/dom_parser_implementation.h"
|
||||||
|
#include "simdjson/internal/jsoncharutils_tables.h"
|
||||||
|
#include "simdjson/internal/numberparsing_tables.h"
|
||||||
|
#include "simdjson/internal/simdprune_tables.h"
|
||||||
|
|
||||||
|
#endif // SIMDJSON_GENERIC_DEPENDENCIES_H
|
||||||
@@ -1,5 +1,10 @@
|
|||||||
#include "simdjson/base.h"
|
#ifndef SIMDJSON_GENERIC_DOM_PARSER_IMPLEMENTATION_H
|
||||||
#include "simdjson/internal/isadetection.h"
|
|
||||||
|
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
#define SIMDJSON_GENERIC_DOM_PARSER_IMPLEMENTATION_H
|
||||||
|
#include "simdjson/generic/base.h"
|
||||||
|
#include "simdjson/internal/dom_parser_implementation.h"
|
||||||
|
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
|
||||||
namespace simdjson {
|
namespace simdjson {
|
||||||
namespace SIMDJSON_IMPLEMENTATION {
|
namespace SIMDJSON_IMPLEMENTATION {
|
||||||
@@ -80,3 +85,5 @@ inline simdjson_warn_unused error_code dom_parser_implementation::set_max_depth(
|
|||||||
|
|
||||||
} // namespace SIMDJSON_IMPLEMENTATION
|
} // namespace SIMDJSON_IMPLEMENTATION
|
||||||
} // namespace simdjson
|
} // namespace simdjson
|
||||||
|
|
||||||
|
#endif // SIMDJSON_GENERIC_DOM_PARSER_IMPLEMENTATION_H
|
||||||
@@ -1,3 +1,11 @@
|
|||||||
|
#ifndef SIMDJSON_GENERIC_IMPLEMENTATION_SIMDJSON_RESULT_BASE_INL_H
|
||||||
|
|
||||||
|
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
#define SIMDJSON_GENERIC_IMPLEMENTATION_SIMDJSON_RESULT_BASE_INL_H
|
||||||
|
#include "simdjson/generic/base.h"
|
||||||
|
#include "simdjson/generic/implementation_simdjson_result_base.h"
|
||||||
|
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
|
||||||
namespace simdjson {
|
namespace simdjson {
|
||||||
namespace SIMDJSON_IMPLEMENTATION {
|
namespace SIMDJSON_IMPLEMENTATION {
|
||||||
|
|
||||||
@@ -78,3 +86,5 @@ simdjson_inline implementation_simdjson_result_base<T>::implementation_simdjson_
|
|||||||
|
|
||||||
} // namespace SIMDJSON_IMPLEMENTATION
|
} // namespace SIMDJSON_IMPLEMENTATION
|
||||||
} // namespace simdjson
|
} // namespace simdjson
|
||||||
|
|
||||||
|
#endif // SIMDJSON_GENERIC_IMPLEMENTATION_SIMDJSON_RESULT_BASE_INL_H
|
||||||
@@ -1,3 +1,10 @@
|
|||||||
|
#ifndef SIMDJSON_GENERIC_IMPLEMENTATION_SIMDJSON_RESULT_BASE_H
|
||||||
|
|
||||||
|
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
#define SIMDJSON_GENERIC_IMPLEMENTATION_SIMDJSON_RESULT_BASE_H
|
||||||
|
#include "simdjson/generic/base.h"
|
||||||
|
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
|
||||||
namespace simdjson {
|
namespace simdjson {
|
||||||
namespace SIMDJSON_IMPLEMENTATION {
|
namespace SIMDJSON_IMPLEMENTATION {
|
||||||
|
|
||||||
@@ -123,3 +130,5 @@ protected:
|
|||||||
|
|
||||||
} // namespace SIMDJSON_IMPLEMENTATION
|
} // namespace SIMDJSON_IMPLEMENTATION
|
||||||
} // namespace simdjson
|
} // namespace simdjson
|
||||||
|
|
||||||
|
#endif // SIMDJSON_GENERIC_IMPLEMENTATION_SIMDJSON_RESULT_BASE_H
|
||||||
@@ -1,5 +1,11 @@
|
|||||||
|
#ifndef SIMDJSON_GENERIC_JSONCHARUTILS_H
|
||||||
|
|
||||||
|
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
#define SIMDJSON_GENERIC_JSONCHARUTILS_H
|
||||||
|
#include "simdjson/generic/base.h"
|
||||||
#include "simdjson/internal/jsoncharutils_tables.h"
|
#include "simdjson/internal/jsoncharutils_tables.h"
|
||||||
#include "simdjson/internal/numberparsing_tables.h"
|
#include "simdjson/internal/numberparsing_tables.h"
|
||||||
|
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
|
||||||
namespace simdjson {
|
namespace simdjson {
|
||||||
namespace SIMDJSON_IMPLEMENTATION {
|
namespace SIMDJSON_IMPLEMENTATION {
|
||||||
@@ -90,27 +96,9 @@ static simdjson_inline uint64_t _umul128(uint64_t ab, uint64_t cd, uint64_t *hi)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
using internal::value128;
|
|
||||||
|
|
||||||
simdjson_inline value128 full_multiplication(uint64_t value1, uint64_t value2) {
|
|
||||||
value128 answer;
|
|
||||||
#if SIMDJSON_REGULAR_VISUAL_STUDIO || SIMDJSON_IS_32BITS
|
|
||||||
#ifdef _M_ARM64
|
|
||||||
// ARM64 has native support for 64-bit multiplications, no need to emultate
|
|
||||||
answer.high = __umulh(value1, value2);
|
|
||||||
answer.low = value1 * value2;
|
|
||||||
#else
|
|
||||||
answer.low = _umul128(value1, value2, &answer.high); // _umul128 not available on ARM64
|
|
||||||
#endif // _M_ARM64
|
|
||||||
#else // SIMDJSON_REGULAR_VISUAL_STUDIO || SIMDJSON_IS_32BITS
|
|
||||||
__uint128_t r = (static_cast<__uint128_t>(value1)) * value2;
|
|
||||||
answer.low = uint64_t(r);
|
|
||||||
answer.high = uint64_t(r >> 64);
|
|
||||||
#endif
|
|
||||||
return answer;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace jsoncharutils
|
} // namespace jsoncharutils
|
||||||
} // unnamed namespace
|
} // unnamed namespace
|
||||||
} // namespace SIMDJSON_IMPLEMENTATION
|
} // namespace SIMDJSON_IMPLEMENTATION
|
||||||
} // namespace simdjson
|
} // namespace simdjson
|
||||||
|
|
||||||
|
#endif // SIMDJSON_GENERIC_JSONCHARUTILS_H
|
||||||
@@ -1,20 +1,20 @@
|
|||||||
|
#ifndef SIMDJSON_GENERIC_NUMBERPARSING_H
|
||||||
|
|
||||||
|
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
#define SIMDJSON_GENERIC_NUMBERPARSING_H
|
||||||
|
#include "simdjson/generic/base.h"
|
||||||
|
#include "simdjson/generic/jsoncharutils.h"
|
||||||
#include "simdjson/internal/numberparsing_tables.h"
|
#include "simdjson/internal/numberparsing_tables.h"
|
||||||
|
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
#include <ostream>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
namespace simdjson {
|
namespace simdjson {
|
||||||
namespace SIMDJSON_IMPLEMENTATION {
|
namespace SIMDJSON_IMPLEMENTATION {
|
||||||
/// @private
|
|
||||||
namespace numberparsing {
|
namespace numberparsing {
|
||||||
|
|
||||||
/**
|
|
||||||
* The type of a JSON number
|
|
||||||
*/
|
|
||||||
enum class number_type {
|
|
||||||
floating_point_number=1, /// a binary64 number
|
|
||||||
signed_integer, /// a signed integer that fits in a 64-bit word using two's complement
|
|
||||||
unsigned_integer /// a positive integer larger or equal to 1<<63
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef JSON_TEST_NUMBERS
|
#ifdef JSON_TEST_NUMBERS
|
||||||
#define INVALID_NUMBER(SRC) (found_invalid_number((SRC)), NUMBER_ERROR)
|
#define INVALID_NUMBER(SRC) (found_invalid_number((SRC)), NUMBER_ERROR)
|
||||||
#define WRITE_INTEGER(VALUE, SRC, WRITER) (found_integer((VALUE), (SRC)), (WRITER).append_s64((VALUE)))
|
#define WRITE_INTEGER(VALUE, SRC, WRITER) (found_integer((VALUE), (SRC)), (WRITER).append_s64((VALUE)))
|
||||||
@@ -165,7 +165,7 @@ simdjson_inline bool compute_float_64(int64_t power, uint64_t i, bool negative,
|
|||||||
// with a returned value of type value128 with a "low component" corresponding to the
|
// with a returned value of type value128 with a "low component" corresponding to the
|
||||||
// 64-bit least significant bits of the product and with a "high component" corresponding
|
// 64-bit least significant bits of the product and with a "high component" corresponding
|
||||||
// to the 64-bit most significant bits of the product.
|
// to the 64-bit most significant bits of the product.
|
||||||
simdjson::internal::value128 firstproduct = jsoncharutils::full_multiplication(i, simdjson::internal::power_of_five_128[index]);
|
simdjson::internal::value128 firstproduct = full_multiplication(i, simdjson::internal::power_of_five_128[index]);
|
||||||
// Both i and power_of_five_128[index] have their most significant bit set to 1 which
|
// Both i and power_of_five_128[index] have their most significant bit set to 1 which
|
||||||
// implies that the either the most or the second most significant bit of the product
|
// implies that the either the most or the second most significant bit of the product
|
||||||
// is 1. We pack values in this manner for efficiency reasons: it maximizes the use
|
// is 1. We pack values in this manner for efficiency reasons: it maximizes the use
|
||||||
@@ -186,8 +186,7 @@ simdjson_inline bool compute_float_64(int64_t power, uint64_t i, bool negative,
|
|||||||
// power_of_five_128[index]. Usually, that's good enough to approximate i * 5^q
|
// power_of_five_128[index]. Usually, that's good enough to approximate i * 5^q
|
||||||
// to the desired approximation using one multiplication. Sometimes it does not suffice.
|
// to the desired approximation using one multiplication. Sometimes it does not suffice.
|
||||||
// Then we store the next most significant 64 bits in power_of_five_128[index + 1], and
|
// Then we store the next most significant 64 bits in power_of_five_128[index + 1], and
|
||||||
// then we get a better approximation to i * 5^q. In very rare cases, even that
|
// then we get a better approximation to i * 5^q.
|
||||||
// will not suffice, though it is seemingly very hard to find such a scenario.
|
|
||||||
//
|
//
|
||||||
// That's for when q>=0. The logic for q<0 is somewhat similar but it is somewhat
|
// That's for when q>=0. The logic for q<0 is somewhat similar but it is somewhat
|
||||||
// more complicated.
|
// more complicated.
|
||||||
@@ -199,15 +198,12 @@ simdjson_inline bool compute_float_64(int64_t power, uint64_t i, bool negative,
|
|||||||
// with a returned value of type value128 with a "low component" corresponding to the
|
// with a returned value of type value128 with a "low component" corresponding to the
|
||||||
// 64-bit least significant bits of the product and with a "high component" corresponding
|
// 64-bit least significant bits of the product and with a "high component" corresponding
|
||||||
// to the 64-bit most significant bits of the product.
|
// to the 64-bit most significant bits of the product.
|
||||||
simdjson::internal::value128 secondproduct = jsoncharutils::full_multiplication(i, simdjson::internal::power_of_five_128[index + 1]);
|
simdjson::internal::value128 secondproduct = full_multiplication(i, simdjson::internal::power_of_five_128[index + 1]);
|
||||||
firstproduct.low += secondproduct.high;
|
firstproduct.low += secondproduct.high;
|
||||||
if(secondproduct.high > firstproduct.low) { firstproduct.high++; }
|
if(secondproduct.high > firstproduct.low) { firstproduct.high++; }
|
||||||
// At this point, we might need to add at most one to firstproduct, but this
|
// As it has been proven by Noble Mushtak and Daniel Lemire in "Fast Number Parsing Without
|
||||||
// can only change the value of firstproduct.high if firstproduct.low is maximal.
|
// Fallback" (https://arxiv.org/abs/2212.06644), at this point we are sure that the product
|
||||||
if(simdjson_unlikely(firstproduct.low == 0xFFFFFFFFFFFFFFFF)) {
|
// is sufficiently accurate, and more computation is not needed.
|
||||||
// This is very unlikely, but if so, we need to do much more work!
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
uint64_t lower = firstproduct.low;
|
uint64_t lower = firstproduct.low;
|
||||||
uint64_t upper = firstproduct.high;
|
uint64_t upper = firstproduct.high;
|
||||||
@@ -1250,6 +1246,8 @@ simdjson_unused simdjson_inline simdjson_result<double> parse_double_in_string(c
|
|||||||
} // unnamed namespace
|
} // unnamed namespace
|
||||||
#endif // SIMDJSON_SKIPNUMBERPARSING
|
#endif // SIMDJSON_SKIPNUMBERPARSING
|
||||||
|
|
||||||
|
} // namespace numberparsing
|
||||||
|
|
||||||
inline std::ostream& operator<<(std::ostream& out, number_type type) noexcept {
|
inline std::ostream& operator<<(std::ostream& out, number_type type) noexcept {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case number_type::signed_integer: out << "integer in [-9223372036854775808,9223372036854775808)"; break;
|
case number_type::signed_integer: out << "integer in [-9223372036854775808,9223372036854775808)"; break;
|
||||||
@@ -1260,6 +1258,7 @@ inline std::ostream& operator<<(std::ostream& out, number_type type) noexcept {
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace numberparsing
|
|
||||||
} // namespace SIMDJSON_IMPLEMENTATION
|
} // namespace SIMDJSON_IMPLEMENTATION
|
||||||
} // namespace simdjson
|
} // namespace simdjson
|
||||||
|
|
||||||
|
#endif // SIMDJSON_GENERIC_NUMBERPARSING_H
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user