mirror of
https://github.com/simdjson/simdjson
synced 2026-06-08 17:27:07 +00:00
Compare commits
99 Commits
v3.2.1
...
jkeiser/comma
| Author | SHA1 | Date | |
|---|---|---|---|
| 8149284602 | |||
| 0e28a8312d | |||
| 04ab4bb4d9 | |||
| 3960880a0d | |||
| e0f906da79 | |||
| 6a054395a6 | |||
| eac04c7324 | |||
| 319b10acad | |||
| d2d15255bc | |||
| 5b7acd2aa7 | |||
| 61ef447595 | |||
| b524e29576 | |||
| a7b7bc2b69 | |||
| 76dd137c87 | |||
| 52b2414281 | |||
| 5d762fb67f | |||
| 9dc70e8d9c | |||
| 589ef23b56 | |||
| 4b1148384e | |||
| 32afd34a90 | |||
| 70674d2dbd | |||
| f594a49a4b | |||
| 54cbebfd29 | |||
| c6e43a631c | |||
| a8635c9b89 | |||
| 075bfb173b | |||
| a88ad515c2 | |||
| 78b4c0aa6e | |||
| 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,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,13 +20,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 &&
|
||||||
|
|||||||
@@ -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,23 @@ 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') }}
|
||||||
|
ctest --output-on-failure -LE explicitonly -j
|
||||||
- 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",
|
||||||
|
|||||||
+1
-1
@@ -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.2.3
|
||||||
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
|
||||||
|
|||||||
@@ -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.2.3"
|
||||||
|
|
||||||
# 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.
|
||||||
|
|||||||
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!)
|
||||||
|
|||||||
@@ -117,7 +117,12 @@ set(CMAKE_CXX_EXTENSIONS OFF)
|
|||||||
set(CMAKE_MACOSX_RPATH 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)
|
||||||
|
|||||||
+1
-1
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
+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,9 @@
|
|||||||
#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/lookup_table.h"
|
||||||
#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,28 @@
|
|||||||
|
#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 simd {
|
||||||
|
|
||||||
|
template <typename T> struct simd8;
|
||||||
|
template <> struct simd8<bool>;
|
||||||
|
template <> struct simd8<uint8_t>;
|
||||||
|
template <typename T> struct simd8x64;
|
||||||
|
|
||||||
|
} // namespace simd
|
||||||
|
|
||||||
|
} // 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/bitmask.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,101 +0,0 @@
|
|||||||
#ifndef SIMDJSON_ARM64_BITMANIPULATION_H
|
|
||||||
#define SIMDJSON_ARM64_BITMANIPULATION_H
|
|
||||||
|
|
||||||
namespace simdjson {
|
|
||||||
namespace SIMDJSON_IMPLEMENTATION {
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
// We sometimes call trailing_zero on inputs that are zero,
|
|
||||||
// but the algorithms do not end up using the returned value.
|
|
||||||
// Sadly, sanitizers are not smart enough to figure it out.
|
|
||||||
SIMDJSON_NO_SANITIZE_UNDEFINED
|
|
||||||
// This function can be used safely even if not all bytes have been
|
|
||||||
// initialized.
|
|
||||||
// See issue https://github.com/simdjson/simdjson/issues/1965
|
|
||||||
SIMDJSON_NO_SANITIZE_MEMORY
|
|
||||||
simdjson_inline int trailing_zeroes(uint64_t input_num) {
|
|
||||||
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
|
|
||||||
unsigned long ret;
|
|
||||||
// Search the mask data from least significant bit (LSB)
|
|
||||||
// to the most significant bit (MSB) for a set bit (1).
|
|
||||||
_BitScanForward64(&ret, input_num);
|
|
||||||
return (int)ret;
|
|
||||||
#else // SIMDJSON_REGULAR_VISUAL_STUDIO
|
|
||||||
return __builtin_ctzll(input_num);
|
|
||||||
#endif // SIMDJSON_REGULAR_VISUAL_STUDIO
|
|
||||||
}
|
|
||||||
|
|
||||||
/* result might be undefined when input_num is zero */
|
|
||||||
simdjson_inline uint64_t clear_lowest_bit(uint64_t input_num) {
|
|
||||||
return input_num & (input_num-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* result might be undefined when input_num is zero */
|
|
||||||
simdjson_inline int leading_zeroes(uint64_t input_num) {
|
|
||||||
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
|
|
||||||
unsigned long leading_zero = 0;
|
|
||||||
// Search the mask data from most significant bit (MSB)
|
|
||||||
// to least significant bit (LSB) for a set bit (1).
|
|
||||||
if (_BitScanReverse64(&leading_zero, input_num))
|
|
||||||
return (int)(63 - leading_zero);
|
|
||||||
else
|
|
||||||
return 64;
|
|
||||||
#else
|
|
||||||
return __builtin_clzll(input_num);
|
|
||||||
#endif// SIMDJSON_REGULAR_VISUAL_STUDIO
|
|
||||||
}
|
|
||||||
|
|
||||||
/* result might be undefined when input_num is zero */
|
|
||||||
simdjson_inline int count_ones(uint64_t input_num) {
|
|
||||||
return vaddv_u8(vcnt_u8(vcreate_u8(input_num)));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#if defined(__GNUC__) // catches clang and gcc
|
|
||||||
/**
|
|
||||||
* ARM has a fast 64-bit "bit reversal function" that is handy. However,
|
|
||||||
* it is not generally available as an intrinsic function under Visual
|
|
||||||
* Studio (though this might be changing). Even under clang/gcc, we
|
|
||||||
* apparently need to invoke inline assembly.
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
* We use SIMDJSON_PREFER_REVERSE_BITS as a hint that algorithms that
|
|
||||||
* work well with bit reversal may use it.
|
|
||||||
*/
|
|
||||||
#define SIMDJSON_PREFER_REVERSE_BITS 1
|
|
||||||
|
|
||||||
/* reverse the bits */
|
|
||||||
simdjson_inline uint64_t reverse_bits(uint64_t input_num) {
|
|
||||||
uint64_t rev_bits;
|
|
||||||
__asm("rbit %0, %1" : "=r"(rev_bits) : "r"(input_num));
|
|
||||||
return rev_bits;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Flips bit at index 63 - lz. Thus if you have 'leading_zeroes' leading zeroes,
|
|
||||||
* then this will set to zero the leading bit. It is possible for leading_zeroes to be
|
|
||||||
* greating or equal to 63 in which case we trigger undefined behavior, but the output
|
|
||||||
* of such undefined behavior is never used.
|
|
||||||
**/
|
|
||||||
SIMDJSON_NO_SANITIZE_UNDEFINED
|
|
||||||
simdjson_inline uint64_t zero_leading_bit(uint64_t rev_bits, int leading_zeroes) {
|
|
||||||
return rev_bits ^ (uint64_t(0x8000000000000000) >> leading_zeroes);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
simdjson_inline bool add_overflow(uint64_t value1, uint64_t value2, uint64_t *result) {
|
|
||||||
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
|
|
||||||
*result = value1 + value2;
|
|
||||||
return *result < value1;
|
|
||||||
#else
|
|
||||||
return __builtin_uaddll_overflow(value1, value2,
|
|
||||||
reinterpret_cast<unsigned long long *>(result));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
} // unnamed namespace
|
|
||||||
} // namespace SIMDJSON_IMPLEMENTATION
|
|
||||||
} // namespace simdjson
|
|
||||||
|
|
||||||
#endif // SIMDJSON_ARM64_BITMANIPULATION_H
|
|
||||||
@@ -1,9 +1,131 @@
|
|||||||
#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"
|
||||||
|
#include "simdjson/arm64/intrinsics.h"
|
||||||
|
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
|
||||||
namespace simdjson {
|
namespace simdjson {
|
||||||
namespace SIMDJSON_IMPLEMENTATION {
|
namespace arm64 {
|
||||||
namespace {
|
namespace bitmask {
|
||||||
|
|
||||||
|
// We sometimes call trailing_zero on inputs that are zero,
|
||||||
|
// but the algorithms do not end up using the returned value.
|
||||||
|
// Sadly, sanitizers are not smart enough to figure it out.
|
||||||
|
SIMDJSON_NO_SANITIZE_UNDEFINED
|
||||||
|
// This function can be used safely even if not all bytes have been
|
||||||
|
// initialized.
|
||||||
|
// See issue https://github.com/simdjson/simdjson/issues/1965
|
||||||
|
SIMDJSON_NO_SANITIZE_MEMORY
|
||||||
|
simdjson_inline int trailing_zeroes(uint64_t input_num) {
|
||||||
|
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||||
|
unsigned long ret;
|
||||||
|
// Search the mask data from least significant bit (LSB)
|
||||||
|
// to the most significant bit (MSB) for a set bit (1).
|
||||||
|
_BitScanForward64(&ret, input_num);
|
||||||
|
return (int)ret;
|
||||||
|
#else // SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||||
|
return __builtin_ctzll(input_num);
|
||||||
|
#endif // SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||||
|
}
|
||||||
|
|
||||||
|
/* result might be undefined when input_num is zero */
|
||||||
|
simdjson_inline uint64_t clear_lowest_bit(uint64_t input_num) {
|
||||||
|
return input_num & (input_num-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* result might be undefined when input_num is zero */
|
||||||
|
simdjson_inline int leading_zeroes(uint64_t input_num) {
|
||||||
|
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||||
|
unsigned long leading_zero = 0;
|
||||||
|
// Search the mask data from most significant bit (MSB)
|
||||||
|
// to least significant bit (LSB) for a set bit (1).
|
||||||
|
if (_BitScanReverse64(&leading_zero, input_num))
|
||||||
|
return (int)(63 - leading_zero);
|
||||||
|
else
|
||||||
|
return 64;
|
||||||
|
#else
|
||||||
|
return __builtin_clzll(input_num);
|
||||||
|
#endif// SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||||
|
}
|
||||||
|
|
||||||
|
/* result might be undefined when input_num is zero */
|
||||||
|
simdjson_inline int count_ones(uint64_t input_num) {
|
||||||
|
return vaddv_u8(vcnt_u8(vcreate_u8(input_num)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(__GNUC__) // catches clang and gcc
|
||||||
|
/**
|
||||||
|
* ARM has a fast 64-bit "bit reversal function" that is handy. However,
|
||||||
|
* it is not generally available as an intrinsic function under Visual
|
||||||
|
* Studio (though this might be changing). Even under clang/gcc, we
|
||||||
|
* apparently need to invoke inline assembly.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* We use SIMDJSON_PREFER_REVERSE_BITS as a hint that algorithms that
|
||||||
|
* work well with bit reversal may use it.
|
||||||
|
*/
|
||||||
|
#define SIMDJSON_PREFER_REVERSE_BITS 1
|
||||||
|
|
||||||
|
/* reverse the bits */
|
||||||
|
simdjson_inline uint64_t reverse_bits(uint64_t input_num) {
|
||||||
|
uint64_t rev_bits;
|
||||||
|
__asm("rbit %0, %1" : "=r"(rev_bits) : "r"(input_num));
|
||||||
|
return rev_bits;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flips bit at index 63 - lz. Thus if you have 'leading_zeroes' leading zeroes,
|
||||||
|
* then this will set to zero the leading bit. It is possible for leading_zeroes to be
|
||||||
|
* greating or equal to 63 in which case we trigger undefined behavior, but the output
|
||||||
|
* of such undefined behavior is never used.
|
||||||
|
**/
|
||||||
|
SIMDJSON_NO_SANITIZE_UNDEFINED
|
||||||
|
simdjson_inline uint64_t zero_leading_bit(uint64_t rev_bits, int leading_zeroes) {
|
||||||
|
return rev_bits ^ (uint64_t(0x8000000000000000) >> leading_zeroes);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
simdjson_inline uint64_t add_carry_out(uint64_t value1, uint64_t value2, bool &carry_out) {
|
||||||
|
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||||
|
uint64_t result = value1 + value2;
|
||||||
|
carry_out = result < value1;
|
||||||
|
return result;
|
||||||
|
#else
|
||||||
|
unsigned long long result;
|
||||||
|
carry_out = __builtin_uaddll_overflow(value1, value2, &result);
|
||||||
|
return result;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
simdjson_inline uint64_t subtract_borrow(uint64_t value1, uint64_t value2, bool &borrow) {
|
||||||
|
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||||
|
value2 += borrow;
|
||||||
|
uint64_t result = value1 - value2;
|
||||||
|
borrow = value1 > value2;
|
||||||
|
return result;
|
||||||
|
#else
|
||||||
|
unsigned long long result;
|
||||||
|
bool borrow1 = __builtin_usubll_overflow(value1, value2, &result);
|
||||||
|
borrow = borrow1 | __builtin_usubll_overflow(result, borrow, &result);
|
||||||
|
return result;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
simdjson_inline uint64_t subtract_borrow_out(uint64_t value1, uint64_t value2, bool &borrow_out) {
|
||||||
|
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||||
|
uint64_t result = value1 - value2;
|
||||||
|
borrow_out = result > value1;
|
||||||
|
return result;
|
||||||
|
#else
|
||||||
|
unsigned long long result;
|
||||||
|
borrow_out = __builtin_usubll_overflow(value1, value2, &result);
|
||||||
|
return result;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Perform a "cumulative bitwise xor," flipping bits each time a 1 is encountered.
|
// Perform a "cumulative bitwise xor," flipping bits each time a 1 is encountered.
|
||||||
|
|||||||
@@ -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
|
||||||
+209
-55
@@ -1,15 +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/arm64/base.h"
|
||||||
|
#include "simdjson/arm64/bitmask.h"
|
||||||
#include "simdjson/internal/simdprune_tables.h"
|
#include "simdjson/internal/simdprune_tables.h"
|
||||||
#include "simdjson/arm64/bitmanipulation.h"
|
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
#include <type_traits>
|
|
||||||
|
|
||||||
|
|
||||||
namespace simdjson {
|
namespace simdjson {
|
||||||
namespace SIMDJSON_IMPLEMENTATION {
|
namespace arm64 {
|
||||||
namespace {
|
|
||||||
namespace simd {
|
namespace simd {
|
||||||
|
|
||||||
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
|
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||||
@@ -28,7 +27,7 @@ namespace {
|
|||||||
* You should not use this function except for compile-time constants:
|
* You should not use this function except for compile-time constants:
|
||||||
* it is not efficient.
|
* it is not efficient.
|
||||||
*/
|
*/
|
||||||
simdjson_inline uint8x16_t make_uint8x16_t(uint8_t x1, uint8_t x2, uint8_t x3, uint8_t x4,
|
simdjson_inline simd_t make_uint8x16_t(uint8_t x1, uint8_t x2, uint8_t x3, uint8_t x4,
|
||||||
uint8_t x5, uint8_t x6, uint8_t x7, uint8_t x8,
|
uint8_t x5, uint8_t x6, uint8_t x7, uint8_t x8,
|
||||||
uint8_t x9, uint8_t x10, uint8_t x11, uint8_t x12,
|
uint8_t x9, uint8_t x10, uint8_t x11, uint8_t x12,
|
||||||
uint8_t x13, uint8_t x14, uint8_t x15, uint8_t x16) {
|
uint8_t x13, uint8_t x14, uint8_t x15, uint8_t x16) {
|
||||||
@@ -36,7 +35,7 @@ simdjson_inline uint8x16_t make_uint8x16_t(uint8_t x1, uint8_t x2, uint8_t x3,
|
|||||||
// uint8_t array[16] = {x1, x2, x3, x4, x5, x6, x7, x8,
|
// uint8_t array[16] = {x1, x2, x3, x4, x5, x6, x7, x8,
|
||||||
// x9, x10,x11,x12,x13,x14,x15,x16};
|
// x9, x10,x11,x12,x13,x14,x15,x16};
|
||||||
// return vld1q_u8(array);
|
// return vld1q_u8(array);
|
||||||
uint8x16_t x{};
|
simd_t x{};
|
||||||
// incredibly, Visual Studio does not allow x[0] = x1
|
// incredibly, Visual Studio does not allow x[0] = x1
|
||||||
x = vsetq_lane_u8(x1, x, 0);
|
x = vsetq_lane_u8(x1, x, 0);
|
||||||
x = vsetq_lane_u8(x2, x, 1);
|
x = vsetq_lane_u8(x2, x, 1);
|
||||||
@@ -109,18 +108,28 @@ simdjson_inline int8x16_t make_int8x16_t(int8_t x1, int8_t x2, int8_t x3, int
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
struct simd8;
|
struct simd8;
|
||||||
|
|
||||||
|
#if !SIMDJSON_IS_ARM && !defined(SIMDJSON_CONDITIONAL_INCLUDE)
|
||||||
|
// Make errors a bit more manageable when editing on non-ARM
|
||||||
|
struct uint8x16_t { uint8_t x[16]; };
|
||||||
|
#endif
|
||||||
|
|
||||||
//
|
//
|
||||||
// Base class of simd8<uint8_t> and simd8<bool>, both of which use uint8x16_t internally.
|
// Base class of simd8<uint8_t> and simd8<bool>, both of which use uint8x16_t internally.
|
||||||
//
|
//
|
||||||
template<typename T, typename Mask=simd8<bool>>
|
template<typename T, typename Mask=simd8<bool>>
|
||||||
struct base_u8 {
|
struct base_u8 {
|
||||||
uint8x16_t value;
|
/** The actual underlying system SIMD type. */
|
||||||
static const int SIZE = sizeof(value);
|
using simd_t = uint8x16_t;
|
||||||
|
static constexpr const int LANES = sizeof(simd_t);
|
||||||
|
using bitmask_t = uint16_t;
|
||||||
|
static_assert(sizeof(bitmask_t)*8 == LANES, "Bitmask type's bits must equal the simd type's bytes");
|
||||||
|
|
||||||
|
simd_t value;
|
||||||
|
|
||||||
// Conversion from/to SIMD register
|
// Conversion from/to SIMD register
|
||||||
simdjson_inline base_u8(const uint8x16_t _value) : value(_value) {}
|
simdjson_inline base_u8(const simd_t _value) : value(_value) {}
|
||||||
simdjson_inline operator const uint8x16_t&() const { return this->value; }
|
simdjson_inline operator const simd_t&() const { return this->value; }
|
||||||
simdjson_inline operator uint8x16_t&() { return this->value; }
|
simdjson_inline operator simd_t&() { return this->value; }
|
||||||
|
|
||||||
// Bit operations
|
// Bit operations
|
||||||
simdjson_inline simd8<T> operator|(const simd8<T> other) const { return vorrq_u8(*this, other); }
|
simdjson_inline simd8<T> operator|(const simd8<T> other) const { return vorrq_u8(*this, other); }
|
||||||
@@ -132,7 +141,8 @@ simdjson_inline int8x16_t make_int8x16_t(int8_t x1, int8_t x2, int8_t x3, int
|
|||||||
simdjson_inline simd8<T>& operator&=(const simd8<T> other) { auto this_cast = static_cast<simd8<T>*>(this); *this_cast = *this_cast & other; return *this_cast; }
|
simdjson_inline simd8<T>& operator&=(const simd8<T> other) { auto this_cast = static_cast<simd8<T>*>(this); *this_cast = *this_cast & other; return *this_cast; }
|
||||||
simdjson_inline simd8<T>& operator^=(const simd8<T> other) { auto this_cast = static_cast<simd8<T>*>(this); *this_cast = *this_cast ^ other; return *this_cast; }
|
simdjson_inline simd8<T>& operator^=(const simd8<T> other) { auto this_cast = static_cast<simd8<T>*>(this); *this_cast = *this_cast ^ other; return *this_cast; }
|
||||||
|
|
||||||
friend simdjson_inline Mask operator==(const simd8<T> lhs, const simd8<T> rhs) { return vceqq_u8(lhs, rhs); }
|
simdjson_inline Mask eq(const simd8<T> rhs) const { return vceqq_u8(*this, rhs); }
|
||||||
|
friend simdjson_inline Mask operator==(const simd8<T> lhs, const simd8<T> rhs) { return lhs.eq(rhs); }
|
||||||
|
|
||||||
template<int N=1>
|
template<int N=1>
|
||||||
simdjson_inline simd8<T> prev(const simd8<T> prev_chunk) const {
|
simdjson_inline simd8<T> prev(const simd8<T> prev_chunk) const {
|
||||||
@@ -148,7 +158,7 @@ simdjson_inline int8x16_t make_int8x16_t(int8_t x1, int8_t x2, int8_t x3, int
|
|||||||
|
|
||||||
static simdjson_inline simd8<bool> splat(bool _value) { return vmovq_n_u8(uint8_t(-(!!_value))); }
|
static simdjson_inline simd8<bool> splat(bool _value) { return vmovq_n_u8(uint8_t(-(!!_value))); }
|
||||||
|
|
||||||
simdjson_inline simd8(const uint8x16_t _value) : base_u8<bool>(_value) {}
|
simdjson_inline simd8(const simd_t _value) : base_u8<bool>(_value) {}
|
||||||
// False constructor
|
// False constructor
|
||||||
simdjson_inline simd8() : simd8(vdupq_n_u8(0)) {}
|
simdjson_inline simd8() : simd8(vdupq_n_u8(0)) {}
|
||||||
// Splat constructor
|
// Splat constructor
|
||||||
@@ -158,14 +168,14 @@ 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 simd_t bit_mask = make_simd_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 simd_t bit_mask = {0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80,
|
||||||
0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80};
|
0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80};
|
||||||
#endif
|
#endif
|
||||||
auto minput = *this & bit_mask;
|
auto minput = *this & bit_mask;
|
||||||
uint8x16_t tmp = vpaddq_u8(minput, minput);
|
simd_t tmp = vpaddq_u8(minput, minput);
|
||||||
tmp = vpaddq_u8(tmp, tmp);
|
tmp = vpaddq_u8(tmp, tmp);
|
||||||
tmp = vpaddq_u8(tmp, tmp);
|
tmp = vpaddq_u8(tmp, tmp);
|
||||||
return vgetq_lane_u16(vreinterpretq_u16_u8(tmp), 0);
|
return vgetq_lane_u16(vreinterpretq_u16_u8(tmp), 0);
|
||||||
@@ -176,11 +186,14 @@ simdjson_inline int8x16_t make_int8x16_t(int8_t x1, int8_t x2, int8_t x3, int
|
|||||||
// Unsigned bytes
|
// Unsigned bytes
|
||||||
template<>
|
template<>
|
||||||
struct simd8<uint8_t>: base_u8<uint8_t> {
|
struct simd8<uint8_t>: base_u8<uint8_t> {
|
||||||
static simdjson_inline uint8x16_t splat(uint8_t _value) { return vmovq_n_u8(_value); }
|
using typename base_u8<uint8_t>::simd_t;
|
||||||
static simdjson_inline uint8x16_t zero() { return vdupq_n_u8(0); }
|
using base_u8<uint8_t>::LANES;
|
||||||
static simdjson_inline uint8x16_t load(const uint8_t* values) { return vld1q_u8(values); }
|
|
||||||
|
|
||||||
simdjson_inline simd8(const uint8x16_t _value) : base_u8<uint8_t>(_value) {}
|
static simdjson_inline simd_t splat(uint8_t _value) { return vmovq_n_u8(_value); }
|
||||||
|
static simdjson_inline simd_t zero() { return vdupq_n_u8(0); }
|
||||||
|
static simdjson_inline simd_t load(const uint8_t* values) { return vld1q_u8(values); }
|
||||||
|
|
||||||
|
simdjson_inline simd8(const simd_t _value) : base_u8<uint8_t>(_value) {}
|
||||||
// Zero constructor
|
// Zero constructor
|
||||||
simdjson_inline simd8() : simd8(zero()) {}
|
simdjson_inline simd8() : simd8(zero()) {}
|
||||||
// Array constructor
|
// Array constructor
|
||||||
@@ -200,7 +213,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(uint8x16_t{
|
) : simd8(simd_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
|
||||||
}) {}
|
}) {}
|
||||||
@@ -254,15 +267,20 @@ simdjson_inline int8x16_t make_int8x16_t(int8_t x1, int8_t x2, int8_t x3, int
|
|||||||
simdjson_inline simd8<uint8_t> shl() const { return vshlq_n_u8(*this, N); }
|
simdjson_inline simd8<uint8_t> shl() const { return vshlq_n_u8(*this, N); }
|
||||||
|
|
||||||
// Perform a lookup assuming the value is between 0 and 16 (undefined behavior for out of range values)
|
// Perform a lookup assuming the value is between 0 and 16 (undefined behavior for out of range values)
|
||||||
template<typename L>
|
simdjson_inline simd8<uint8_t> lookup_16(simd8<uint8_t> lookup_table) const {
|
||||||
simdjson_inline simd8<L> lookup_16(simd8<L> lookup_table) const {
|
|
||||||
return lookup_table.apply_lookup_16_to(*this);
|
return lookup_table.apply_lookup_16_to(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Perform a lookup based on the lower 4 bits of each lane. (Platform-dependent behavior for
|
||||||
|
// non-ASCII values--may look up the lower 4 bits on some platforms, and return 0 on others.)
|
||||||
|
simdjson_inline simd8<uint8_t> lookup_low_nibble_ascii(simd8<uint8_t> lookup_table) const {
|
||||||
|
return lookup_table.apply_lookup_16_to(*this & 0b10001111);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Copies to 'output" all bytes corresponding to a 0 in the mask (interpreted as a bitset).
|
// Copies to 'output" all bytes corresponding to a 0 in the mask (interpreted as a bitset).
|
||||||
// Passing a 0 value for mask would be equivalent to writing out every byte to output.
|
// Passing a 0 value for mask would be equivalent to writing out every byte to output.
|
||||||
// Only the first 16 - count_ones(mask) bytes of the result are significant but 16 bytes
|
// Only the first 16 - bitmask::count_ones(mask) bytes of the result are significant but 16 bytes
|
||||||
// get written.
|
// get written.
|
||||||
// Design consideration: it seems like a function with the
|
// Design consideration: it seems like a function with the
|
||||||
// signature simd8<L> compress(uint16_t mask) would be
|
// signature simd8<L> compress(uint16_t mask) would be
|
||||||
@@ -280,16 +298,16 @@ simdjson_inline int8x16_t make_int8x16_t(int8_t x1, int8_t x2, int8_t x3, int
|
|||||||
// thintable_epi8[mask2] into a 128-bit register, using only
|
// thintable_epi8[mask2] into a 128-bit register, using only
|
||||||
// two instructions on most compilers.
|
// two instructions on most compilers.
|
||||||
uint64x2_t shufmask64 = {thintable_epi8[mask1], thintable_epi8[mask2]};
|
uint64x2_t shufmask64 = {thintable_epi8[mask1], thintable_epi8[mask2]};
|
||||||
uint8x16_t shufmask = vreinterpretq_u8_u64(shufmask64);
|
simd_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);
|
simd_t inc = 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};
|
simd_t inc = {0, 0, 0, 0, 0, 0, 0, 0, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08};
|
||||||
#endif
|
#endif
|
||||||
shufmask = vaddq_u8(shufmask, inc);
|
shufmask = vaddq_u8(shufmask, inc);
|
||||||
// this is the version "nearly pruned"
|
// this is the version "nearly pruned"
|
||||||
uint8x16_t pruned = vqtbl1q_u8(*this, shufmask);
|
simd_t pruned = vqtbl1q_u8(*this, shufmask);
|
||||||
// we still need to put the two halves together.
|
// we still need to put the two halves together.
|
||||||
// we compute the popcount of the first half:
|
// we compute the popcount of the first half:
|
||||||
int pop1 = BitsSetTable256mul2[mask1];
|
int pop1 = BitsSetTable256mul2[mask1];
|
||||||
@@ -297,8 +315,8 @@ simdjson_inline int8x16_t make_int8x16_t(int8_t x1, int8_t x2, int8_t x3, int
|
|||||||
// only the first pop1 bytes from the first 8 bytes, and then
|
// only the first pop1 bytes from the first 8 bytes, and then
|
||||||
// it fills in with the bytes from the second 8 bytes + some filling
|
// it fills in with the bytes from the second 8 bytes + some filling
|
||||||
// at the end.
|
// at the end.
|
||||||
uint8x16_t compactmask = vld1q_u8(reinterpret_cast<const uint8_t *>(pshufb_combine_table + pop1 * 8));
|
simd_t compactmask = vld1q_u8(reinterpret_cast<const uint8_t *>(pshufb_combine_table + pop1 * 8));
|
||||||
uint8x16_t answer = vqtbl1q_u8(pruned, compactmask);
|
simd_t answer = vqtbl1q_u8(pruned, compactmask);
|
||||||
vst1q_u8(reinterpret_cast<uint8_t*>(output), answer);
|
vst1q_u8(reinterpret_cast<uint8_t*>(output), answer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -323,20 +341,6 @@ simdjson_inline int8x16_t make_int8x16_t(int8_t x1, int8_t x2, int8_t x3, int
|
|||||||
vst1_u8((uint8_t*)output2, vqtbl1_u8(*this, compactmask2));
|
vst1_u8((uint8_t*)output2, vqtbl1_u8(*this, compactmask2));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename L>
|
|
||||||
simdjson_inline simd8<L> lookup_16(
|
|
||||||
L replace0, L replace1, L replace2, L replace3,
|
|
||||||
L replace4, L replace5, L replace6, L replace7,
|
|
||||||
L replace8, L replace9, L replace10, L replace11,
|
|
||||||
L replace12, L replace13, L replace14, L replace15) const {
|
|
||||||
return lookup_16(simd8<L>::repeat_16(
|
|
||||||
replace0, replace1, replace2, replace3,
|
|
||||||
replace4, replace5, replace6, replace7,
|
|
||||||
replace8, replace9, replace10, replace11,
|
|
||||||
replace12, replace13, replace14, replace15
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
simdjson_inline simd8<uint8_t> apply_lookup_16_to(const simd8<T> original) {
|
simdjson_inline simd8<uint8_t> apply_lookup_16_to(const simd8<T> original) {
|
||||||
return vqtbl1q_u8(*this, simd8<uint8_t>(original));
|
return vqtbl1q_u8(*this, simd8<uint8_t>(original));
|
||||||
@@ -401,7 +405,7 @@ simdjson_inline int8x16_t make_int8x16_t(int8_t x1, int8_t x2, int8_t x3, int
|
|||||||
// In theory, we could check this occurrence with std::same_as and std::enabled_if but it is C++14
|
// In theory, we could check this occurrence with std::same_as and std::enabled_if but it is C++14
|
||||||
// and relatively ugly and hard to read.
|
// and relatively ugly and hard to read.
|
||||||
#ifndef SIMDJSON_REGULAR_VISUAL_STUDIO
|
#ifndef SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||||
simdjson_inline explicit simd8(const uint8x16_t other): simd8(vreinterpretq_s8_u8(other)) {}
|
simdjson_inline explicit simd8(const simd_t other): simd8(vreinterpretq_s8_u8(other)) {}
|
||||||
#endif
|
#endif
|
||||||
simdjson_inline explicit operator simd8<uint8_t>() const { return vreinterpretq_u8_s8(this->value); }
|
simdjson_inline explicit operator simd8<uint8_t>() const { return vreinterpretq_u8_s8(this->value); }
|
||||||
|
|
||||||
@@ -424,10 +428,13 @@ simdjson_inline int8x16_t make_int8x16_t(int8_t x1, int8_t x2, int8_t x3, int
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Perform a lookup assuming no value is larger than 16
|
// Perform a lookup assuming no value is larger than 16
|
||||||
template<typename L>
|
simdjson_inline simd8<int8_t> lookup_16(simd8<int8_t> lookup_table) const {
|
||||||
simdjson_inline simd8<L> lookup_16(simd8<L> lookup_table) const {
|
|
||||||
return lookup_table.apply_lookup_16_to(*this);
|
return lookup_table.apply_lookup_16_to(*this);
|
||||||
}
|
}
|
||||||
|
// Perform a lookup based on the lower 4 bits of each lane, returning 0 for values with a high bit of 1.
|
||||||
|
simdjson_inline simd8<int8_t> lookup_low_nibble_ascii(simd8<int8_t> lookup_table) const {
|
||||||
|
return lookup_table.apply_lookup_16_to(*this & 0b10001111);
|
||||||
|
}
|
||||||
template<typename L>
|
template<typename L>
|
||||||
simdjson_inline simd8<L> lookup_16(
|
simdjson_inline simd8<L> lookup_16(
|
||||||
L replace0, L replace1, L replace2, L replace3,
|
L replace0, L replace1, L replace2, L replace3,
|
||||||
@@ -460,6 +467,8 @@ simdjson_inline int8x16_t make_int8x16_t(int8_t x1, int8_t x2, int8_t x3, int
|
|||||||
|
|
||||||
simdjson_inline simd8x64(const simd8<T> chunk0, const simd8<T> chunk1, const simd8<T> chunk2, const simd8<T> chunk3) : chunks{chunk0, chunk1, chunk2, chunk3} {}
|
simdjson_inline simd8x64(const simd8<T> chunk0, const simd8<T> chunk1, const simd8<T> chunk2, const simd8<T> chunk3) : chunks{chunk0, chunk1, chunk2, chunk3} {}
|
||||||
simdjson_inline simd8x64(const T ptr[64]) : chunks{simd8<T>::load(ptr), simd8<T>::load(ptr+16), simd8<T>::load(ptr+32), simd8<T>::load(ptr+48)} {}
|
simdjson_inline simd8x64(const T ptr[64]) : chunks{simd8<T>::load(ptr), simd8<T>::load(ptr+16), simd8<T>::load(ptr+32), simd8<T>::load(ptr+48)} {}
|
||||||
|
simdjson_inline simd8x64(simd8x64<T>&& o) noexcept = default;
|
||||||
|
simdjson_inline simd8x64<T>& operator=(simd8x64<T>&& other) noexcept = default;
|
||||||
|
|
||||||
simdjson_inline void store(T ptr[64]) const {
|
simdjson_inline void store(T ptr[64]) const {
|
||||||
this->chunks[0].store(ptr+sizeof(simd8<T>)*0);
|
this->chunks[0].store(ptr+sizeof(simd8<T>)*0);
|
||||||
@@ -486,19 +495,19 @@ 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 simd_t bit_mask = 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
|
||||||
);
|
);
|
||||||
#else
|
#else
|
||||||
const uint8x16_t bit_mask = {
|
const simd_t bit_mask = {
|
||||||
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
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
// Add each of the elements next to each other, successively, to stuff each 8 byte mask into one.
|
// Add each of the elements next to each other, successively, to stuff each 8 byte mask into one.
|
||||||
uint8x16_t sum0 = vpaddq_u8(this->chunks[0] & bit_mask, this->chunks[1] & bit_mask);
|
simd_t sum0 = vpaddq_u8(this->chunks[0] & bit_mask, this->chunks[1] & bit_mask);
|
||||||
uint8x16_t sum1 = vpaddq_u8(this->chunks[2] & bit_mask, this->chunks[3] & bit_mask);
|
simd_t sum1 = vpaddq_u8(this->chunks[2] & bit_mask, this->chunks[3] & bit_mask);
|
||||||
sum0 = vpaddq_u8(sum0, sum1);
|
sum0 = vpaddq_u8(sum0, sum1);
|
||||||
sum0 = vpaddq_u8(sum0, sum0);
|
sum0 = vpaddq_u8(sum0, sum0);
|
||||||
return vgetq_lane_u64(vreinterpretq_u64_u8(sum0), 0);
|
return vgetq_lane_u64(vreinterpretq_u64_u8(sum0), 0);
|
||||||
@@ -514,6 +523,24 @@ simdjson_inline int8x16_t make_int8x16_t(int8_t x1, int8_t x2, int8_t x3, int
|
|||||||
).to_bitmask();
|
).to_bitmask();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
simdjson_inline simd8x64<T> lookup_16(const simd8<T>& lookup_table) const {
|
||||||
|
return {
|
||||||
|
this->chunks[0].lookup_16(lookup_table),
|
||||||
|
this->chunks[1].lookup_16(lookup_table),
|
||||||
|
this->chunks[2].lookup_16(lookup_table),
|
||||||
|
this->chunks[3].lookup_16(lookup_table)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
simdjson_inline simd8x64<T> lookup_low_nibble_ascii(const simd8<T>& lookup_table) const {
|
||||||
|
return {
|
||||||
|
this->chunks[0].lookup_low_nibble_ascii(lookup_table),
|
||||||
|
this->chunks[1].lookup_low_nibble_ascii(lookup_table),
|
||||||
|
this->chunks[2].lookup_low_nibble_ascii(lookup_table),
|
||||||
|
this->chunks[3].lookup_low_nibble_ascii(lookup_table)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
simdjson_inline uint64_t lteq(const T m) const {
|
simdjson_inline uint64_t lteq(const T m) const {
|
||||||
const simd8<T> mask = simd8<T>::splat(m);
|
const simd8<T> mask = simd8<T>::splat(m);
|
||||||
return simd8x64<bool>(
|
return simd8x64<bool>(
|
||||||
@@ -523,11 +550,138 @@ simdjson_inline int8x16_t make_int8x16_t(int8_t x1, int8_t x2, int8_t x3, int
|
|||||||
this->chunks[3] <= mask
|
this->chunks[3] <= mask
|
||||||
).to_bitmask();
|
).to_bitmask();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
simdjson_inline simd8x64<T> operator&(const simd8x64<T>& other) const {
|
||||||
|
return {
|
||||||
|
this->chunks[0] & other.chunks[0],
|
||||||
|
this->chunks[1] & other.chunks[1],
|
||||||
|
this->chunks[2] & other.chunks[2],
|
||||||
|
this->chunks[3] & other.chunks[3]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
simdjson_inline simd8x64<T> operator&(const simd8<T>& other) const {
|
||||||
|
return {
|
||||||
|
this->chunks[0] & other,
|
||||||
|
this->chunks[1] & other,
|
||||||
|
this->chunks[2] & other,
|
||||||
|
this->chunks[3] & other
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
simdjson_inline simd8x64<T> operator|(const simd8x64<T>& other) const {
|
||||||
|
return {
|
||||||
|
this->chunks[0] | other.chunks[0],
|
||||||
|
this->chunks[1] | other.chunks[1],
|
||||||
|
this->chunks[2] | other.chunks[2],
|
||||||
|
this->chunks[3] | other.chunks[3]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
simdjson_inline simd8x64<T> operator|(const simd8<T>& other) const {
|
||||||
|
return {
|
||||||
|
this->chunks[0] | other,
|
||||||
|
this->chunks[1] | other,
|
||||||
|
this->chunks[2] | other,
|
||||||
|
this->chunks[3] | other
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
simdjson_inline simd8x64<T> operator^(const simd8x64<T>& other) const {
|
||||||
|
return {
|
||||||
|
this->chunks[0] ^ other.chunks[0],
|
||||||
|
this->chunks[1] ^ other.chunks[1],
|
||||||
|
this->chunks[2] ^ other.chunks[2],
|
||||||
|
this->chunks[3] ^ other.chunks[3]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
simdjson_inline simd8x64<T> operator^(const simd8<T>& other) const {
|
||||||
|
return {
|
||||||
|
this->chunks[0] ^ other,
|
||||||
|
this->chunks[1] ^ other,
|
||||||
|
this->chunks[2] ^ other,
|
||||||
|
this->chunks[3] ^ other
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
simdjson_inline simd8x64<T> bit_andnot(const simd8x64<T>& other) const {
|
||||||
|
return {
|
||||||
|
this->chunks[0].bit_andnot(other.chunks[0]),
|
||||||
|
this->chunks[1].bit_andnot(other.chunks[1]),
|
||||||
|
this->chunks[2].bit_andnot(other.chunks[2]),
|
||||||
|
this->chunks[3].bit_andnot(other.chunks[3])
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
simdjson_inline simd8x64<T> bit_andnot(const simd8<T>& other) const {
|
||||||
|
return {
|
||||||
|
this->chunks[0].bit_andnot(other),
|
||||||
|
this->chunks[1].bit_andnot(other),
|
||||||
|
this->chunks[2].bit_andnot(other),
|
||||||
|
this->chunks[3].bit_andnot(other)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <int N>
|
||||||
|
simdjson_inline simd8x64<T> shr() const noexcept {
|
||||||
|
return {
|
||||||
|
this->chunks[0].template shr<N>(),
|
||||||
|
this->chunks[1].template shr<N>(),
|
||||||
|
this->chunks[2].template shr<N>(),
|
||||||
|
this->chunks[3].template shr<N>()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <int N>
|
||||||
|
simdjson_inline simd8x64<T> shl() const noexcept {
|
||||||
|
return {
|
||||||
|
this->chunks[0].template shl<N>(),
|
||||||
|
this->chunks[1].template shl<N>(),
|
||||||
|
this->chunks[2].template shl<N>(),
|
||||||
|
this->chunks[3].template shl<N>()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
simdjson_inline simd8x64<bool> any_bits_set(const simd8<T>& bits) const {
|
||||||
|
return {
|
||||||
|
this->chunks[0].any_bits_set(bits),
|
||||||
|
this->chunks[1].any_bits_set(bits),
|
||||||
|
this->chunks[2].any_bits_set(bits),
|
||||||
|
this->chunks[3].any_bits_set(bits)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
simdjson_inline simd8x64<bool> any_bits_set(const simd8x64<T>& bits) const {
|
||||||
|
return {
|
||||||
|
this->chunks[0].any_bits_set(bits.chunks[0]),
|
||||||
|
this->chunks[1].any_bits_set(bits.chunks[1]),
|
||||||
|
this->chunks[2].any_bits_set(bits.chunks[2]),
|
||||||
|
this->chunks[3].any_bits_set(bits.chunks[3])
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
simdjson_inline simd8x64<bool> no_bits_set(const simd8<T>& bits) const {
|
||||||
|
return {
|
||||||
|
this->chunks[0].no_bits_set(bits),
|
||||||
|
this->chunks[1].no_bits_set(bits),
|
||||||
|
this->chunks[2].no_bits_set(bits),
|
||||||
|
this->chunks[3].no_bits_set(bits)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
simdjson_inline simd8x64<bool> no_bits_set(const simd8x64<T>& bits) const {
|
||||||
|
return {
|
||||||
|
this->chunks[0].no_bits_set(bits.chunks[0]),
|
||||||
|
this->chunks[1].no_bits_set(bits.chunks[1]),
|
||||||
|
this->chunks[2].no_bits_set(bits.chunks[2]),
|
||||||
|
this->chunks[3].no_bits_set(bits.chunks[3])
|
||||||
|
};
|
||||||
|
}
|
||||||
}; // struct simd8x64<T>
|
}; // struct simd8x64<T>
|
||||||
|
|
||||||
} // namespace simd
|
} // namespace simd
|
||||||
} // unnamed namespace
|
} // namespace arm64
|
||||||
} // namespace SIMDJSON_IMPLEMENTATION
|
|
||||||
} // namespace simdjson
|
} // namespace simdjson
|
||||||
|
|
||||||
#endif // SIMDJSON_ARM64_SIMD_H
|
#endif // SIMDJSON_ARM64_SIMD_H
|
||||||
|
|||||||
+11
-9
@@ -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/bitmask.h"
|
||||||
|
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
|
||||||
namespace simdjson {
|
namespace simdjson {
|
||||||
namespace SIMDJSON_IMPLEMENTATION {
|
namespace arm64 {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
using namespace simd;
|
using namespace simd;
|
||||||
@@ -19,8 +21,8 @@ public:
|
|||||||
|
|
||||||
simdjson_inline bool has_quote_first() { return ((bs_bits - 1) & quote_bits) != 0; }
|
simdjson_inline bool has_quote_first() { return ((bs_bits - 1) & quote_bits) != 0; }
|
||||||
simdjson_inline bool has_backslash() { return bs_bits != 0; }
|
simdjson_inline bool has_backslash() { return bs_bits != 0; }
|
||||||
simdjson_inline int quote_index() { return trailing_zeroes(quote_bits); }
|
simdjson_inline int quote_index() { return bitmask::trailing_zeroes(quote_bits); }
|
||||||
simdjson_inline int backslash_index() { return trailing_zeroes(bs_bits); }
|
simdjson_inline int backslash_index() { return bitmask::trailing_zeroes(bs_bits); }
|
||||||
|
|
||||||
uint32_t bs_bits;
|
uint32_t bs_bits;
|
||||||
uint32_t quote_bits;
|
uint32_t quote_bits;
|
||||||
@@ -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
|
||||||
@@ -180,6 +167,41 @@ constexpr size_t DEFAULT_MAX_DEPTH = 1024;
|
|||||||
#define simdjson_inline simdjson_really_inline
|
#define simdjson_inline simdjson_really_inline
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef simdjson_constexpr
|
||||||
|
#if __cpp_constexpr
|
||||||
|
#define simdjson_constexpr constexpr simdjson_inline
|
||||||
|
#else
|
||||||
|
#define simdjson_constexpr simdjson_inline
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
// simdjson_constexpr
|
||||||
|
|
||||||
|
#ifndef simdjson_consteval
|
||||||
|
#if __cpp_consteval
|
||||||
|
#define simdjson_consteval consteval simdjson_inline
|
||||||
|
#else
|
||||||
|
#define simdjson_consteval simdjson_constexpr
|
||||||
|
#endif
|
||||||
|
#endif // simdjson_consteval
|
||||||
|
|
||||||
|
#ifndef simdjson_constinit
|
||||||
|
#if __cpp_constinit
|
||||||
|
#define simdjson_constinit constinit
|
||||||
|
#elif __cpp_consteval
|
||||||
|
#define simdjson_constinit consteval
|
||||||
|
#else
|
||||||
|
#define simdjson_constinit constexpr
|
||||||
|
#endif
|
||||||
|
#endif // simdjson_constinit
|
||||||
|
|
||||||
|
#ifndef simdjson_if_constexpr
|
||||||
|
#if SIMDJSON_CPLUSPLUS17
|
||||||
|
#define simdjson_if_constexpr constexpr
|
||||||
|
#else
|
||||||
|
#define simdjson_if_constexpr
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#if SIMDJSON_VISUAL_STUDIO
|
#if SIMDJSON_VISUAL_STUDIO
|
||||||
/**
|
/**
|
||||||
* Windows users need to do some extra work when building
|
* Windows users need to do some extra work when building
|
||||||
@@ -322,7 +344,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 +354,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 {
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|
||||||
@@ -438,4 +444,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
|
||||||
@@ -537,7 +528,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,12 +1,16 @@
|
|||||||
#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>
|
||||||
|
|
||||||
namespace simdjson {
|
namespace simdjson {
|
||||||
@@ -236,4 +240,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.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|
||||||
|
|||||||
@@ -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/bitmask.h"
|
||||||
|
#include "simdjson/fallback/stringparsing_defs.h"
|
||||||
|
#include "simdjson/fallback/numberparsing_defs.h"
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
#ifndef SIMDJSON_FALLBACK_BITMANIPULATION_H
|
#ifndef SIMDJSON_FALLBACK_BITMASK_H
|
||||||
#define SIMDJSON_FALLBACK_BITMANIPULATION_H
|
#define SIMDJSON_FALLBACK_BITMASK_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 bitmask {
|
||||||
|
|
||||||
#if defined(_MSC_VER) && !defined(_M_ARM64) && !defined(_M_X64)
|
#if defined(_MSC_VER) && !defined(_M_ARM64) && !defined(_M_X64)
|
||||||
static inline unsigned char _BitScanForward64(unsigned long* ret, uint64_t x) {
|
static inline unsigned char _BitScanForward64(unsigned long* ret, uint64_t x) {
|
||||||
@@ -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
|
||||||
@@ -0,0 +1,303 @@
|
|||||||
|
#ifndef SIMDJSON_GENERIC_SIMD_LOOKUP_TABLE_H
|
||||||
|
|
||||||
|
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
#define SIMDJSON_GENERIC_SIMD_LOOKUP_TABLE_H
|
||||||
|
#include "simdjson/generic/base.h"
|
||||||
|
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
|
||||||
|
namespace simdjson {
|
||||||
|
namespace SIMDJSON_IMPLEMENTATION {
|
||||||
|
namespace simd {
|
||||||
|
|
||||||
|
template <typename T = uint8_t>
|
||||||
|
struct simd8_buffer {
|
||||||
|
T buf[simd8<T>::LANES] = {0};
|
||||||
|
simdjson_consteval T& operator[](size_t i) noexcept { return buf[i]; }
|
||||||
|
simdjson_consteval T operator[](size_t i) const noexcept { return buf[i]; }
|
||||||
|
simdjson_inline operator simd8<T>() const noexcept { return buf; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct nibble_range;
|
||||||
|
|
||||||
|
struct byte_range {
|
||||||
|
struct _exclusive{};
|
||||||
|
static simdjson_constinit _exclusive exclusive{};
|
||||||
|
|
||||||
|
simdjson_consteval byte_range(uint8_t start, uint16_t end, const _exclusive&) noexcept : _start{start}, _end{end} {
|
||||||
|
SIMDJSON_ASSUME(start < end && end <= 256);
|
||||||
|
}
|
||||||
|
simdjson_consteval byte_range(uint8_t first, uint8_t last) noexcept : byte_range(first, static_cast<uint16_t>(last+1), exclusive) {}
|
||||||
|
simdjson_consteval byte_range(uint8_t first) noexcept : byte_range(first, first) {}
|
||||||
|
|
||||||
|
simdjson_consteval size_t size() const noexcept { return static_cast<size_t>(_end - _start); }
|
||||||
|
simdjson_consteval byte_range operator|(const byte_range& other) const noexcept {
|
||||||
|
SIMDJSON_ASSUME((_end + 1 >= other._start) || (other._end + 1 >= _start));
|
||||||
|
return {std::min(_start, other._start), std::max(_end, other._end), exclusive};
|
||||||
|
}
|
||||||
|
|
||||||
|
simdjson_consteval bool includes(uint8_t byte) const noexcept { return _start <= byte && byte < _end; }
|
||||||
|
|
||||||
|
struct nibble_iter {
|
||||||
|
int nibble;
|
||||||
|
const int last_nibble;
|
||||||
|
simdjson_consteval nibble_iter& operator++() noexcept {
|
||||||
|
if (nibble == last_nibble) {
|
||||||
|
nibble = -1;
|
||||||
|
} else {
|
||||||
|
++nibble;
|
||||||
|
nibble %= 16;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
simdjson_consteval nibble_iter operator++(int) noexcept { auto copy = *this; ++*this; return copy; }
|
||||||
|
simdjson_consteval bool operator==(const nibble_iter& other) const noexcept { return nibble == other.nibble; }
|
||||||
|
simdjson_consteval bool operator!=(const nibble_iter& other) const noexcept { return nibble != other.nibble; }
|
||||||
|
simdjson_consteval uint8_t operator*() const noexcept { return static_cast<uint8_t>(nibble); }
|
||||||
|
simdjson_consteval nibble_iter begin() const noexcept { return *this; }
|
||||||
|
simdjson_consteval nibble_iter end() const noexcept { return {-1, last_nibble}; }
|
||||||
|
};
|
||||||
|
|
||||||
|
simdjson_consteval nibble_iter nibble(int shift) const noexcept {
|
||||||
|
SIMDJSON_ASSUME(_start < _end);
|
||||||
|
auto first_nibble = _start >> shift;
|
||||||
|
auto last_nibble = (_end-1) >> shift;
|
||||||
|
if ((last_nibble - first_nibble) >= 16) { return {0x00, 0x0F}; }
|
||||||
|
return {static_cast<uint8_t>(first_nibble & 0x0F), static_cast<uint8_t>(last_nibble & 0x0F)};
|
||||||
|
}
|
||||||
|
|
||||||
|
struct _iter {
|
||||||
|
uint16_t value;
|
||||||
|
simdjson_consteval _iter& operator++() noexcept { ++value; return *this; }
|
||||||
|
simdjson_consteval _iter operator++(int) noexcept { auto copy = *this; ++*this; return copy; }
|
||||||
|
simdjson_consteval bool operator==(const _iter& other) const noexcept { return value == other.value; }
|
||||||
|
simdjson_consteval bool operator!=(const _iter& other) const noexcept { return value != other.value; }
|
||||||
|
simdjson_consteval uint8_t operator*() const noexcept { return static_cast<uint8_t>(value); }
|
||||||
|
};
|
||||||
|
|
||||||
|
simdjson_consteval _iter begin() const noexcept { return _iter{_start}; }
|
||||||
|
simdjson_consteval _iter end() const noexcept { return _iter{_end}; }
|
||||||
|
|
||||||
|
uint8_t _start;
|
||||||
|
const uint16_t _end;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
struct _lookup_entry_range;
|
||||||
|
|
||||||
|
struct _lookup_entry : byte_range {
|
||||||
|
const uint8_t value;
|
||||||
|
|
||||||
|
simdjson_consteval _lookup_entry(const byte_range& bytes, uint8_t value) noexcept
|
||||||
|
: byte_range{bytes}, value{value} {}
|
||||||
|
};
|
||||||
|
|
||||||
|
simdjson_consteval simd8_buffer<uint8_t> _make_nibble_lookup_table(
|
||||||
|
std::initializer_list<_lookup_entry> entries, int shift) noexcept {
|
||||||
|
// Make the buffer
|
||||||
|
simd8_buffer<uint8_t> buf;
|
||||||
|
for (auto entry : entries) {
|
||||||
|
for (auto key : entry.nibble(shift)) {
|
||||||
|
// Repeat the value over and over for longer simd types.
|
||||||
|
for (uint8_t k = key; k < sizeof(buf); k += 16) { buf[k] |= entry.value; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // unnamed namespace
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Byte lookup table where the key is the high 4 bits of the input, and the value is an
|
||||||
|
* arbitrary byte.
|
||||||
|
*
|
||||||
|
* - Unmatched values yield 0.
|
||||||
|
* - Multiple keys may yield the same value.
|
||||||
|
* - Multiple bytes with the same high 4 bits may NOT yield different values.
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* enum ops_t : uint8_t {
|
||||||
|
* COMMA = 1,
|
||||||
|
* COLON = 2,
|
||||||
|
* BRACKET = 3,
|
||||||
|
* CURLY = 4
|
||||||
|
* };
|
||||||
|
* static constinit const high_nibble_lookup OPS(
|
||||||
|
* {',', COMMA},
|
||||||
|
* {':', COLON},
|
||||||
|
* {'[', BRACKET},
|
||||||
|
* {']', BRACKET},
|
||||||
|
* {'{', CURLY},
|
||||||
|
* {'}', CURLY}
|
||||||
|
* );
|
||||||
|
* simd8<uint8_t> lookup_ops(simd8<uint8_t>& operators) { return OPS[operators]; }
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
struct high_nibble_lookup {
|
||||||
|
const simd8_buffer<uint8_t> table;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a nibble lookup table from the high bits of the input to the output.
|
||||||
|
*
|
||||||
|
* @param entries A list of {key, value} pairs (e.g. {'a', 10}).
|
||||||
|
* @error asserts if multiple keys have the same high 4 bits but different values.
|
||||||
|
*/
|
||||||
|
simdjson_consteval high_nibble_lookup(std::initializer_list<_lookup_entry> entries) noexcept
|
||||||
|
: table{_make_nibble_lookup_table(entries, 4)} {}
|
||||||
|
simdjson_consteval high_nibble_lookup(const simd8_buffer<uint8_t>& table) noexcept : table(table) {}
|
||||||
|
|
||||||
|
/** Look up the value corresponding the higher 4 bits of each input byte, and return it. */
|
||||||
|
simdjson_inline simd8<uint8_t> operator[](const simd8<uint8_t>& keys) const noexcept { return lookup(keys); }
|
||||||
|
/** Look up the value corresponding the higher 4 bits of each input byte, and return it. */
|
||||||
|
simdjson_inline simd8<uint8_t> lookup(const simd8<uint8_t>& keys) const noexcept { return lookup_low(keys.shr<4>()); }
|
||||||
|
/**
|
||||||
|
* Look up the value in the table assuming the high 4 key bits are stored in the lower 4 bits.
|
||||||
|
* @pre all indexes be less than 16.
|
||||||
|
*/
|
||||||
|
simdjson_inline simd8<uint8_t> lookup_low(const simd8<uint8_t>& shifted_keys) const noexcept {
|
||||||
|
return shifted_keys.lookup_16(table);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Look up the value in the table assuming the high 4 key bits are stored in the lower 4 bits.
|
||||||
|
* @pre all indexes be less than 16.
|
||||||
|
*/
|
||||||
|
simdjson_inline simd8x64<uint8_t> lookup_low(const simd8x64<uint8_t>& shifted_keys) const noexcept {
|
||||||
|
return shifted_keys.lookup_16(table);
|
||||||
|
}
|
||||||
|
/** Look up the value corresponding the higher 4 bits of each input byte, and return it. */
|
||||||
|
simdjson_inline simd8x64<uint8_t> lookup(const simd8x64<uint8_t>& keys) const noexcept { return lookup_low(keys.shr<4>()); }
|
||||||
|
/** Look up the value corresponding the higher 4 bits of each input byte, and return it. */
|
||||||
|
simdjson_inline simd8x64<uint8_t> operator[](const simd8x64<uint8_t>& keys) const noexcept { return lookup(keys); }
|
||||||
|
|
||||||
|
simdjson_consteval uint8_t operator[](uint8_t key) const noexcept { return lookup(key); }
|
||||||
|
simdjson_consteval uint8_t lookup(uint8_t key) const noexcept { return table[key >> 4]; }
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Byte lookup table where the key is the low 4 bits of the input, and the value is an
|
||||||
|
* arbitrary byte.
|
||||||
|
*
|
||||||
|
* - Unmatched values yield 0.
|
||||||
|
* - Multiple keys may yield the same value.
|
||||||
|
* - Multiple bytes with the same low 4 bits may NOT yield different values.
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* enum ops_t : uint8_t {
|
||||||
|
* COMMA = 1,
|
||||||
|
* COLON = 2,
|
||||||
|
* BRACKET = 3,
|
||||||
|
* CURLY = 4
|
||||||
|
* };
|
||||||
|
* static constinit const high_nibble_lookup OPS(
|
||||||
|
* {',', COMMA},
|
||||||
|
* {':', COLON},
|
||||||
|
* {'[', BRACKET},
|
||||||
|
* {']', BRACKET},
|
||||||
|
* {'{', CURLY},
|
||||||
|
* {'}', CURLY}
|
||||||
|
* );
|
||||||
|
* simd8<uint8_t> lookup_ops(simd8<uint8_t>& operators) { return OPS[operators]; }
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
struct low_nibble_lookup {
|
||||||
|
const simd8_buffer<uint8_t> table;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a nibble lookup table from the low bits of the input to the output.
|
||||||
|
*
|
||||||
|
* @param entries A list of {key, value} pairs (e.g. {'a', 0}).
|
||||||
|
* @error asserts if multiple keys have the same low 4 bits but different values.
|
||||||
|
*/
|
||||||
|
simdjson_consteval low_nibble_lookup(std::initializer_list<_lookup_entry> entries) noexcept
|
||||||
|
: table{_make_nibble_lookup_table(entries, 0)} {}
|
||||||
|
simdjson_consteval low_nibble_lookup(const simd8_buffer<uint8_t>& table) noexcept : table(table) {}
|
||||||
|
|
||||||
|
/** Look up the value corresponding the lower 4 bits of each input byte, and return it. */
|
||||||
|
simdjson_inline simd8<uint8_t> operator[](const simd8<uint8_t>& keys) const noexcept { return lookup(keys); }
|
||||||
|
/** Look up the value corresponding the lower 4 bits of each input byte, and return it. */
|
||||||
|
simdjson_inline simd8<uint8_t> lookup(const simd8<uint8_t>& keys) const noexcept {
|
||||||
|
return keys.lookup_low_nibble_ascii(table);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Look up the value in the table. Behavior is system-dependent for indexes greater than 16.
|
||||||
|
*
|
||||||
|
* - On some platforms like arm64, indexes greater than 16 will not match anything in the table.
|
||||||
|
* - On platforms like Intel, index bits 4-6 will be ignored, but if the high bit is set, it
|
||||||
|
* will not match anything in the table. greater than 16 will be ignored, *except* if the high bit is 1,
|
||||||
|
*/
|
||||||
|
simdjson_inline simd8<uint8_t> lookup_unsafe(const simd8<uint8_t>& keys) const noexcept {
|
||||||
|
return keys.lookup_16(table);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Look up the value corresponding the lower 4 bits of each input byte, and return it. */
|
||||||
|
simdjson_inline simd8x64<uint8_t> operator[](const simd8x64<uint8_t>& keys) const noexcept { return lookup(keys); }
|
||||||
|
/** Look up the value corresponding the lower 4 bits of each input byte, and return it. */
|
||||||
|
simdjson_inline simd8x64<uint8_t> lookup(const simd8x64<uint8_t>& keys) const noexcept {
|
||||||
|
return keys.lookup_low_nibble_ascii(table);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Look up the value in the table. Behavior is system-dependent for indexes greater than 16.
|
||||||
|
*
|
||||||
|
* - On some platforms like arm64, indexes greater than 16 will not match anything in the table.
|
||||||
|
* - On platforms like Intel, index bits 4-6 will be ignored, but if the high bit is set, it
|
||||||
|
* will not match anything in the table. greater than 16 will be ignored, *except* if the high bit is 1,
|
||||||
|
*/
|
||||||
|
simdjson_inline simd8x64<uint8_t> lookup_unsafe(const simd8x64<uint8_t>& low_keys) const noexcept {
|
||||||
|
return low_keys.lookup_16(table);
|
||||||
|
}
|
||||||
|
|
||||||
|
simdjson_consteval uint8_t operator[](uint8_t key) const noexcept { return lookup(key); }
|
||||||
|
simdjson_consteval uint8_t lookup(uint8_t key) const noexcept { return table[key & 0x0F]; }
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Classifies bytes by looking up their lower 4 bits, then their high 4 bits, and &'ing the
|
||||||
|
* results together.
|
||||||
|
*
|
||||||
|
* Pass the bytes you want to match, and the classifications you want for them.
|
||||||
|
*/
|
||||||
|
struct byte_classifier {
|
||||||
|
const low_nibble_lookup low;
|
||||||
|
const high_nibble_lookup high;
|
||||||
|
simdjson_consteval byte_classifier(std::initializer_list<_lookup_entry> entries)
|
||||||
|
: low{entries}, high{entries} {}
|
||||||
|
|
||||||
|
simdjson_inline simd8<uint8_t> classify(const simd8<uint8_t>& bytes) const noexcept {
|
||||||
|
return low.lookup(bytes) & high.lookup(bytes);
|
||||||
|
}
|
||||||
|
simdjson_inline simd8x64<uint8_t> classify(const simd8x64<uint8_t>& bytes) const noexcept {
|
||||||
|
auto low_lookup = low.lookup(bytes); // 3 (+simd:N)
|
||||||
|
auto high_lookup = high.lookup(bytes); // 6 (+simd:2N)
|
||||||
|
return low_lookup & high_lookup; // 3 (+simd:N)
|
||||||
|
// critical path: 9 (+simd:4N)
|
||||||
|
}
|
||||||
|
simdjson_consteval uint8_t classify(uint8_t byte) const noexcept {
|
||||||
|
return low.lookup(byte) & high.lookup(byte);
|
||||||
|
}
|
||||||
|
|
||||||
|
simdjson_inline simd8<uint8_t> operator[](const simd8<uint8_t>& bytes) const noexcept { return classify(bytes); }
|
||||||
|
simdjson_inline simd8x64<uint8_t> operator[](const simd8x64<uint8_t>& bytes) const noexcept { return classify(bytes); }
|
||||||
|
simdjson_consteval uint8_t operator[](uint8_t byte) const noexcept { return classify(byte); }
|
||||||
|
|
||||||
|
simdjson_inline bool matches_correctly(std::initializer_list<_lookup_entry> entries) const noexcept {
|
||||||
|
uint8_t expected_output[256] = {};
|
||||||
|
for (auto entry : entries) {
|
||||||
|
for (uint8_t byte : entry) {
|
||||||
|
expected_output[byte] |= entry.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (uint8_t byte = 0; byte <= 0xFF; byte++) {
|
||||||
|
if (expected_output[byte] != classify(byte)) { return false; }
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace simd
|
||||||
|
} // namespace SIMDJSON_IMPLEMENTATION
|
||||||
|
} // namespace simdjson
|
||||||
|
|
||||||
|
#endif // SIMDJSON_GENERIC_SIMD_LOOKUP_TABLE_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)))
|
||||||
@@ -143,7 +143,7 @@ simdjson_inline bool compute_float_64(int64_t power, uint64_t i, bool negative,
|
|||||||
|
|
||||||
|
|
||||||
// We want the most significant bit of i to be 1. Shift if needed.
|
// We want the most significant bit of i to be 1. Shift if needed.
|
||||||
int lz = leading_zeroes(i);
|
int lz = bitmask::leading_zeroes(i);
|
||||||
i <<= lz;
|
i <<= lz;
|
||||||
|
|
||||||
|
|
||||||
@@ -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
|
||||||
@@ -199,7 +199,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 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
|
// At this point, we might need to add at most one to firstproduct, but this
|
||||||
@@ -1250,6 +1250,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 +1262,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
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
#include "simdjson/generic/ondemand/json_type-inl.h"
|
|
||||||
#include "simdjson/generic/ondemand/logger-inl.h"
|
|
||||||
#include "simdjson/generic/ondemand/raw_json_string-inl.h"
|
|
||||||
#include "simdjson/generic/ondemand/token_iterator-inl.h"
|
|
||||||
#include "simdjson/generic/ondemand/json_iterator-inl.h"
|
|
||||||
#include "simdjson/generic/ondemand/value_iterator-inl.h"
|
|
||||||
#include "simdjson/generic/ondemand/array_iterator-inl.h"
|
|
||||||
#include "simdjson/generic/ondemand/object_iterator-inl.h"
|
|
||||||
#include "simdjson/generic/ondemand/array-inl.h"
|
|
||||||
#include "simdjson/generic/ondemand/document-inl.h"
|
|
||||||
#include "simdjson/generic/ondemand/value-inl.h"
|
|
||||||
#include "simdjson/generic/ondemand/field-inl.h"
|
|
||||||
#include "simdjson/generic/ondemand/object-inl.h"
|
|
||||||
#include "simdjson/generic/ondemand/parser-inl.h"
|
|
||||||
#include "simdjson/generic/ondemand/document_stream-inl.h"
|
|
||||||
#include "simdjson/generic/ondemand/serialization-inl.h"
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
namespace simdjson {
|
|
||||||
namespace SIMDJSON_IMPLEMENTATION {
|
|
||||||
/**
|
|
||||||
* A fast, simple, DOM-like interface that parses JSON as you use it.
|
|
||||||
*
|
|
||||||
* Designed for maximum speed and a lower memory profile.
|
|
||||||
*/
|
|
||||||
namespace ondemand {
|
|
||||||
|
|
||||||
/** Represents the depth of a JSON value (number of nested arrays/objects). */
|
|
||||||
using depth_t = int32_t;
|
|
||||||
|
|
||||||
/** @copydoc simdjson::SIMDJSON_IMPLEMENTATION::numberparsing::number_type */
|
|
||||||
using number_type = simdjson::SIMDJSON_IMPLEMENTATION::numberparsing::number_type;
|
|
||||||
|
|
||||||
} // namespace ondemand
|
|
||||||
} // namespace SIMDJSON_IMPLEMENTATION
|
|
||||||
} // namespace simdjson
|
|
||||||
|
|
||||||
#include "simdjson/generic/ondemand/json_type.h"
|
|
||||||
#include "simdjson/generic/ondemand/token_position.h"
|
|
||||||
#include "simdjson/generic/ondemand/logger.h"
|
|
||||||
#include "simdjson/generic/ondemand/raw_json_string.h"
|
|
||||||
#include "simdjson/generic/ondemand/token_iterator.h"
|
|
||||||
#include "simdjson/generic/ondemand/json_iterator.h"
|
|
||||||
#include "simdjson/generic/ondemand/value_iterator.h"
|
|
||||||
#include "simdjson/generic/ondemand/array_iterator.h"
|
|
||||||
#include "simdjson/generic/ondemand/object_iterator.h"
|
|
||||||
#include "simdjson/generic/ondemand/array.h"
|
|
||||||
#include "simdjson/generic/ondemand/document.h"
|
|
||||||
#include "simdjson/generic/ondemand/value.h"
|
|
||||||
#include "simdjson/generic/ondemand/field.h"
|
|
||||||
#include "simdjson/generic/ondemand/object.h"
|
|
||||||
#include "simdjson/generic/ondemand/parser.h"
|
|
||||||
#include "simdjson/generic/ondemand/document_stream.h"
|
|
||||||
#include "simdjson/generic/ondemand/serialization.h"
|
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
#if defined(SIMDJSON_CONDITIONAL_INCLUDE) && !defined(SIMDJSON_GENERIC_ONDEMAND_DEPENDENCIES_H)
|
||||||
|
#error simdjson/generic/ondemand/dependencies.h must be included before simdjson/generic/ondemand/amalgamated.h!
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Stuff other things depend on
|
||||||
|
#include "simdjson/generic/ondemand/base.h"
|
||||||
|
#include "simdjson/generic/ondemand/value_iterator.h"
|
||||||
|
#include "simdjson/generic/ondemand/value.h"
|
||||||
|
#include "simdjson/generic/ondemand/logger.h"
|
||||||
|
#include "simdjson/generic/ondemand/token_iterator.h"
|
||||||
|
#include "simdjson/generic/ondemand/json_iterator.h"
|
||||||
|
#include "simdjson/generic/ondemand/json_type.h"
|
||||||
|
#include "simdjson/generic/ondemand/raw_json_string.h"
|
||||||
|
#include "simdjson/generic/ondemand/parser.h"
|
||||||
|
|
||||||
|
// All other declarations
|
||||||
|
#include "simdjson/generic/ondemand/array.h"
|
||||||
|
#include "simdjson/generic/ondemand/array_iterator.h"
|
||||||
|
#include "simdjson/generic/ondemand/document.h"
|
||||||
|
#include "simdjson/generic/ondemand/document_stream.h"
|
||||||
|
#include "simdjson/generic/ondemand/field.h"
|
||||||
|
#include "simdjson/generic/ondemand/object.h"
|
||||||
|
#include "simdjson/generic/ondemand/object_iterator.h"
|
||||||
|
#include "simdjson/generic/ondemand/serialization.h"
|
||||||
|
|
||||||
|
// Inline definitions
|
||||||
|
#include "simdjson/generic/ondemand/array-inl.h"
|
||||||
|
#include "simdjson/generic/ondemand/array_iterator-inl.h"
|
||||||
|
#include "simdjson/generic/ondemand/document-inl.h"
|
||||||
|
#include "simdjson/generic/ondemand/document_stream-inl.h"
|
||||||
|
#include "simdjson/generic/ondemand/field-inl.h"
|
||||||
|
#include "simdjson/generic/ondemand/json_iterator-inl.h"
|
||||||
|
#include "simdjson/generic/ondemand/json_type-inl.h"
|
||||||
|
#include "simdjson/generic/ondemand/logger-inl.h"
|
||||||
|
#include "simdjson/generic/ondemand/object-inl.h"
|
||||||
|
#include "simdjson/generic/ondemand/object_iterator-inl.h"
|
||||||
|
#include "simdjson/generic/ondemand/parser-inl.h"
|
||||||
|
#include "simdjson/generic/ondemand/raw_json_string-inl.h"
|
||||||
|
#include "simdjson/generic/ondemand/serialization-inl.h"
|
||||||
|
#include "simdjson/generic/ondemand/token_iterator-inl.h"
|
||||||
|
#include "simdjson/generic/ondemand/value-inl.h"
|
||||||
|
#include "simdjson/generic/ondemand/value_iterator-inl.h"
|
||||||
@@ -1,3 +1,15 @@
|
|||||||
|
#ifndef SIMDJSON_GENERIC_ONDEMAND_ARRAY_INL_H
|
||||||
|
|
||||||
|
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
#define SIMDJSON_GENERIC_ONDEMAND_ARRAY_INL_H
|
||||||
|
#include "simdjson/generic/ondemand/base.h"
|
||||||
|
#include "simdjson/generic/ondemand/array.h"
|
||||||
|
#include "simdjson/generic/ondemand/array_iterator-inl.h"
|
||||||
|
#include "simdjson/generic/ondemand/json_iterator.h"
|
||||||
|
#include "simdjson/generic/ondemand/value.h"
|
||||||
|
#include "simdjson/generic/ondemand/value_iterator-inl.h"
|
||||||
|
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
|
||||||
namespace simdjson {
|
namespace simdjson {
|
||||||
namespace SIMDJSON_IMPLEMENTATION {
|
namespace SIMDJSON_IMPLEMENTATION {
|
||||||
namespace ondemand {
|
namespace ondemand {
|
||||||
@@ -210,3 +222,5 @@ simdjson_inline simdjson_result<std::string_view> simdjson_result<SIMDJSON_IMPL
|
|||||||
return first.raw_json();
|
return first.raw_json();
|
||||||
}
|
}
|
||||||
} // namespace simdjson
|
} // namespace simdjson
|
||||||
|
|
||||||
|
#endif // SIMDJSON_GENERIC_ONDEMAND_ARRAY_INL_H
|
||||||
@@ -1,12 +1,16 @@
|
|||||||
#include "simdjson/error.h"
|
#ifndef SIMDJSON_GENERIC_ONDEMAND_ARRAY_H
|
||||||
|
|
||||||
|
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
#define SIMDJSON_GENERIC_ONDEMAND_ARRAY_H
|
||||||
|
#include "simdjson/generic/ondemand/base.h"
|
||||||
|
#include "simdjson/generic/implementation_simdjson_result_base.h"
|
||||||
|
#include "simdjson/generic/ondemand/value_iterator.h"
|
||||||
|
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
|
||||||
namespace simdjson {
|
namespace simdjson {
|
||||||
namespace SIMDJSON_IMPLEMENTATION {
|
namespace SIMDJSON_IMPLEMENTATION {
|
||||||
namespace ondemand {
|
namespace ondemand {
|
||||||
|
|
||||||
class value;
|
|
||||||
class document;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A forward-only JSON array.
|
* A forward-only JSON array.
|
||||||
*/
|
*/
|
||||||
@@ -191,3 +195,5 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
} // namespace simdjson
|
} // namespace simdjson
|
||||||
|
|
||||||
|
#endif // SIMDJSON_GENERIC_ONDEMAND_ARRAY_H
|
||||||
@@ -1,3 +1,13 @@
|
|||||||
|
#ifndef SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_INL_H
|
||||||
|
|
||||||
|
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
#define SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_INL_H
|
||||||
|
#include "simdjson/generic/ondemand/base.h"
|
||||||
|
#include "simdjson/generic/ondemand/array_iterator.h"
|
||||||
|
#include "simdjson/generic/ondemand/value-inl.h"
|
||||||
|
#include "simdjson/generic/ondemand/value_iterator-inl.h"
|
||||||
|
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
|
||||||
namespace simdjson {
|
namespace simdjson {
|
||||||
namespace SIMDJSON_IMPLEMENTATION {
|
namespace SIMDJSON_IMPLEMENTATION {
|
||||||
namespace ondemand {
|
namespace ondemand {
|
||||||
@@ -64,3 +74,5 @@ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_iterato
|
|||||||
}
|
}
|
||||||
|
|
||||||
} // namespace simdjson
|
} // namespace simdjson
|
||||||
|
|
||||||
|
#endif // SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_INL_H
|
||||||
@@ -1,13 +1,17 @@
|
|||||||
#include "simdjson/error.h"
|
#ifndef SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_H
|
||||||
|
|
||||||
|
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
#define SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_H
|
||||||
|
#include "simdjson/generic/implementation_simdjson_result_base.h"
|
||||||
|
#include "simdjson/generic/ondemand/base.h"
|
||||||
|
#include "simdjson/generic/ondemand/value_iterator.h"
|
||||||
|
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
|
||||||
|
|
||||||
namespace simdjson {
|
namespace simdjson {
|
||||||
namespace SIMDJSON_IMPLEMENTATION {
|
namespace SIMDJSON_IMPLEMENTATION {
|
||||||
namespace ondemand {
|
namespace ondemand {
|
||||||
|
|
||||||
class array;
|
|
||||||
class value;
|
|
||||||
class document;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A forward-only JSON array.
|
* A forward-only JSON array.
|
||||||
*
|
*
|
||||||
@@ -88,3 +92,5 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
} // namespace simdjson
|
} // namespace simdjson
|
||||||
|
|
||||||
|
#endif // SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_H
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user