Compare commits

...

99 Commits

Author SHA1 Message Date
John Keiser 8149284602 Revert string parsing to old algorithm 2023-08-31 01:40:42 -04:00
John Keiser 0e28a8312d Actually use new algorithm for borrows 2023-08-31 01:38:57 -04:00
John Keiser 04ab4bb4d9 Fix ctrl character detection 2023-08-31 00:46:33 -04:00
John Keiser 3960880a0d Just use the one struct 2023-08-30 20:45:30 -04:00
John Keiser e0f906da79 Consolidate classification methods 2023-08-30 20:07:23 -04:00
John Keiser 6a054395a6 Move classifications into a struct 2023-08-30 19:26:03 -04:00
John Keiser eac04c7324 Centralize classification 2023-08-30 15:31:02 -04:00
John Keiser 319b10acad Expose and use real quote, reducing register pressure 2023-08-30 15:24:23 -04:00
John Keiser d2d15255bc Move input reading near other input reading 2023-08-30 15:19:42 -04:00
John Keiser 5b7acd2aa7 Don't send or receive commas 2023-08-30 15:00:41 -04:00
John Keiser 61ef447595 Fix subtraction to use fewer instructions 2023-08-30 14:59:35 -04:00
John Keiser b524e29576 Restore UTF-8 algorithm to before lookup table 2023-08-29 18:25:20 -04:00
John Keiser a7b7bc2b69 Fix a few bugs 2023-08-29 18:25:20 -04:00
John Keiser 76dd137c87 Make it compile 2023-08-29 18:25:20 -04:00
John Keiser 52b2414281 Send commas 2023-08-29 18:25:20 -04:00
John Keiser 5d762fb67f Update numbers more 2023-08-29 18:25:20 -04:00
John Keiser 9dc70e8d9c Update latencies 2023-08-29 18:25:20 -04:00
John Keiser 589ef23b56 Better bitmask subtraction 2023-08-29 18:25:20 -04:00
John Keiser 4b1148384e More betterer simd 2023-08-29 18:25:20 -04:00
John Keiser 32afd34a90 Fix scanner to use actual bitmask/simd methods 2023-08-29 18:25:20 -04:00
John Keiser 70674d2dbd Add no_bits_set to simd8x64 2023-08-29 18:25:20 -04:00
John Keiser f594a49a4b Move bitmask methods into namespace, add subtract_borrow_out 2023-08-29 18:25:20 -04:00
John Keiser 54cbebfd29 Initial speculative parsing scanner 2023-08-29 18:25:20 -04:00
John Keiser c6e43a631c Add byte_classifier abstraction to make lookup tables readable. 2023-08-29 18:25:20 -04:00
John Keiser a8635c9b89 Use new eq_any for classification 2023-08-29 18:25:20 -04:00
John Keiser 075bfb173b Add eq_any() 2023-08-29 18:25:20 -04:00
John Keiser a88ad515c2 Define single simd_t for easier copy/paste 2023-08-29 18:25:20 -04:00
John Keiser 78b4c0aa6e Make simd constexpr 2023-08-29 18:25:20 -04:00
John Keiser 14ec0ca8f4 Merge pull request #2052 from simdjson/jkeiser/structural_indexer_step
Write out 4 structural indexes at a time instead of 8
2023-08-29 15:24:54 -07:00
John Keiser 8dabd02c3a Default to step = 4 2023-08-29 15:48:52 -04:00
Daniel Lemire c9692005fd This allows us to pass SIMDJSON_STRUCTURAL_INDEXER_STEP as a command-line option. (#2055) 2023-08-25 13:47:20 -04:00
Daniel Lemire 2e0a9397c9 Merge branch 'master' into jkeiser/structural_indexer_step 2023-08-25 11:34:13 -04:00
Daniel Lemire f7922075c3 Adding support for Apple event counters (#2054) 2023-08-25 11:33:24 -04:00
Daniel Lemire b2e20e04c9 Standard compatibility fixes (#2053)
* Standard compatibility fixes

* missing commit

* Should work.

* Fix.

* Fix.

* Should work now.

---------

Co-authored-by: Daniel Lemire <dlemire@lemire.me>
2023-08-25 10:18:02 -04:00
John Keiser adc9d18efd Change step for structural_indexes to 2 2023-08-23 19:02:05 -07:00
Daniel Lemire bf849e3619 Preparing release 2023-08-22 14:05:14 -04:00
Daniel Lemire c09e8dc225 Icelake processes 64 bytes at a time when processing strings. (#2050)
Co-authored-by: Daniel Lemire <dlemire@lemire.me>
2023-08-18 14:37:10 -04:00
Daniel Lemire 5bf585ef02 Fixing failing thread sanitizer (#2051) 2023-08-18 14:35:12 -04:00
Daniel Lemire caff09cafc Update iterate_many.md 2023-08-14 12:18:09 -04:00
Daniel Lemire f043db4dca Preparing release. 2023-08-02 16:01:39 -04:00
Daniel Lemire e3bd0828d1 Fix for issue 2045. (#2046)
* Fix for issue 2045.

* Retauring single-header code.
2023-08-02 16:00:45 -04:00
John Keiser 9408298e0e Merge pull request #2042 from simdjson/jkeiser/escape3
New escape algorithm with significantly less data dependency
2023-08-02 10:38:09 -07:00
John Keiser 573bbac2d2 Reamalgamate again 2023-08-02 08:28:35 -07:00
John Keiser ac78c625df simdjson_inline -> simdjson_really_inline 2023-08-02 08:28:05 -07:00
John Keiser 390a66c6e8 Make next_structurals inline 2023-08-02 08:28:05 -07:00
John Keiser 210e0a56a1 Reamalgamate 2023-08-02 08:28:05 -07:00
John Keiser 084f662f32 Don't use C++20 designated initializers 2023-08-02 08:28:05 -07:00
John Keiser c878ff2500 Fix compiler warnings 2023-08-02 08:28:05 -07:00
John Keiser 06afe9ecb3 New escape algorithm with significantly less data dependency 2023-08-02 08:28:05 -07:00
Daniel Lemire e658502adb We are having issues with llvm.sh (#2044) 2023-08-02 11:24:28 -04:00
Daniel Lemire 6e7d415040 These lines should not be necessary. (#2043) 2023-08-01 19:33:27 -04:00
John Keiser 2ccd5b9c97 Merge pull request #2039 from simdjson/jkeiser/more-headers
Disallow including headers from implementation files
2023-07-21 12:09:57 -07:00
Daniel Lemire 1cdcbf79b3 We do actually support legacy 32-bit systems, although not with fast kernels. (#2041) 2023-07-21 13:53:10 -04:00
Calum McConnell 7013ed98cc Peek(0) is an error on 32-bit systems, where pointers are indistinguishable from int32_t (#2040) 2023-07-21 13:52:53 -04:00
John Keiser b383c717d7 Have amalgamate.py verify it's actually amalgamating all the files 2023-07-20 15:11:52 -07:00
John Keiser b8743bced0 Fix amalgamate.py under python 3.7 2023-07-20 14:14:44 -07:00
John Keiser ae9ba2bed2 Rename SIMDJSON_AMALGAMATED to SIMDJSON_CONDITIONAL_INCLUDE 2023-07-20 11:43:19 -07:00
Daniel Lemire 939844d79f Adding tests for issue 2037. (#2038)
* Adding tests for issue 2037.

* Fixed typo

* Simplifying.
2023-07-20 14:11:33 -04:00
John Keiser 4f4e81668e Change all include paths to <> instead of "" to avoid relative path includes 2023-07-20 10:48:25 -07:00
John Keiser bb54946b78 Disallow including headers from implementation files 2023-07-20 10:01:22 -07:00
John Keiser 4dec6ed5a7 Merge pull request #2036 from simdjson/jkeiser/more-header-fixes
A few more header fixes
2023-07-18 10:26:40 -07:00
John Keiser 1dfd48195d Merge pull request #2035 from simdjson/jkeiser/sanitizer-ci
Run sanitizers in parallel
2023-07-17 23:37:34 -07:00
John Keiser 23afc6b695 Merge branch 'master' into jkeiser/sanitizer-ci 2023-07-17 16:09:20 -07:00
John Keiser e3cac71afe Enforce that dependencies.h and generic/*.h include the same dependencies. 2023-07-17 16:07:42 -07:00
John Keiser cbe562c1d5 Fix header define names for inline files 2023-07-17 13:55:07 -07:00
John Keiser 30437d0ff6 A few header fixes for dom and ondemand 2023-07-17 13:53:50 -07:00
John Keiser 1e97af7dfb Merge pull request #2031 from simdjson/jkeiser/vscode-green
Get headers compiling in editor
2023-07-17 13:07:20 -07:00
John Keiser 80bc9e5051 Run sanitizers in parallel 2023-07-17 12:57:50 -07:00
John Keiser a74e87df17 Merge pull request #2026 from Cuda-Chen/pretty-print-for-dom
Add pretty print for DOM
2023-07-17 12:38:20 -07:00
John Keiser 3274299647 Merge pull request #2030 from yongxiangng/lazy-log-error
Add info and error logging, defer log message evaluation
2023-07-17 12:38:05 -07:00
John Keiser 22ca25faa6 Reamalgamate; make amalgamation normalize paths 2023-07-17 11:27:43 -07:00
John Keiser 37399fd41b Merge pull request #2034 from simdjson/add_add_emul_for_32bits
Adding missing umul
2023-07-17 10:02:55 -07:00
Daniel Lemire a170145d5b Missing header. 2023-07-17 11:48:07 -04:00
Daniel Lemire 7d1d635883 Adding missing umul 2023-07-17 10:04:57 -04:00
John Keiser ddfa8ae928 Reamalgamate 2023-07-16 22:53:42 -07:00
John Keiser 25dfb078c7 A few random header include ordering fixes 2023-07-16 22:50:54 -07:00
John Keiser 9f0710e3ad Move full_multiplication to <implementation>/numberparsing_defs.h 2023-07-16 22:34:21 -07:00
John Keiser 19b9cd9b05 Explain new directory structure 2023-07-16 21:42:50 -07:00
John Keiser 7540248396 Include simdprune_tables.h in generic implementations 2023-07-16 19:19:10 -07:00
John Keiser ab09e96de9 Only use amalgamated.h in generic/ 2023-07-16 19:18:58 -07:00
John Keiser 66252e4925 Honor --output-on-failure again 2023-07-15 17:44:44 -07:00
John Keiser 944778c186 Reamalgamate 2023-07-15 17:30:42 -07:00
John Keiser 62868a2f53 Catch more headers without which it won't compile 2023-07-15 17:16:18 -07:00
John Keiser 3c446c551b Move AMALGAMATED up to include implementation.cpp 2023-07-15 17:04:14 -07:00
John Keiser efe3d4b7d7 Few more missing headers, make it even stricter 2023-07-15 16:55:27 -07:00
John Keiser 28db262b47 Make SIMDJSON_AMALGAMATED checking much stricter 2023-07-15 16:46:15 -07:00
John Keiser bf076bfb5f Begin amalgamation early in simdjson.cpp 2023-07-15 15:55:38 -07:00
John Keiser 7bf1ecff9e Mark amalgamation early in 2023-07-15 15:53:09 -07:00
John Keiser e25a40facf Check if amalgamation rules are not being followed while compiling 2023-07-15 15:47:14 -07:00
John Keiser a442842f0d Use SIMDJSON_AMALGAMATED (which works in-editor and out) instead of editor-specific tweaks 2023-07-15 14:53:02 -07:00
John Keiser 421ed4f390 Try to make output on failure actually work 2023-07-14 20:57:24 -07:00
John Keiser 7dff5fa37c Include intrin.h from jsoncharutils.h since it's needed 2023-07-14 20:53:47 -07:00
John Keiser 9a0527c380 Only make editor stuff work in editor 2023-07-14 20:05:05 -07:00
John Keiser b160cf0610 Make simdjson.cpp compile on VSCode 2023-07-08 11:53:58 -07:00
John Keiser 553ee69b7c Make implementation .h/.cpp compile 2023-07-08 11:42:57 -07:00
John Keiser bf70cd0ebf Get headers compiling in editor 2023-07-08 10:47:15 -07:00
Cuda-Chen cf0551edf5 Add pretty print for DOM
Add pretty print for DOM with documentation.
Currently, the indentation is fixed to four spaces.

Close #1329.
2023-07-08 21:09:57 +08:00
yongxiangng ddb094d550 Move should log into separate if clause 2023-07-08 13:07:25 +08:00
Yong Xiang Ng 975fdda03c Add fine grain logging 2023-07-07 12:11:27 +08:00
261 changed files with 107417 additions and 20752 deletions
+45 -1
View File
@@ -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
+1 -1
View File
@@ -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**
+1 -1
View File
@@ -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"
+1
View File
@@ -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
+2 -2
View File
@@ -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 &&
+2 -2
View File
@@ -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 &&
+2 -2
View File
@@ -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 &&
+2 -2
View File
@@ -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 &&
+15 -3
View File
@@ -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
+16 -2
View File
@@ -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 &&
+1 -3
View File
@@ -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
+1 -3
View File
@@ -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
+2 -2
View File
@@ -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 &&
+1 -1
View File
@@ -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
@@ -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
+16 -2
View File
@@ -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 &&
+3
View File
@@ -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
+8 -3
View File
@@ -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.
+1
View File
@@ -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
View File
@@ -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
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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;
+1 -1
View File
@@ -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];
} }
+28 -3
View File
@@ -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!)
+5
View File
@@ -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
View File
@@ -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
+3
View File
@@ -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
View File
@@ -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
+3 -28
View File
@@ -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
+28
View File
@@ -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
+9
View File
@@ -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
-101
View File
@@ -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
+124 -2
View File
@@ -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.
+5
View File
@@ -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
+4 -6
View File
@@ -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
*/ */
+4
View File
@@ -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>
-27
View File
@@ -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
+8
View File
@@ -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
View File
@@ -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
@@ -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
View File
@@ -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
View File
@@ -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
+37
View File
@@ -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
+38
View File
@@ -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
+36
View File
@@ -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
+66 -24
View File
@@ -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
+8
View File
@@ -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 -7
View File
@@ -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
+9 -5
View File
@@ -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 -10
View File
@@ -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.
*/ */
+54
View File
@@ -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
+7 -6
View File
@@ -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
+2 -4
View File
@@ -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.
* *
+10 -6
View File
@@ -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
+2 -3
View File
@@ -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 {
+12 -6
View File
@@ -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
+2 -12
View File
@@ -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
+5 -3
View File
@@ -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 {
+9 -6
View File
@@ -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
+2 -10
View File
@@ -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.
*/ */
+1 -1
View File
@@ -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 {
+60 -4
View File
@@ -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
+9 -50
View File
@@ -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())
;
}
+11 -7
View File
@@ -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 -29
View File
@@ -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.
* *
+131 -23
View File
@@ -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>
+126 -85
View File
@@ -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
+5 -6
View File
@@ -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
+3 -1
View File
@@ -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 {
+2 -24
View File
@@ -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
+19
View File
@@ -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
+4
View File
@@ -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
+4
View File
@@ -1 +1,5 @@
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
#include "simdjson/fallback/base.h"
#endif // SIMDJSON_CONDITIONAL_INCLUDE
#undef SIMDJSON_IMPLEMENTATION #undef SIMDJSON_IMPLEMENTATION
+4 -6
View File
@@ -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;
-36
View File
@@ -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
+8
View File
@@ -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
@@ -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
+12
View File
@@ -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"
+12
View File
@@ -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
+46
View File
@@ -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
+20
View File
@@ -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
+8 -20
View File
@@ -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
+303
View File
@@ -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
+17 -14
View File
@@ -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
-16
View File
@@ -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"
-36
View File
@@ -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
+10 -4
View File
@@ -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