mirror of
https://github.com/simdjson/simdjson
synced 2026-06-08 17:27:07 +00:00
Compare commits
115 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a49ac04046 | |||
| 49c7654a70 | |||
| 3e777c1759 | |||
| a410c723c8 | |||
| f91a1ae07e | |||
| c3954b1fb8 | |||
| ce74ece545 | |||
| dd4dce848e | |||
| e8f370b085 | |||
| 645033a8c8 | |||
| 3b5ceeb80d | |||
| 82433a67f9 | |||
| 8c1bfe782b | |||
| 730939f01c | |||
| b169dc2ea7 | |||
| 1aa1d537fe | |||
| c122462278 | |||
| b6b338bea9 | |||
| f72636b5b0 | |||
| f6a2bac11b | |||
| e4ddc5446b | |||
| e0e0aa9e7b | |||
| 9f0a2e0e86 | |||
| 203c03e90b | |||
| 6698eb96b9 | |||
| 30f7de387c | |||
| e0788507fe | |||
| e4740c87fb | |||
| 5beef701e7 | |||
| c6f9c93c33 | |||
| 3a93e45dd1 | |||
| 6db8ceb46c | |||
| 23651f0d41 | |||
| 7e1893db42 | |||
| b4b1927b0f | |||
| e275589832 | |||
| 69ee84973a | |||
| 76bed68ec3 | |||
| 003d970cd2 | |||
| 4aaf3f030c | |||
| 2763f7e719 | |||
| 39035c39be | |||
| ac179ff40f | |||
| b41bece32c | |||
| 9cb0c5f92d | |||
| 1dec7b04fe | |||
| c6eb6f98b8 | |||
| 1b01969bda | |||
| 17f3148ac7 | |||
| 35b4a48e99 | |||
| c0d18452fc | |||
| e5c9a310cf | |||
| 6d308a08c5 | |||
| 9e477ddb00 | |||
| b7c4d1eeef | |||
| 4a2f10ebcf | |||
| 41cb909604 | |||
| 91908ade4d | |||
| 9a32c48098 | |||
| d996ffc494 | |||
| d56fdc3d04 | |||
| 1dce4fed6e | |||
| cae5e5342f | |||
| 4e609aa955 | |||
| d28e5534d9 | |||
| 3bd8b0b575 | |||
| af4ff7cc33 | |||
| c9179ad81d | |||
| d6b5124c88 | |||
| 64b62fd3b3 | |||
| cebe3fb299 | |||
| ed7343f7f2 | |||
| 35158257c6 | |||
| b935ce2e06 | |||
| 4afe7565b4 | |||
| 6bed34ad61 | |||
| 0ad52a7e22 | |||
| aa52cf6868 | |||
| cd11838e5f | |||
| c31157bafe | |||
| 419b7b2ce8 | |||
| ca3f3cc49d | |||
| d3f0e2afb3 | |||
| eac3832ec0 | |||
| db19c7675f | |||
| d036fdf919 | |||
| fc0934755a | |||
| de4deb8c4e | |||
| ba46616cbc | |||
| a552638373 | |||
| e30123d58f | |||
| b7dee3e9c8 | |||
| 717d0c24a6 | |||
| 40813752f4 | |||
| 19902abaf8 | |||
| 06643fc9f5 | |||
| 0fa68d8930 | |||
| cc98358453 | |||
| 5f0b35b2c5 | |||
| bd0f5e9322 | |||
| cb0e4b23c7 | |||
| d83e69d977 | |||
| f657516a7e | |||
| 8d29c5f931 | |||
| eeac91579c | |||
| e5a4b8b81b | |||
| 7b8f775893 | |||
| c6ef2105ab | |||
| e681234e45 | |||
| eb93b98d6a | |||
| 7d887fdc1e | |||
| 9d405a5df4 | |||
| 18c003e8bf | |||
| ec4316aa84 | |||
| b79261eebc |
+5
-5
@@ -15,22 +15,22 @@ environment:
|
|||||||
- job_name: VS2019
|
- job_name: VS2019
|
||||||
CMAKE_ARGS: -A %Platform%
|
CMAKE_ARGS: -A %Platform%
|
||||||
- job_name: VS2019ARM
|
- job_name: VS2019ARM
|
||||||
CMAKE_ARGS: -A ARM64 -DCMAKE_CROSSCOMPILING=1 -D SIMDJSON_GOOGLE_BENCHMARKS=OFF # Does Google Benchmark builds under VS ARM?
|
CMAKE_ARGS: -A ARM64 -DSIMDJSON_DEVELOPER_MODE=ON -DCMAKE_CROSSCOMPILING=1 -D SIMDJSON_GOOGLE_BENCHMARKS=OFF # Does Google Benchmark builds under VS ARM?
|
||||||
- job_name: VS2017 (Static, No Threads)
|
- job_name: VS2017 (Static, No Threads)
|
||||||
image: Visual Studio 2017
|
image: Visual Studio 2017
|
||||||
CMAKE_ARGS: -A %Platform% -DBUILD_SHARED_LIBS=OFF -DSIMDJSON_ENABLE_THREADS=OFF
|
CMAKE_ARGS: -A %Platform% -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=OFF -DSIMDJSON_ENABLE_THREADS=OFF
|
||||||
CTEST_ARGS: -LE explicitonly
|
CTEST_ARGS: -LE explicitonly
|
||||||
- job_name: VS2019 (Win32)
|
- job_name: VS2019 (Win32)
|
||||||
platform: Win32
|
platform: Win32
|
||||||
CMAKE_ARGS: -A %Platform% -DBUILD_SHARED_LIBS=ON -DSIMDJSON_ENABLE_THREADS=ON # This should be the default. Testing anyway.
|
CMAKE_ARGS: -A %Platform% -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=ON -DSIMDJSON_ENABLE_THREADS=ON # This should be the default. Testing anyway.
|
||||||
CTEST_ARGS: -LE explicitonly
|
CTEST_ARGS: -LE explicitonly
|
||||||
- job_name: VS2019 (Win32, No Exceptions)
|
- job_name: VS2019 (Win32, No Exceptions)
|
||||||
platform: Win32
|
platform: Win32
|
||||||
CMAKE_ARGS: -A %Platform% -DBUILD_SHARED_LIBS=ON -DSIMDJSON_ENABLE_THREADS=ON -DSIMDJSON_EXCEPTIONS=OFF
|
CMAKE_ARGS: -A %Platform% -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=ON -DSIMDJSON_ENABLE_THREADS=ON -DSIMDJSON_EXCEPTIONS=OFF
|
||||||
CTEST_ARGS: -LE explicitonly
|
CTEST_ARGS: -LE explicitonly
|
||||||
- job_name: VS2015
|
- job_name: VS2015
|
||||||
image: Visual Studio 2015
|
image: Visual Studio 2015
|
||||||
CMAKE_ARGS: -A %Platform% -DBUILD_SHARED_LIBS=OFF -DSIMDJSON_ENABLE_THREADS=OFF
|
CMAKE_ARGS: -A %Platform% -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=OFF -DSIMDJSON_ENABLE_THREADS=OFF
|
||||||
CTEST_ARGS: -LE explicitonly
|
CTEST_ARGS: -LE explicitonly
|
||||||
|
|
||||||
build_script:
|
build_script:
|
||||||
|
|||||||
+7
-15
@@ -88,13 +88,13 @@ commands:
|
|||||||
steps:
|
steps:
|
||||||
- cmake_prep
|
- cmake_prep
|
||||||
- dependency_restore
|
- dependency_restore
|
||||||
- run: cmake $CMAKE_FLAGS -DCMAKE_INSTALL_PREFIX:PATH=destination -B build .
|
- run: cmake -DSIMDJSON_DEVELOPER_MODE=ON $CMAKE_FLAGS -DCMAKE_INSTALL_PREFIX:PATH=destination -B build .
|
||||||
- dependency_cache # dependencies are produced in the configure step
|
- dependency_cache # dependencies are produced in the configure step
|
||||||
|
|
||||||
cmake_build:
|
cmake_build:
|
||||||
steps:
|
steps:
|
||||||
- cmake_build_cache
|
- cmake_build_cache
|
||||||
- run: cmake --build build
|
- run: cmake --build build
|
||||||
|
|
||||||
cmake_test:
|
cmake_test:
|
||||||
steps:
|
steps:
|
||||||
@@ -191,12 +191,12 @@ jobs:
|
|||||||
sanitize-gcc10:
|
sanitize-gcc10:
|
||||||
description: Build and run tests on GCC 10 and AVX 2 with a cmake sanitize build
|
description: Build and run tests on GCC 10 and AVX 2 with a cmake sanitize build
|
||||||
executor: gcc10
|
executor: gcc10
|
||||||
environment: { CMAKE_FLAGS: -DBUILD_SHARED_LIBS=ON -DSIMDJSON_SANITIZE=ON, CTEST_FLAGS: --output-on-failure -LE explicitonly }
|
environment: { CMAKE_FLAGS: -DCMAKE_BUILD_TYPE=Debug -DBUILD_SHARED_LIBS=ON -DSIMDJSON_SANITIZE=ON, CTEST_FLAGS: --output-on-failure -LE explicitonly }
|
||||||
steps: [ cmake_test ]
|
steps: [ cmake_test ]
|
||||||
sanitize-clang10:
|
sanitize-clang10:
|
||||||
description: Build and run tests on clang 10 and AVX 2 with a cmake sanitize build
|
description: Build and run tests on clang 10 and AVX 2 with a cmake sanitize build
|
||||||
executor: clang10
|
executor: clang10
|
||||||
environment: { CMAKE_FLAGS: -DBUILD_SHARED_LIBS=ON -DSIMDJSON_SANITIZE=ON, CTEST_FLAGS: --output-on-failure -LE explicitonly }
|
environment: { CMAKE_FLAGS: -DBUILD_SHARED_LIBS=ON -DSIMDJSON_NO_FORCE_INLINING=ON -DSIMDJSON_SANITIZE=ON, CTEST_FLAGS: --output-on-failure -LE explicitonly }
|
||||||
steps: [ cmake_test ]
|
steps: [ cmake_test ]
|
||||||
threadsanitize-gcc10:
|
threadsanitize-gcc10:
|
||||||
description: Build and run tests on GCC 10 and AVX 2 with a cmake sanitize build
|
description: Build and run tests on GCC 10 and AVX 2 with a cmake sanitize build
|
||||||
@@ -206,15 +206,7 @@ jobs:
|
|||||||
threadsanitize-clang10:
|
threadsanitize-clang10:
|
||||||
description: Build and run tests on clang 10 and AVX 2 with a cmake sanitize build
|
description: Build and run tests on clang 10 and AVX 2 with a cmake sanitize build
|
||||||
executor: clang10
|
executor: clang10
|
||||||
environment: { CMAKE_FLAGS: -DBUILD_SHARED_LIBS=ON -DSIMDJSON_SANITIZE_THREADS=ON, CTEST_FLAGS: --output-on-failure -LE explicitonly }
|
environment: { CMAKE_FLAGS: -DBUILD_SHARED_LIBS=ON -DSIMDJSON_NO_FORCE_INLINING=ON -DSIMDJSON_SANITIZE_THREADS=ON, CTEST_FLAGS: --output-on-failure -LE explicitonly }
|
||||||
steps: [ cmake_test ]
|
|
||||||
nocheckeof-clang10:
|
|
||||||
description: Validate that when __SIMDJSON_CHECK_EOF=0, everything still succeeds
|
|
||||||
environment:
|
|
||||||
CXXFLAGS: -D__SIMDJSON_CHECK_EOF=0
|
|
||||||
CMAKE_BUILD_FLAGS: --target ondemand_tests
|
|
||||||
CTEST_FLAGS: --output-on-failure -R ondemand_
|
|
||||||
executor: clang10
|
|
||||||
steps: [ cmake_test ]
|
steps: [ cmake_test ]
|
||||||
# dynamic
|
# dynamic
|
||||||
dynamic-gcc10:
|
dynamic-gcc10:
|
||||||
@@ -270,12 +262,12 @@ jobs:
|
|||||||
sanitize-haswell-gcc10:
|
sanitize-haswell-gcc10:
|
||||||
description: Build and run tests on GCC 10 and AVX 2 with a cmake sanitize build
|
description: Build and run tests on GCC 10 and AVX 2 with a cmake sanitize build
|
||||||
executor: gcc10
|
executor: gcc10
|
||||||
environment: { CXXFLAGS: -march=haswell, CMAKE_FLAGS: -DBUILD_SHARED_LIBS=ON -DSIMDJSON_SANITIZE=ON, CTEST_FLAGS: --output-on-failure -LE explicitonly }
|
environment: { CXXFLAGS: -march=haswell, CMAKE_FLAGS: -DCMAKE_BUILD_TYPE=Debug -DBUILD_SHARED_LIBS=ON -DSIMDJSON_SANITIZE=ON, CTEST_FLAGS: --output-on-failure -LE explicitonly }
|
||||||
steps: [ cmake_test ]
|
steps: [ cmake_test ]
|
||||||
sanitize-haswell-clang10:
|
sanitize-haswell-clang10:
|
||||||
description: Build and run tests on clang 10 and AVX 2 with a cmake sanitize build
|
description: Build and run tests on clang 10 and AVX 2 with a cmake sanitize build
|
||||||
executor: clang10
|
executor: clang10
|
||||||
environment: { CXXFLAGS: -march=haswell, CMAKE_FLAGS: -DBUILD_SHARED_LIBS=ON -DSIMDJSON_SANITIZE=ON, CTEST_FLAGS: --output-on-failure -LE explicitonly }
|
environment: { CXXFLAGS: -march=haswell, CMAKE_FLAGS: -DBUILD_SHARED_LIBS=ON -DSIMDJSON_NO_FORCE_INLINING=ON -DSIMDJSON_SANITIZE=ON, CTEST_FLAGS: --output-on-failure -LE explicitonly }
|
||||||
steps: [ cmake_test ]
|
steps: [ cmake_test ]
|
||||||
|
|
||||||
workflows:
|
workflows:
|
||||||
|
|||||||
+8
-46
@@ -1,46 +1,4 @@
|
|||||||
kind: pipeline
|
kind: pipeline
|
||||||
name: i386-gcc # we do not support 32-bit systems, but we run tests
|
|
||||||
platform: { os: linux, arch: amd64 }
|
|
||||||
steps:
|
|
||||||
- name: Build and Test
|
|
||||||
image: i386/ubuntu
|
|
||||||
environment:
|
|
||||||
CC: gcc
|
|
||||||
CXX: g++
|
|
||||||
BUILD_FLAGS: -- -j
|
|
||||||
CMAKE_FLAGS: -DBUILD_SHARED_LIBS=OFF
|
|
||||||
CTEST_FLAGS: -j4 --output-on-failure -LE explicitonly
|
|
||||||
commands:
|
|
||||||
- scripts/addcmakeppa.sh "$(env -i sh -c '. /etc/os-release; echo $VERSION_CODENAME')"
|
|
||||||
- apt-get install -y g++ cmake gcc git
|
|
||||||
- mkdir build
|
|
||||||
- cd build
|
|
||||||
- cmake $CMAKE_FLAGS ..
|
|
||||||
- cmake --build . $BUILD_FLAGS
|
|
||||||
- ctest $CTEST_FLAGS
|
|
||||||
---
|
|
||||||
kind: pipeline
|
|
||||||
name: i386-clang # we do not support 32-bit systems, but we run tests
|
|
||||||
platform: { os: linux, arch: amd64 }
|
|
||||||
steps:
|
|
||||||
- name: Build and Test
|
|
||||||
image: i386/ubuntu
|
|
||||||
environment:
|
|
||||||
CC: clang-6.0
|
|
||||||
CXX: clang++-6.0
|
|
||||||
BUILD_FLAGS: -- -j
|
|
||||||
CMAKE_FLAGS: -DBUILD_SHARED_LIBS=OFF
|
|
||||||
CTEST_FLAGS: -j4 --output-on-failure -LE explicitonly
|
|
||||||
commands:
|
|
||||||
- scripts/addcmakeppa.sh "$(env -i sh -c '. /etc/os-release; echo $VERSION_CODENAME')"
|
|
||||||
- apt-get install -y clang++-6.0 cmake git
|
|
||||||
- mkdir build
|
|
||||||
- cd build
|
|
||||||
- cmake $CMAKE_FLAGS ..
|
|
||||||
- cmake --build . $BUILD_FLAGS
|
|
||||||
- ctest $CTEST_FLAGS
|
|
||||||
---
|
|
||||||
kind: pipeline
|
|
||||||
name: gcc9
|
name: gcc9
|
||||||
platform: { os: linux, arch: amd64 }
|
platform: { os: linux, arch: amd64 }
|
||||||
steps:
|
steps:
|
||||||
@@ -50,7 +8,7 @@ steps:
|
|||||||
CC: gcc
|
CC: gcc
|
||||||
CXX: g++
|
CXX: g++
|
||||||
BUILD_FLAGS: -- -j
|
BUILD_FLAGS: -- -j
|
||||||
CMAKE_FLAGS: -DBUILD_SHARED_LIBS=OFF -DSIMDJSON_IMPLEMENTATION=haswell;westmere;fallback
|
CMAKE_FLAGS: -DBUILD_SHARED_LIBS=OFF -DSIMDJSON_IMPLEMENTATION=icelake;haswell;westmere;fallback
|
||||||
CTEST_FLAGS: -j4 --output-on-failure -LE explicitonly
|
CTEST_FLAGS: -j4 --output-on-failure -LE explicitonly
|
||||||
commands:
|
commands:
|
||||||
- echo "deb http://deb.debian.org/debian buster-backports main" >> /etc/apt/sources.list
|
- echo "deb http://deb.debian.org/debian buster-backports main" >> /etc/apt/sources.list
|
||||||
@@ -61,6 +19,7 @@ steps:
|
|||||||
- cmake $CMAKE_FLAGS ..
|
- cmake $CMAKE_FLAGS ..
|
||||||
- cmake --build . $BUILD_FLAGS
|
- cmake --build . $BUILD_FLAGS
|
||||||
- ctest $CTEST_FLAGS -L acceptance -LE per_implementation
|
- ctest $CTEST_FLAGS -L acceptance -LE per_implementation
|
||||||
|
- SIMDJSON_FORCE_IMPLEMENTATION=icelake ctest $CTEST_FLAGS -L per_implementation
|
||||||
- SIMDJSON_FORCE_IMPLEMENTATION=haswell ctest $CTEST_FLAGS -L per_implementation
|
- SIMDJSON_FORCE_IMPLEMENTATION=haswell ctest $CTEST_FLAGS -L per_implementation
|
||||||
- SIMDJSON_FORCE_IMPLEMENTATION=westmere ctest $CTEST_FLAGS -L per_implementation
|
- SIMDJSON_FORCE_IMPLEMENTATION=westmere ctest $CTEST_FLAGS -L per_implementation
|
||||||
- SIMDJSON_FORCE_IMPLEMENTATION=fallback ctest $CTEST_FLAGS -L per_implementation
|
- SIMDJSON_FORCE_IMPLEMENTATION=fallback ctest $CTEST_FLAGS -L per_implementation
|
||||||
@@ -77,7 +36,7 @@ steps:
|
|||||||
CC: clang-6.0
|
CC: clang-6.0
|
||||||
CXX: clang++-6.0
|
CXX: clang++-6.0
|
||||||
BUILD_FLAGS: -- -j
|
BUILD_FLAGS: -- -j
|
||||||
CMAKE_FLAGS: -DBUILD_SHARED_LIBS=OFF -DSIMDJSON_IMPLEMENTATION=haswell;westmere;fallback
|
CMAKE_FLAGS: -DBUILD_SHARED_LIBS=OFF -DSIMDJSON_IMPLEMENTATION=icelake;haswell;westmere;fallback
|
||||||
CTEST_FLAGS: -j4 --output-on-failure -LE explicitonly
|
CTEST_FLAGS: -j4 --output-on-failure -LE explicitonly
|
||||||
commands:
|
commands:
|
||||||
- mkdir build
|
- mkdir build
|
||||||
@@ -85,6 +44,7 @@ steps:
|
|||||||
- cmake $CMAKE_FLAGS ..
|
- cmake $CMAKE_FLAGS ..
|
||||||
- cmake --build . $BUILD_FLAGS
|
- cmake --build . $BUILD_FLAGS
|
||||||
- ctest $CTEST_FLAGS -L acceptance -LE per_implementation
|
- ctest $CTEST_FLAGS -L acceptance -LE per_implementation
|
||||||
|
- SIMDJSON_FORCE_IMPLEMENTATION=icelake ctest $CTEST_FLAGS -L per_implementation
|
||||||
- SIMDJSON_FORCE_IMPLEMENTATION=haswell ctest $CTEST_FLAGS -L per_implementation
|
- SIMDJSON_FORCE_IMPLEMENTATION=haswell ctest $CTEST_FLAGS -L per_implementation
|
||||||
- SIMDJSON_FORCE_IMPLEMENTATION=westmere ctest $CTEST_FLAGS -L per_implementation
|
- SIMDJSON_FORCE_IMPLEMENTATION=westmere ctest $CTEST_FLAGS -L per_implementation
|
||||||
- SIMDJSON_FORCE_IMPLEMENTATION=fallback ctest $CTEST_FLAGS -L per_implementation
|
- SIMDJSON_FORCE_IMPLEMENTATION=fallback ctest $CTEST_FLAGS -L per_implementation
|
||||||
@@ -142,7 +102,7 @@ steps:
|
|||||||
CC: gcc
|
CC: gcc
|
||||||
CXX: g++
|
CXX: g++
|
||||||
BUILD_FLAGS: -- -j
|
BUILD_FLAGS: -- -j
|
||||||
CMAKE_FLAGS: -DBUILD_SHARED_LIBS=OFF -DSIMDJSON_IMPLEMENTATION=haswell;westmere;fallback
|
CMAKE_FLAGS: -DBUILD_SHARED_LIBS=OFF -DSIMDJSON_IMPLEMENTATION=icelake;haswell;westmere;fallback
|
||||||
CTEST_FLAGS: -j4 --output-on-failure -LE explicitonly
|
CTEST_FLAGS: -j4 --output-on-failure -LE explicitonly
|
||||||
commands:
|
commands:
|
||||||
- echo "deb http://deb.debian.org/debian buster-backports main" >> /etc/apt/sources.list
|
- echo "deb http://deb.debian.org/debian buster-backports main" >> /etc/apt/sources.list
|
||||||
@@ -153,6 +113,7 @@ steps:
|
|||||||
- cmake $CMAKE_FLAGS ..
|
- cmake $CMAKE_FLAGS ..
|
||||||
- cmake --build . $BUILD_FLAGS
|
- cmake --build . $BUILD_FLAGS
|
||||||
- ASAN_OPTIONS="detect_leaks=0" ctest $CTEST_FLAGS -L acceptance -LE per_implementation
|
- ASAN_OPTIONS="detect_leaks=0" ctest $CTEST_FLAGS -L acceptance -LE per_implementation
|
||||||
|
- SIMDJSON_FORCE_IMPLEMENTATION=icelake ASAN_OPTIONS="detect_leaks=0" ctest $CTEST_FLAGS -L per_implementation
|
||||||
- SIMDJSON_FORCE_IMPLEMENTATION=haswell ASAN_OPTIONS="detect_leaks=0" ctest $CTEST_FLAGS -L per_implementation
|
- SIMDJSON_FORCE_IMPLEMENTATION=haswell ASAN_OPTIONS="detect_leaks=0" ctest $CTEST_FLAGS -L per_implementation
|
||||||
- SIMDJSON_FORCE_IMPLEMENTATION=westmere ASAN_OPTIONS="detect_leaks=0" ctest $CTEST_FLAGS -L per_implementation
|
- SIMDJSON_FORCE_IMPLEMENTATION=westmere ASAN_OPTIONS="detect_leaks=0" ctest $CTEST_FLAGS -L per_implementation
|
||||||
- SIMDJSON_FORCE_IMPLEMENTATION=fallback ASAN_OPTIONS="detect_leaks=0" ctest $CTEST_FLAGS -L per_implementation
|
- SIMDJSON_FORCE_IMPLEMENTATION=fallback ASAN_OPTIONS="detect_leaks=0" ctest $CTEST_FLAGS -L per_implementation
|
||||||
@@ -168,7 +129,7 @@ steps:
|
|||||||
environment:
|
environment:
|
||||||
CC: clang-9
|
CC: clang-9
|
||||||
CXX: clang++-9
|
CXX: clang++-9
|
||||||
CMAKE_FLAGS: -DSIMDJSON_SANITIZE=ON -DSIMDJSON_IMPLEMENTATION=haswell;westmere;fallback
|
CMAKE_FLAGS: -DSIMDJSON_SANITIZE=ON -DSIMDJSON_IMPLEMENTATION=icelake;haswell;westmere;fallback
|
||||||
BUILD_FLAGS: -- -j
|
BUILD_FLAGS: -- -j
|
||||||
CTEST_FLAGS: -j4 --output-on-failure -LE explicitonly
|
CTEST_FLAGS: -j4 --output-on-failure -LE explicitonly
|
||||||
commands:
|
commands:
|
||||||
@@ -177,6 +138,7 @@ steps:
|
|||||||
- cmake $CMAKE_FLAGS ..
|
- cmake $CMAKE_FLAGS ..
|
||||||
- cmake --build . $BUILD_FLAGS
|
- cmake --build . $BUILD_FLAGS
|
||||||
- ASAN_OPTIONS="detect_leaks=0" ctest $CTEST_FLAGS -L acceptance -LE per_implementation
|
- ASAN_OPTIONS="detect_leaks=0" ctest $CTEST_FLAGS -L acceptance -LE per_implementation
|
||||||
|
- SIMDJSON_FORCE_IMPLEMENTATION=icelake ASAN_OPTIONS="detect_leaks=0" ctest $CTEST_FLAGS -L per_implementation
|
||||||
- SIMDJSON_FORCE_IMPLEMENTATION=haswell ASAN_OPTIONS="detect_leaks=0" ctest $CTEST_FLAGS -L per_implementation
|
- SIMDJSON_FORCE_IMPLEMENTATION=haswell ASAN_OPTIONS="detect_leaks=0" ctest $CTEST_FLAGS -L per_implementation
|
||||||
- SIMDJSON_FORCE_IMPLEMENTATION=westmere ASAN_OPTIONS="detect_leaks=0" ctest $CTEST_FLAGS -L per_implementation
|
- SIMDJSON_FORCE_IMPLEMENTATION=westmere ASAN_OPTIONS="detect_leaks=0" ctest $CTEST_FLAGS -L per_implementation
|
||||||
- SIMDJSON_FORCE_IMPLEMENTATION=fallback ASAN_OPTIONS="detect_leaks=0" ctest $CTEST_FLAGS -L per_implementation
|
- SIMDJSON_FORCE_IMPLEMENTATION=fallback ASAN_OPTIONS="detect_leaks=0" ctest $CTEST_FLAGS -L per_implementation
|
||||||
|
|||||||
@@ -1,12 +1,6 @@
|
|||||||
name: Alpine Linux
|
name: Alpine Linux
|
||||||
|
|
||||||
on:
|
on: [push, pull_request]
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
ubuntu-build:
|
ubuntu-build:
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
name: CIFuzz
|
||||||
|
on: [pull_request]
|
||||||
|
jobs:
|
||||||
|
Fuzzing:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Build Fuzzers
|
||||||
|
id: build
|
||||||
|
uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master
|
||||||
|
with:
|
||||||
|
oss-fuzz-project-name: 'simdjson'
|
||||||
|
dry-run: false
|
||||||
|
- name: Run Fuzzers
|
||||||
|
uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master
|
||||||
|
with:
|
||||||
|
oss-fuzz-project-name: 'simdjson'
|
||||||
|
fuzz-seconds: 600
|
||||||
|
dry-run: false
|
||||||
|
- name: Upload Crash
|
||||||
|
uses: actions/upload-artifact@v1
|
||||||
|
if: failure() && steps.build.outcome == 'success'
|
||||||
|
with:
|
||||||
|
name: artifacts
|
||||||
|
path: ./out/artifacts
|
||||||
@@ -1,9 +1,6 @@
|
|||||||
name: Detect trailing whitespace
|
name: Detect trailing whitespace
|
||||||
|
|
||||||
on:
|
on: [push, pull_request]
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
whitespace:
|
whitespace:
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
name: Macos (Xcode 11)
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
macos-build:
|
||||||
|
if: >-
|
||||||
|
! contains(toJSON(github.event.commits.*.message), '[skip ci]') &&
|
||||||
|
! contains(toJSON(github.event.commits.*.message), '[skip github]')
|
||||||
|
runs-on: macos-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
path: dependencies/.cache
|
||||||
|
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
|
||||||
|
- name: Use cmake
|
||||||
|
run: |
|
||||||
|
xcversion select 11.7
|
||||||
|
mkdir builddebug &&
|
||||||
|
cd builddebug &&
|
||||||
|
cmake -DCMAKE_BUILD_TYPE=Debug -DSIMDJSON_GOOGLE_BENCHMARKS=OFF -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=OFF .. &&
|
||||||
|
cmake --build . &&
|
||||||
|
ctest -j --output-on-failure -LE explicitonly &&
|
||||||
|
cd .. &&
|
||||||
|
mkdir build &&
|
||||||
|
cd build &&
|
||||||
|
cmake -DSIMDJSON_GOOGLE_BENCHMARKS=ON -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=OFF -DCMAKE_INSTALL_PREFIX:PATH=destination .. &&
|
||||||
|
cmake --build . &&
|
||||||
|
ctest -j --output-on-failure -LE explicitonly &&
|
||||||
|
cmake --install . &&
|
||||||
|
echo -e '#include <simdjson.h>\nint main(int argc,char**argv) {simdjson::dom::parser parser;simdjson::dom::element tweets = parser.load(argv[1]); }' > tmp.cpp && c++ -Idestination/include -Ldestination/lib -std=c++17 -Wl,-rpath,destination/lib -o linkandrun tmp.cpp -lsimdjson && ./linkandrun jsonexamples/twitter.json &&
|
||||||
|
cd ../tests/installation_tests/find &&
|
||||||
|
mkdir build && cd build && cmake -DCMAKE_INSTALL_PREFIX:PATH=../../../build/destination .. && cmake --build .
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
name: Macos
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
macos-build:
|
||||||
|
if: >-
|
||||||
|
! contains(toJSON(github.event.commits.*.message), '[skip ci]') &&
|
||||||
|
! contains(toJSON(github.event.commits.*.message), '[skip github]')
|
||||||
|
runs-on: macos-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
path: dependencies/.cache
|
||||||
|
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
|
||||||
|
- name: Use cmake
|
||||||
|
run: |
|
||||||
|
mkdir builddebug &&
|
||||||
|
cd builddebug &&
|
||||||
|
cmake -DCMAKE_BUILD_TYPE=Debug -DSIMDJSON_GOOGLE_BENCHMARKS=OFF -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=OFF .. &&
|
||||||
|
cmake --build . &&
|
||||||
|
ctest -j --output-on-failure -LE explicitonly &&
|
||||||
|
cd .. &&
|
||||||
|
mkdir build &&
|
||||||
|
cd build &&
|
||||||
|
cmake -DSIMDJSON_GOOGLE_BENCHMARKS=ON -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=OFF -DCMAKE_INSTALL_PREFIX:PATH=destination .. &&
|
||||||
|
cmake --build . &&
|
||||||
|
ctest -j --output-on-failure -LE explicitonly &&
|
||||||
|
cmake --install . &&
|
||||||
|
echo -e '#include <simdjson.h>\nint main(int argc,char**argv) {simdjson::dom::parser parser;simdjson::dom::element tweets = parser.load(argv[1]); }' > tmp.cpp && c++ -Idestination/include -Ldestination/lib -std=c++17 -Wl,-rpath,destination/lib -o linkandrun tmp.cpp -lsimdjson && ./linkandrun jsonexamples/twitter.json &&
|
||||||
|
cd ../tests/installation_tests/find &&
|
||||||
|
mkdir build && cd build && cmake -DCMAKE_INSTALL_PREFIX:PATH=../../../build/destination .. && cmake --build .
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
name: MinGW32-CI
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
|
|
||||||
# Important: scoop will either install 32-bit GCC or 64-bit GCC, not both.
|
|
||||||
|
|
||||||
# It is important to build static libraries because cmake is not smart enough under Windows/mingw to take care of the path. So
|
|
||||||
# with a dynamic library, you could get failures due to the fact that the EXE can't find its DLL.
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
ci:
|
|
||||||
if: >-
|
|
||||||
! contains(toJSON(github.event.commits.*.message), '[skip ci]') &&
|
|
||||||
! contains(toJSON(github.event.commits.*.message), '[skip github]')
|
|
||||||
name: windows-gcc
|
|
||||||
runs-on: windows-2016
|
|
||||||
|
|
||||||
env:
|
|
||||||
CMAKE_GENERATOR: Ninja # This is critical, try ' cmake -GNinja-DBUILD_SHARED_LIBS=OFF .. ' if using the command line
|
|
||||||
CC: gcc
|
|
||||||
CXX: g++
|
|
||||||
|
|
||||||
steps: # To reproduce what is below, start a powershell with administrative rights, using scoop *is* a good idea
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
|
|
||||||
- uses: actions/cache@v2 # we cache the scoop setup with 32-bit GCC
|
|
||||||
id: cache
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
C:\ProgramData\scoop
|
|
||||||
key: scoop32 # static key: should be good forever
|
|
||||||
|
|
||||||
- uses: actions/cache@v2
|
|
||||||
with:
|
|
||||||
path: dependencies/.cache
|
|
||||||
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
|
|
||||||
|
|
||||||
- name: Setup Windows # This should almost never run if the cache works.
|
|
||||||
if: steps.cache.outputs.cache-hit != 'true'
|
|
||||||
shell: powershell
|
|
||||||
run: |
|
|
||||||
Invoke-Expression (New-Object System.Net.WebClient).DownloadString('https://get.scoop.sh')
|
|
||||||
scoop install sudo --global
|
|
||||||
sudo scoop install git --global
|
|
||||||
sudo scoop install ninja --global
|
|
||||||
sudo scoop install cmake --global
|
|
||||||
sudo scoop install gcc --arch 32bit --global
|
|
||||||
$env:path
|
|
||||||
Write-Host 'Everything has been installed, you are good!'
|
|
||||||
- name: Build and Test 32-bit x86
|
|
||||||
shell: powershell
|
|
||||||
run: |
|
|
||||||
$ENV:PATH="C:\ProgramData\scoop\shims;C:\ProgramData\scoop\apps\gcc\current\bin;C:\ProgramData\scoop\apps\ninja\current;$ENV:PATH"
|
|
||||||
g++ --version
|
|
||||||
cmake --version
|
|
||||||
ninja --version
|
|
||||||
git --version
|
|
||||||
mkdir build32
|
|
||||||
cd build32
|
|
||||||
cmake -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=OFF -DSIMDJSON_COMPETITION=OFF -DSIMDJSON_GOOGLE_BENCHMARKS=OFF -DSIMDJSON_ENABLE_THREADS=OFF ..
|
|
||||||
cmake --build . --target acceptance_tests --verbose
|
|
||||||
ctest -L acceptance --output-on-failure
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
name: MinGW64-CI
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
|
|
||||||
# Important: scoop will either install 32-bit GCC or 64-bit GCC, not both.
|
|
||||||
|
|
||||||
# It is important to build static libraries because cmake is not smart enough under Windows/mingw to take care of the path. So
|
|
||||||
# with a dynamic library, you could get failures due to the fact that the EXE can't find its DLL.
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
ci:
|
|
||||||
if: >-
|
|
||||||
! contains(toJSON(github.event.commits.*.message), '[skip ci]') &&
|
|
||||||
! contains(toJSON(github.event.commits.*.message), '[skip github]')
|
|
||||||
name: windows-gcc
|
|
||||||
runs-on: windows-2016
|
|
||||||
|
|
||||||
env:
|
|
||||||
CMAKE_GENERATOR: Ninja # This is critical, try ' cmake -GNinja-DBUILD_SHARED_LIBS=OFF .. ' if using the command line
|
|
||||||
CC: gcc
|
|
||||||
CXX: g++
|
|
||||||
|
|
||||||
steps: # To reproduce what is below, start a powershell with administrative rights, using scoop *is* a good idea
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
|
|
||||||
- uses: actions/cache@v2 # we cache the scoop setup with 64-bit GCC
|
|
||||||
id: cache
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
C:\ProgramData\scoop
|
|
||||||
key: scoop64 # static key: should be good forever
|
|
||||||
|
|
||||||
- uses: actions/cache@v2
|
|
||||||
with:
|
|
||||||
path: dependencies/.cache
|
|
||||||
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
|
|
||||||
|
|
||||||
- name: Setup Windows # This should almost never run if the cache works.
|
|
||||||
if: steps.cache.outputs.cache-hit != 'true'
|
|
||||||
shell: powershell
|
|
||||||
run: |
|
|
||||||
Invoke-Expression (New-Object System.Net.WebClient).DownloadString('https://get.scoop.sh')
|
|
||||||
scoop install sudo --global
|
|
||||||
sudo scoop install git --global
|
|
||||||
sudo scoop install ninja --global
|
|
||||||
sudo scoop install cmake --global
|
|
||||||
sudo scoop install gcc --arch 64bit --global
|
|
||||||
$env:path
|
|
||||||
Write-Host 'Everything has been installed, you are good!'
|
|
||||||
- name: Build and Test 64-bit x64
|
|
||||||
shell: powershell
|
|
||||||
run: |
|
|
||||||
$ENV:PATH="C:\ProgramData\scoop\shims;C:\ProgramData\scoop\apps\gcc\current\bin;C:\ProgramData\scoop\apps\ninja\current;$ENV:PATH"
|
|
||||||
g++ --version
|
|
||||||
cmake --version
|
|
||||||
ninja --version
|
|
||||||
git --version
|
|
||||||
mkdir build64
|
|
||||||
cd build64
|
|
||||||
cmake -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=OFF -DSIMDJSON_COMPETITION=OFF -DSIMDJSON_GOOGLE_BENCHMARKS=OFF -DSIMDJSON_ENABLE_THREADS=OFF ..
|
|
||||||
cmake --build . --target acceptance_tests --verbose
|
|
||||||
ctest -L acceptance --output-on-failure
|
|
||||||
cd ..
|
|
||||||
mkdir build64debug
|
|
||||||
cd build64debug
|
|
||||||
cmake -DSIMDJSON_DEVELOPER_MODE=ON -DCMAKE_BUILD_TYPE=Debug -DBUILD_SHARED_LIBS=OFF -DSIMDJSON_COMPETITION=OFF -DSIMDJSON_GOOGLE_BENCHMARKS=OFF -DSIMDJSON_ENABLE_THREADS=OFF ..
|
|
||||||
cmake --build . --target acceptance_tests --verbose
|
|
||||||
ctest -L acceptance --output-on-failure
|
|
||||||
@@ -1,12 +1,7 @@
|
|||||||
name: MSYS2-CLANG-CI
|
name: MSYS2-CLANG-CI
|
||||||
|
|
||||||
on:
|
on: [push, pull_request]
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
windows-mingw:
|
windows-mingw:
|
||||||
@@ -22,15 +17,9 @@ jobs:
|
|||||||
- msystem: "MINGW64"
|
- msystem: "MINGW64"
|
||||||
install: mingw-w64-x86_64-libxml2 mingw-w64-x86_64-cmake mingw-w64-x86_64-ninja mingw-w64-x86_64-clang
|
install: mingw-w64-x86_64-libxml2 mingw-w64-x86_64-cmake mingw-w64-x86_64-ninja mingw-w64-x86_64-clang
|
||||||
type: Release
|
type: Release
|
||||||
- msystem: "MINGW32"
|
|
||||||
install: mingw-w64-i686-libxml2 mingw-w64-i686-cmake mingw-w64-i686-ninja mingw-w64-i686-clang
|
|
||||||
type: Release
|
|
||||||
- msystem: "MINGW64"
|
- msystem: "MINGW64"
|
||||||
install: mingw-w64-x86_64-libxml2 mingw-w64-x86_64-cmake mingw-w64-x86_64-ninja mingw-w64-x86_64-clang
|
install: mingw-w64-x86_64-libxml2 mingw-w64-x86_64-cmake mingw-w64-x86_64-ninja mingw-w64-x86_64-clang
|
||||||
type: Debug
|
type: Debug
|
||||||
- msystem: "MINGW32"
|
|
||||||
install: mingw-w64-i686-libxml2 mingw-w64-i686-cmake mingw-w64-i686-ninja mingw-w64-i686-clang
|
|
||||||
type: Debug
|
|
||||||
env:
|
env:
|
||||||
CMAKE_GENERATOR: Ninja
|
CMAKE_GENERATOR: Ninja
|
||||||
|
|
||||||
@@ -49,6 +38,6 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
cmake -DSIMDJSON_DEVELOPER_MODE=ON -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_BUILD_TYPE=${{ matrix.type }} -DSIMDJSON_BUILD_STATIC=ON -DSIMDJSON_DO_NOT_USE_THREADS_NO_MATTER_WHAT=ON ..
|
cmake -DSIMDJSON_DEVELOPER_MODE=ON -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_BUILD_TYPE=${{ matrix.type }} -DBUILD_SHARED_LIBS=OFF -DSIMDJSON_DO_NOT_USE_THREADS_NO_MATTER_WHAT=ON ..
|
||||||
cmake --build . --verbose
|
cmake --build . --verbose
|
||||||
ctest -j4 --output-on-failure -LE explicitonly
|
ctest -j4 --output-on-failure -LE explicitonly
|
||||||
|
|||||||
@@ -1,12 +1,6 @@
|
|||||||
name: MSYS2-CI
|
name: MSYS2-CI
|
||||||
|
|
||||||
on:
|
on: [push, pull_request]
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
windows-mingw:
|
windows-mingw:
|
||||||
@@ -25,15 +19,9 @@ jobs:
|
|||||||
- msystem: "MINGW64"
|
- msystem: "MINGW64"
|
||||||
install: mingw-w64-x86_64-cmake mingw-w64-x86_64-ninja mingw-w64-x86_64-gcc
|
install: mingw-w64-x86_64-cmake mingw-w64-x86_64-ninja mingw-w64-x86_64-gcc
|
||||||
type: Release
|
type: Release
|
||||||
- msystem: "MINGW32"
|
|
||||||
install: mingw-w64-i686-cmake mingw-w64-i686-ninja mingw-w64-i686-gcc
|
|
||||||
type: Release
|
|
||||||
- msystem: "MINGW64"
|
- msystem: "MINGW64"
|
||||||
install: mingw-w64-x86_64-cmake mingw-w64-x86_64-ninja mingw-w64-x86_64-gcc
|
install: mingw-w64-x86_64-cmake mingw-w64-x86_64-ninja mingw-w64-x86_64-gcc
|
||||||
type: Debug
|
type: Debug
|
||||||
- msystem: "MINGW32"
|
|
||||||
install: mingw-w64-i686-cmake mingw-w64-i686-ninja mingw-w64-i686-gcc
|
|
||||||
type: Debug
|
|
||||||
env:
|
env:
|
||||||
CMAKE_GENERATOR: Ninja
|
CMAKE_GENERATOR: Ninja
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
name: Ubuntu 18.04 CI (LLVM 7)
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
ubuntu-build:
|
||||||
|
if: >-
|
||||||
|
! contains(toJSON(github.event.commits.*.message), '[skip ci]') &&
|
||||||
|
! contains(toJSON(github.event.commits.*.message), '[skip github]')
|
||||||
|
runs-on: ubuntu-18.04
|
||||||
|
|
||||||
|
env:
|
||||||
|
CC: clang-7
|
||||||
|
CXX: clang++-7
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
path: dependencies/.cache
|
||||||
|
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
|
||||||
|
- name: install clang 7
|
||||||
|
run: |
|
||||||
|
sudo apt update
|
||||||
|
sudo apt install clang-7
|
||||||
|
- name: Use cmake
|
||||||
|
run: |
|
||||||
|
mkdir build &&
|
||||||
|
cd build &&
|
||||||
|
cmake -DSIMDJSON_DEVELOPER_MODE=ON -DSIMDJSON_GOOGLE_BENCHMARKS=ON -DBUILD_SHARED_LIBS=OFF -DCMAKE_INSTALL_PREFIX:PATH=destination .. &&
|
||||||
|
cmake --build . &&
|
||||||
|
ctest -j --output-on-failure -LE explicitonly
|
||||||
@@ -1,12 +1,7 @@
|
|||||||
name: Ubuntu 18.04 CI (GCC 7) with Thread Sanitizer
|
name: Ubuntu 18.04 CI (GCC 7) with Thread Sanitizer
|
||||||
|
|
||||||
on:
|
on: [push, pull_request]
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
ubuntu-build:
|
ubuntu-build:
|
||||||
|
|||||||
@@ -1,12 +1,6 @@
|
|||||||
name: Ubuntu 18.04 CI (GCC 7)
|
name: Ubuntu 18.04 CI (GCC 7)
|
||||||
|
|
||||||
on:
|
on: [push, pull_request]
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
ubuntu-build:
|
ubuntu-build:
|
||||||
|
|||||||
@@ -1,12 +1,6 @@
|
|||||||
name: Ubuntu 20.04 CI (GCC 9) without exceptions
|
name: Ubuntu 20.04 CI (GCC 9) without exceptions
|
||||||
|
|
||||||
on:
|
on: [push, pull_request]
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
ubuntu-build:
|
ubuntu-build:
|
||||||
|
|||||||
@@ -1,12 +1,6 @@
|
|||||||
name: Ubuntu 20.04 CI (GCC 9) without threads
|
name: Ubuntu 20.04 CI (GCC 9) Without Threads
|
||||||
|
|
||||||
on:
|
on: [push, pull_request]
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
ubuntu-build:
|
ubuntu-build:
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
name: Ubuntu 20.04 CI (GCC 9) With Memory Sanitizer
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
ubuntu-build:
|
||||||
|
if: >-
|
||||||
|
! contains(toJSON(github.event.commits.*.message), '[skip ci]') &&
|
||||||
|
! contains(toJSON(github.event.commits.*.message), '[skip github]')
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
path: dependencies/.cache
|
||||||
|
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
|
||||||
|
- name: Use cmake
|
||||||
|
run: |
|
||||||
|
mkdir builddebug &&
|
||||||
|
cd builddebug &&
|
||||||
|
cmake -DSIMDJSON_SANITIZE=ON -DCMAKE_BUILD_TYPE=Debug -DSIMDJSON_GOOGLE_BENCHMARKS=OFF -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=OFF .. &&
|
||||||
|
cmake --build . &&
|
||||||
|
ctest -j --output-on-failure -LE explicitonly
|
||||||
@@ -1,12 +1,6 @@
|
|||||||
name: Ubuntu 20.04 CI (GCC 9) with Thread Sanitizer
|
name: Ubuntu 20.04 CI (GCC 9) with Thread Sanitizer
|
||||||
|
|
||||||
on:
|
on: [push, pull_request]
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
ubuntu-build:
|
ubuntu-build:
|
||||||
|
|||||||
@@ -1,12 +1,6 @@
|
|||||||
name: Ubuntu 20.04 CI (GCC 9)
|
name: Ubuntu 20.04 CI (GCC 9)
|
||||||
|
|
||||||
on:
|
on: [push, pull_request]
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
ubuntu-build:
|
ubuntu-build:
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
name: Ubuntu 22.04 CI (GCC 11)
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
ubuntu-build:
|
||||||
|
if: >-
|
||||||
|
! contains(toJSON(github.event.commits.*.message), '[skip ci]') &&
|
||||||
|
! contains(toJSON(github.event.commits.*.message), '[skip github]')
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
path: dependencies/.cache
|
||||||
|
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
|
||||||
|
- name: Use cmake
|
||||||
|
run: |
|
||||||
|
mkdir builddebug &&
|
||||||
|
cd builddebug &&
|
||||||
|
cmake -DCMAKE_BUILD_TYPE=Debug -DSIMDJSON_GOOGLE_BENCHMARKS=OFF -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=OFF .. &&
|
||||||
|
cmake --build . &&
|
||||||
|
ctest -j --output-on-failure -LE explicitonly &&
|
||||||
|
cd .. &&
|
||||||
|
mkdir build &&
|
||||||
|
cd build &&
|
||||||
|
cmake -DSIMDJSON_GOOGLE_BENCHMARKS=ON -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=OFF -DCMAKE_INSTALL_PREFIX:PATH=destination .. &&
|
||||||
|
cmake --build . &&
|
||||||
|
ctest -j --output-on-failure -LE explicitonly &&
|
||||||
|
cmake --install . &&
|
||||||
|
echo -e '#include <simdjson.h>\nint main(int argc,char**argv) {simdjson::dom::parser parser;simdjson::dom::element tweets = parser.load(argv[1]); }' > tmp.cpp && c++ -Idestination/include -Ldestination/lib -std=c++17 -Wl,-rpath,destination/lib -o linkandrun tmp.cpp -lsimdjson && ./linkandrun jsonexamples/twitter.json &&
|
||||||
|
cd ../tests/installation_tests/find &&
|
||||||
|
mkdir build && cd build && cmake -DCMAKE_INSTALL_PREFIX:PATH=../../../build/destination .. && cmake --build .
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
name: VS16-CLANG-CI
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
ci:
|
|
||||||
if: >-
|
|
||||||
! contains(toJSON(github.event.commits.*.message), '[skip ci]') &&
|
|
||||||
! contains(toJSON(github.event.commits.*.message), '[skip github]')
|
|
||||||
name: windows-vs16
|
|
||||||
runs-on: windows-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- uses: actions/cache@v2
|
|
||||||
with:
|
|
||||||
path: dependencies/.cache
|
|
||||||
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
|
|
||||||
- name: 'Run CMake with VS16 Clang'
|
|
||||||
uses: lukka/run-cmake@v3
|
|
||||||
with:
|
|
||||||
cmakeListsOrSettingsJson: CMakeListsTxtAdvanced
|
|
||||||
cmakeListsTxtPath: '${{ github.workspace }}/CMakeLists.txt'
|
|
||||||
buildDirectory: "${{ github.workspace }}/../../_temp/windows"
|
|
||||||
cmakeBuildType: Release
|
|
||||||
buildWithCMake: true
|
|
||||||
cmakeAppendedArgs: -T ClangCL -DSIMDJSON_COMPETITION=OFF -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=OFF
|
|
||||||
buildWithCMakeArgs: --config Release
|
|
||||||
|
|
||||||
- name: 'Run CTest'
|
|
||||||
run: ctest -C Release -LE explicitonly --output-on-failure
|
|
||||||
working-directory: "${{ github.workspace }}/../../_temp/windows"
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
name: VS16-Ninja-CI
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
ci:
|
|
||||||
if: >-
|
|
||||||
! contains(toJSON(github.event.commits.*.message), '[skip ci]') &&
|
|
||||||
! contains(toJSON(github.event.commits.*.message), '[skip github]')
|
|
||||||
name: windows-vs16
|
|
||||||
runs-on: windows-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- uses: actions/cache@v2
|
|
||||||
with:
|
|
||||||
path: dependencies/.cache
|
|
||||||
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
|
|
||||||
- name: 'Run CMake with VS16'
|
|
||||||
uses: lukka/run-cmake@v2
|
|
||||||
with:
|
|
||||||
cmakeListsOrSettingsJson: CMakeListsTxtAdvanced
|
|
||||||
cmakeListsTxtPath: '${{ github.workspace }}/CMakeLists.txt'
|
|
||||||
buildDirectory: "${{ github.workspace }}/../../_temp/windows"
|
|
||||||
cmakeBuildType: Release
|
|
||||||
buildWithCMake: true
|
|
||||||
cmakeAppendedArgs: -G Ninja -DSIMDJSON_COMPETITION=OFF -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=OFF
|
|
||||||
buildWithCMakeArgs: --config Release
|
|
||||||
- name: 'Run CTest'
|
|
||||||
run: ctest -C Release -LE explicitonly --output-on-failure
|
|
||||||
working-directory: "${{ github.workspace }}/../../_temp/windows"
|
|
||||||
- name: 'Install with CMake'
|
|
||||||
uses: lukka/run-cmake@v3
|
|
||||||
with:
|
|
||||||
cmakeListsTxtPath: '${{ github.workspace }}/CMakeLists.txt'
|
|
||||||
buildWithCMakeArgs: '--target install'
|
|
||||||
- name: 'Test Installation with CMake'
|
|
||||||
uses: lukka/run-cmake@v3
|
|
||||||
with:
|
|
||||||
cmakeListsOrSettingsJson: CMakeListsTxtAdvanced
|
|
||||||
cmakeListsTxtPath: '${{ github.workspace }}/tests/installation_tests/find/CMakeLists.txt'
|
|
||||||
cmakeBuildType: Release
|
|
||||||
buildWithCMake: true
|
|
||||||
buildDirectory: '${{ github.workspace }}/tests/installation_tests/find/buildDirectory'
|
|
||||||
cmakeAppendedArgs: -G Ninja
|
|
||||||
buildWithCMakeArgs: '--config Release --verbose'
|
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
name: VS16-ARM-CI
|
name: VS17-ARM-CI
|
||||||
|
|
||||||
on: [push, pull_request]
|
on: [push, pull_request]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
ci:
|
ci:
|
||||||
name: windows-vs16
|
name: windows-vs17
|
||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
@@ -1,34 +1,28 @@
|
|||||||
name: VS16-CI
|
name: VS17-CI
|
||||||
|
|
||||||
on:
|
on: [push, pull_request]
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
ci:
|
ci:
|
||||||
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]')
|
||||||
name: windows-vs16
|
name: windows-vs17
|
||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- {gen: Visual Studio 16 2019, arch: Win32, static: ON}
|
- {gen: Visual Studio 17 2022, arch: Win32, shared: ON}
|
||||||
- {gen: Visual Studio 16 2019, arch: Win32, static: OFF}
|
- {gen: Visual Studio 17 2022, arch: Win32, shared: OFF}
|
||||||
- {gen: Visual Studio 16 2019, arch: x64, static: ON}
|
- {gen: Visual Studio 17 2022, arch: x64, shared: ON}
|
||||||
- {gen: Visual Studio 16 2019, arch: x64, static: OFF}
|
- {gen: Visual Studio 17 2022, arch: x64, shared: OFF}
|
||||||
steps:
|
steps:
|
||||||
- name: checkout
|
- name: checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
- name: Configure
|
- name: Configure
|
||||||
run: |
|
run: |
|
||||||
cmake -G "${{matrix.gen}}" -A ${{matrix.arch}} -DSIMDJSON_DEVELOPER_MODE=ON -DSIMDJSON_COMPETITION=OFF -DSIMDJSON_BUILD_STATIC=${{matrix.static}} -B build
|
cmake -G "${{matrix.gen}}" -A ${{matrix.arch}} -DSIMDJSON_DEVELOPER_MODE=ON -DSIMDJSON_COMPETITION=OFF -DBUILD_SHARED_LIBS=${{matrix.shared}} -B build
|
||||||
- name: Build Debug
|
- name: Build Debug
|
||||||
run: cmake --build build --config Debug --verbose
|
run: cmake --build build --config Debug --verbose
|
||||||
- name: Build Release
|
- name: Build Release
|
||||||
@@ -1,34 +1,25 @@
|
|||||||
name: VS15-CI
|
name: VS17-CLANG-CI
|
||||||
|
|
||||||
on:
|
on: [push, pull_request]
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
ci:
|
ci:
|
||||||
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]')
|
||||||
name: windows-vs15
|
name: windows-vs17
|
||||||
runs-on: windows-2016
|
runs-on: windows-latest
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- {gen: Visual Studio 15 2017, arch: Win32, static: ON}
|
- {gen: Visual Studio 17 2022, arch: x64}
|
||||||
- {gen: Visual Studio 15 2017, arch: Win32, static: OFF}
|
|
||||||
- {gen: Visual Studio 15 2017, arch: x64, static: ON}
|
|
||||||
- {gen: Visual Studio 15 2017, arch: x64, static: OFF}
|
|
||||||
steps:
|
steps:
|
||||||
- name: checkout
|
- name: checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
- name: Configure
|
- name: Configure
|
||||||
run: |
|
run: |
|
||||||
cmake -G "${{matrix.gen}}" -A ${{matrix.arch}} -DSIMDJSON_COMPETITION=OFF -DSIMDJSON_DEVELOPER_MODE=ON -DSIMDJSON_BUILD_STATIC=${{matrix.static}} -B build
|
cmake -G "${{matrix.gen}}" -A ${{matrix.arch}} -T ClangCL -DSIMDJSON_DEVELOPER_MODE=ON -DSIMDJSON_COMPETITION=OFF -B build
|
||||||
- name: Build Debug
|
- name: Build Debug
|
||||||
run: cmake --build build --config Debug --verbose
|
run: cmake --build build --config Debug --verbose
|
||||||
- name: Build Release
|
- name: Build Release
|
||||||
@@ -1,16 +1,10 @@
|
|||||||
name: VS16-NoExcept-CI
|
name: VS17-NoExcept-CI
|
||||||
|
|
||||||
on:
|
on: [push, pull_request]
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
ci:
|
ci:
|
||||||
name: windows-vs16
|
name: windows-vs17
|
||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
@@ -18,7 +12,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
path: dependencies/.cache
|
path: dependencies/.cache
|
||||||
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
|
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
|
||||||
- name: 'Run CMake with VS16'
|
- name: 'Run CMake with VS17'
|
||||||
uses: lukka/run-cmake@v3
|
uses: lukka/run-cmake@v3
|
||||||
with:
|
with:
|
||||||
cmakeListsOrSettingsJson: CMakeListsTxtAdvanced
|
cmakeListsOrSettingsJson: CMakeListsTxtAdvanced
|
||||||
Vendored
+3
-2
@@ -17,7 +17,6 @@
|
|||||||
"__errc": "cpp",
|
"__errc": "cpp",
|
||||||
"__functional_base": "cpp",
|
"__functional_base": "cpp",
|
||||||
"__hash_table": "cpp",
|
"__hash_table": "cpp",
|
||||||
"__locale": "cpp",
|
|
||||||
"__mutex_base": "cpp",
|
"__mutex_base": "cpp",
|
||||||
"__node_handle": "cpp",
|
"__node_handle": "cpp",
|
||||||
"__nullptr": "cpp",
|
"__nullptr": "cpp",
|
||||||
@@ -85,6 +84,8 @@
|
|||||||
"utility": "cpp",
|
"utility": "cpp",
|
||||||
"valarray": "cpp",
|
"valarray": "cpp",
|
||||||
"vector": "cpp",
|
"vector": "cpp",
|
||||||
"*.ipp": "cpp"
|
"*.ipp": "cpp",
|
||||||
|
"__functional_base_03": "cpp",
|
||||||
|
"filesystem": "cpp"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+5
-13
@@ -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 0.9.1
|
VERSION 2.0.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
|
||||||
@@ -20,8 +20,8 @@ string(
|
|||||||
# ---- Options, variables ----
|
# ---- Options, variables ----
|
||||||
|
|
||||||
# These version numbers are modified by tools/release.py
|
# These version numbers are modified by tools/release.py
|
||||||
set(SIMDJSON_LIB_VERSION "8.0.0" CACHE STRING "simdjson library version")
|
set(SIMDJSON_LIB_VERSION "11.0.0" CACHE STRING "simdjson library version")
|
||||||
set(SIMDJSON_LIB_SOVERSION "8" CACHE STRING "simdjson library soversion")
|
set(SIMDJSON_LIB_SOVERSION "11" CACHE STRING "simdjson library soversion")
|
||||||
|
|
||||||
option(SIMDJSON_ENABLE_THREADS "Link with thread support" ON)
|
option(SIMDJSON_ENABLE_THREADS "Link with thread support" ON)
|
||||||
|
|
||||||
@@ -49,19 +49,10 @@ endif()
|
|||||||
if(is_top_project)
|
if(is_top_project)
|
||||||
option(SIMDJSON_DEVELOPER_MODE "Enable targets for developing simdjson" OFF)
|
option(SIMDJSON_DEVELOPER_MODE "Enable targets for developing simdjson" OFF)
|
||||||
option(BUILD_SHARED_LIBS "Build simdjson as a shared library" OFF)
|
option(BUILD_SHARED_LIBS "Build simdjson as a shared library" OFF)
|
||||||
|
|
||||||
if("$ENV{CI}")
|
|
||||||
set(SIMDJSON_DEVELOPER_MODE ON CACHE INTERNAL "")
|
|
||||||
endif()
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
include(cmake/handle-deprecations.cmake)
|
include(cmake/handle-deprecations.cmake)
|
||||||
|
include(cmake/developer-options.cmake)
|
||||||
if(SIMDJSON_DEVELOPER_MODE)
|
|
||||||
include(cmake/developer-options.cmake)
|
|
||||||
else()
|
|
||||||
message(STATUS "Building only the library. Advanced users may want to turn SIMDJSON_DEVELOPER_MODE to ON, e.g., via -D SIMDJSON_DEVELOPER_MODE=ON.")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# ---- simdjson library ----
|
# ---- simdjson library ----
|
||||||
|
|
||||||
@@ -180,6 +171,7 @@ endif()
|
|||||||
# ---- Developer mode extras ----
|
# ---- Developer mode extras ----
|
||||||
|
|
||||||
if(NOT SIMDJSON_DEVELOPER_MODE)
|
if(NOT SIMDJSON_DEVELOPER_MODE)
|
||||||
|
message(STATUS "Building only the library. Advanced users may want to turn SIMDJSON_DEVELOPER_MODE to ON, e.g., via -D SIMDJSON_DEVELOPER_MODE=ON.")
|
||||||
return()
|
return()
|
||||||
elseif(NOT is_top_project)
|
elseif(NOT is_top_project)
|
||||||
message(AUTHOR_WARNING "Developer mode is intended for developers of simdjson")
|
message(AUTHOR_WARNING "Developer mode is intended for developers of simdjson")
|
||||||
|
|||||||
@@ -37,5 +37,9 @@ Furkan Taşkale
|
|||||||
Brendan Knapp
|
Brendan Knapp
|
||||||
Danila Kutenin
|
Danila Kutenin
|
||||||
Pavel Pavlov
|
Pavel Pavlov
|
||||||
|
Hao Chen
|
||||||
|
Nicolas Boyer
|
||||||
|
Kim Walisch and Jatin Bhateja (AVX-512 bitset decoder)
|
||||||
|
Fangzheng Zhang and Weiqiang Wan (AVX-512 kernel)
|
||||||
# if you have contributed to the project and your name does not
|
# if you have contributed to the project and your name does not
|
||||||
# appear in this list, please let us know!
|
# appear in this list, please let us know!
|
||||||
|
|||||||
@@ -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 = "0.9.1"
|
PROJECT_NUMBER = "2.0.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
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
[/badge.svg)](https://simdjson.org/plots.html)
|
[/badge.svg)](https://simdjson.org/plots.html)
|
||||||

|

|
||||||

|

|
||||||
[![][license img]][license] [](https://simdjson.org/api/0.9.0/index.html)
|
[![][license img]][license] [](https://simdjson.org/api/2.0.0/index.html)
|
||||||
|
|
||||||
simdjson : Parsing gigabytes of JSON per second
|
simdjson : Parsing gigabytes of JSON per second
|
||||||
===============================================
|
===============================================
|
||||||
@@ -53,6 +53,7 @@ The simdjson library is easily consumable with a single .h and .cpp file.
|
|||||||
2. Create `quickstart.cpp`:
|
2. Create `quickstart.cpp`:
|
||||||
|
|
||||||
```c++
|
```c++
|
||||||
|
#include <iostream>
|
||||||
#include "simdjson.h"
|
#include "simdjson.h"
|
||||||
using namespace simdjson;
|
using namespace simdjson;
|
||||||
int main(void) {
|
int main(void) {
|
||||||
@@ -78,7 +79,7 @@ Usage documentation is available:
|
|||||||
* [Performance](doc/performance.md) shows some more advanced scenarios and how to tune for them.
|
* [Performance](doc/performance.md) shows some more advanced scenarios and how to tune for them.
|
||||||
* [Implementation Selection](doc/implementation-selection.md) describes runtime CPU detection and
|
* [Implementation Selection](doc/implementation-selection.md) describes runtime CPU detection and
|
||||||
how you can work with it.
|
how you can work with it.
|
||||||
* [API](https://simdjson.org/api/0.9.0/annotated.html) contains the automatically generated API documentation.
|
* [API](https://simdjson.org/api/1.0.0/annotated.html) contains the automatically generated API documentation.
|
||||||
|
|
||||||
Performance results
|
Performance results
|
||||||
-------------------
|
-------------------
|
||||||
@@ -137,6 +138,7 @@ We distinguish between "bindings" (which just wrap the C++ code) and a port to a
|
|||||||
- [rcppsimdjson](https://github.com/eddelbuettel/rcppsimdjson): R bindings.
|
- [rcppsimdjson](https://github.com/eddelbuettel/rcppsimdjson): R bindings.
|
||||||
- [simdjson_erlang](https://github.com/ChomperT/simdjson_erlang): erlang bindings.
|
- [simdjson_erlang](https://github.com/ChomperT/simdjson_erlang): erlang bindings.
|
||||||
- [lua-simdjson](https://github.com/FourierTransformer/lua-simdjson): lua bindings.
|
- [lua-simdjson](https://github.com/FourierTransformer/lua-simdjson): lua bindings.
|
||||||
|
- [hermes-json](https://hackage.haskell.org/package/hermes-json): haskell bindings.
|
||||||
|
|
||||||
|
|
||||||
About simdjson
|
About simdjson
|
||||||
@@ -158,7 +160,7 @@ We also have an informal [blog post providing some background and context](https
|
|||||||
|
|
||||||
For the video inclined, <br />
|
For the video inclined, <br />
|
||||||
[](http://www.youtube.com/watch?v=wlvKAT7SZIQ)<br />
|
[](http://www.youtube.com/watch?v=wlvKAT7SZIQ)<br />
|
||||||
(it was the best voted talk, we're kinda proud of it).
|
(It was the best voted talk, we're kinda proud of it.)
|
||||||
|
|
||||||
Funding
|
Funding
|
||||||
-------
|
-------
|
||||||
|
|||||||
@@ -4,8 +4,12 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
|
||||||
namespace amazon_cellphones {
|
namespace amazon_cellphones {
|
||||||
|
|
||||||
|
const bool UNTHREADED = false;
|
||||||
|
const bool THREADED = true;
|
||||||
|
|
||||||
using namespace json_benchmark;
|
using namespace json_benchmark;
|
||||||
|
|
||||||
struct brand {
|
struct brand {
|
||||||
@@ -59,10 +63,11 @@ struct runner : public file_runner<I> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<bool threaded>
|
||||||
struct simdjson_dom;
|
struct simdjson_dom;
|
||||||
|
|
||||||
template<typename I> simdjson_really_inline static void amazon_cellphones(benchmark::State &state) {
|
template<typename I> simdjson_really_inline static void amazon_cellphones(benchmark::State &state) {
|
||||||
run_json_benchmark<runner<I>, runner<simdjson_dom>>(state);
|
run_json_benchmark<runner<I>, runner<simdjson_dom<UNTHREADED>>>(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace amazon_cellphones
|
} // namespace amazon_cellphones
|
||||||
@@ -8,12 +8,16 @@ namespace amazon_cellphones {
|
|||||||
|
|
||||||
using namespace simdjson;
|
using namespace simdjson;
|
||||||
|
|
||||||
|
template<bool threaded>
|
||||||
struct simdjson_dom {
|
struct simdjson_dom {
|
||||||
using StringType = std::string;
|
using StringType = std::string;
|
||||||
|
|
||||||
dom::parser parser{};
|
dom::parser parser{};
|
||||||
|
|
||||||
bool run(simdjson::padded_string &json, std::map<StringType, brand> &result) {
|
bool run(simdjson::padded_string &json, std::map<StringType, brand> &result) {
|
||||||
|
#ifdef SIMDJSON_THREADS_ENABLED
|
||||||
|
parser.threaded = threaded;
|
||||||
|
#endif
|
||||||
auto stream = parser.parse_many(json);
|
auto stream = parser.parse_many(json);
|
||||||
auto i = stream.begin();
|
auto i = stream.begin();
|
||||||
++i; // Skip first line
|
++i; // Skip first line
|
||||||
@@ -37,7 +41,10 @@ struct simdjson_dom {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
BENCHMARK_TEMPLATE(amazon_cellphones, simdjson_dom)->UseManualTime();
|
BENCHMARK_TEMPLATE(amazon_cellphones, simdjson_dom<UNTHREADED>)->UseManualTime();
|
||||||
|
#ifdef SIMDJSON_THREADS_ENABLED
|
||||||
|
BENCHMARK_TEMPLATE(amazon_cellphones, simdjson_dom<THREADED>)->UseManualTime();
|
||||||
|
#endif
|
||||||
|
|
||||||
} // namespace amazon_cellphones
|
} // namespace amazon_cellphones
|
||||||
|
|
||||||
|
|||||||
@@ -8,17 +8,21 @@ namespace amazon_cellphones {
|
|||||||
|
|
||||||
using namespace simdjson;
|
using namespace simdjson;
|
||||||
|
|
||||||
|
template<bool threaded>
|
||||||
struct simdjson_ondemand {
|
struct simdjson_ondemand {
|
||||||
using StringType = std::string;
|
using StringType = std::string;
|
||||||
|
|
||||||
ondemand::parser parser{};
|
ondemand::parser parser{};
|
||||||
|
|
||||||
bool run(simdjson::padded_string &json, std::map<StringType, brand> &result) {
|
bool run(simdjson::padded_string &json, std::map<StringType, brand> &result) {
|
||||||
|
#ifdef SIMDJSON_THREADS_ENABLED
|
||||||
|
parser.threaded = threaded;
|
||||||
|
#endif
|
||||||
ondemand::document_stream stream = parser.iterate_many(json);
|
ondemand::document_stream stream = parser.iterate_many(json);
|
||||||
ondemand::document_stream::iterator i = stream.begin();
|
ondemand::document_stream::iterator i = stream.begin();
|
||||||
++i; // Skip first line
|
++i; // Skip first line
|
||||||
for (;i != stream.end(); ++i) {
|
for (;i != stream.end(); ++i) {
|
||||||
auto & doc = *i;
|
auto doc = *i;
|
||||||
size_t index{0};
|
size_t index{0};
|
||||||
StringType copy;
|
StringType copy;
|
||||||
double rating;
|
double rating;
|
||||||
@@ -58,7 +62,10 @@ struct simdjson_ondemand {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
BENCHMARK_TEMPLATE(amazon_cellphones, simdjson_ondemand)->UseManualTime();
|
BENCHMARK_TEMPLATE(amazon_cellphones, simdjson_ondemand<UNTHREADED>)->UseManualTime();
|
||||||
|
#ifdef SIMDJSON_THREADS_ENABLED
|
||||||
|
BENCHMARK_TEMPLATE(amazon_cellphones, simdjson_ondemand<THREADED>)->UseManualTime();
|
||||||
|
#endif
|
||||||
|
|
||||||
} // namespace amazon_cellphones
|
} // namespace amazon_cellphones
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#include <benchmark/benchmark.h>
|
#include <benchmark/benchmark.h>
|
||||||
|
#include <iostream>
|
||||||
#include "simdjson.h"
|
#include "simdjson.h"
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#include <benchmark/benchmark.h>
|
#include <benchmark/benchmark.h>
|
||||||
|
#include <iostream>
|
||||||
#include "simdjson.h"
|
#include "simdjson.h"
|
||||||
using namespace simdjson;
|
using namespace simdjson;
|
||||||
using namespace benchmark;
|
using namespace benchmark;
|
||||||
|
|||||||
@@ -97,9 +97,9 @@ struct option_struct {
|
|||||||
verbose = true;
|
verbose = true;
|
||||||
break;
|
break;
|
||||||
case 'a': {
|
case 'a': {
|
||||||
auto impl = simdjson::available_implementations[optarg];
|
auto impl = simdjson::get_available_implementations()[optarg];
|
||||||
if(impl && impl->supported_by_runtime_system()) {
|
if(impl && impl->supported_by_runtime_system()) {
|
||||||
simdjson::active_implementation = impl;
|
simdjson::get_active_implementation() = impl;
|
||||||
} else {
|
} else {
|
||||||
std::cerr << "implementation " << optarg << " not found or not supported " << std::endl;
|
std::cerr << "implementation " << optarg << " not found or not supported " << std::endl;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
#define __BENCHMARKER_H
|
#define __BENCHMARKER_H
|
||||||
|
|
||||||
#include "event_counter.h"
|
#include "event_counter.h"
|
||||||
#include "simdjson.h" // For SIMDJSON_DISABLE_DEPRECATED_WARNINGS
|
#include "simdjson.h"
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ void print_usage(ostream& out) {
|
|||||||
out << "-H - Make the buffers hot (reduce page allocation and related OS tasks during parsing) [default]" << endl;
|
out << "-H - Make the buffers hot (reduce page allocation and related OS tasks during parsing) [default]" << endl;
|
||||||
out << "-a IMPL - Use the given parser implementation. By default, detects the most advanced" << endl;
|
out << "-a IMPL - Use the given parser implementation. By default, detects the most advanced" << endl;
|
||||||
out << " implementation supported on the host machine." << endl;
|
out << " implementation supported on the host machine." << endl;
|
||||||
for (auto impl : simdjson::available_implementations) {
|
for (auto impl : simdjson::get_available_implementations()) {
|
||||||
if(impl->supported_by_runtime_system()) {
|
if(impl->supported_by_runtime_system()) {
|
||||||
out << "-a " << std::left << std::setw(9) << impl->name() << " - Use the " << impl->description() << " parser implementation." << endl;
|
out << "-a " << std::left << std::setw(9) << impl->name() << " - Use the " << impl->description() << " parser implementation." << endl;
|
||||||
}
|
}
|
||||||
@@ -116,10 +116,10 @@ struct option_struct {
|
|||||||
verbose = true;
|
verbose = true;
|
||||||
break;
|
break;
|
||||||
case 'a': {
|
case 'a': {
|
||||||
const implementation *impl = simdjson::available_implementations[optarg];
|
const implementation *impl = simdjson::get_available_implementations()[optarg];
|
||||||
if ((!impl) || (!impl->supported_by_runtime_system())) {
|
if ((!impl) || (!impl->supported_by_runtime_system())) {
|
||||||
std::string exit_message = string("Unsupported option value -a ") + optarg + ": expected -a with one of ";
|
std::string exit_message = string("Unsupported option value -a ") + optarg + ": expected -a with one of ";
|
||||||
for (auto imple : simdjson::available_implementations) {
|
for (auto imple : simdjson::get_available_implementations()) {
|
||||||
if(imple->supported_by_runtime_system()) {
|
if(imple->supported_by_runtime_system()) {
|
||||||
exit_message += imple->name();
|
exit_message += imple->name();
|
||||||
exit_message += " ";
|
exit_message += " ";
|
||||||
@@ -127,7 +127,7 @@ struct option_struct {
|
|||||||
}
|
}
|
||||||
exit_usage(exit_message);
|
exit_usage(exit_message);
|
||||||
}
|
}
|
||||||
simdjson::active_implementation = impl;
|
simdjson::get_active_implementation() = impl;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'C':
|
case 'C':
|
||||||
@@ -175,7 +175,7 @@ int main(int argc, char *argv[]) {
|
|||||||
option_struct options(argc, argv);
|
option_struct options(argc, argv);
|
||||||
if (options.verbose) {
|
if (options.verbose) {
|
||||||
verbose_stream = &cout;
|
verbose_stream = &cout;
|
||||||
verbose() << "Implementation: " << simdjson::active_implementation->name() << endl;
|
verbose() << "Implementation: " << simdjson::get_active_implementation()->name() << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start collecting events. We put this early so if it prints an error message, it's the
|
// Start collecting events. We put this early so if it prints an error message, it's the
|
||||||
|
|||||||
@@ -50,9 +50,9 @@ simdjson_really_inline void simdjson_process_atom(stat_t &s,
|
|||||||
} else if(element.is<double>()) {
|
} else if(element.is<double>()) {
|
||||||
s.float_count++;
|
s.float_count++;
|
||||||
} else if (element.is<bool>()) {
|
} else if (element.is<bool>()) {
|
||||||
simdjson::error_code err;
|
|
||||||
bool v;
|
bool v;
|
||||||
err = element.get(v);
|
simdjson::error_code error;
|
||||||
|
if ((error = element.get(v))) { std::cerr << error << std::endl; abort(); }
|
||||||
if (v) {
|
if (v) {
|
||||||
s.true_count++;
|
s.true_count++;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ void maybe_display_implementation() {
|
|||||||
static bool displayed_implementation = false;
|
static bool displayed_implementation = false;
|
||||||
if(!displayed_implementation) {
|
if(!displayed_implementation) {
|
||||||
displayed_implementation = true;
|
displayed_implementation = true;
|
||||||
std::cout << "simdjson::dom implementation: " << simdjson::active_implementation->name() << std::endl;
|
std::cout << "simdjson::dom implementation: " << simdjson::get_active_implementation()->name() << std::endl;
|
||||||
std::cout << "simdjson::ondemand implementation (stage 1): " << simdjson::active_implementation->name() << std::endl;
|
std::cout << "simdjson::ondemand implementation (stage 1): " << simdjson::get_active_implementation()->name() << std::endl;
|
||||||
std::cout << "simdjson::ondemand implementation (stage 2): " << simdjson::builtin_implementation()->name() << std::endl;
|
std::cout << "simdjson::ondemand implementation (stage 2): " << simdjson::builtin_implementation()->name() << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,9 @@
|
|||||||
|
|
||||||
namespace large_amazon_cellphones {
|
namespace large_amazon_cellphones {
|
||||||
|
|
||||||
|
const bool UNTHREADED = false;
|
||||||
|
const bool THREADED = true;
|
||||||
|
|
||||||
static const simdjson::padded_string &get_built_json();
|
static const simdjson::padded_string &get_built_json();
|
||||||
|
|
||||||
using namespace json_benchmark;
|
using namespace json_benchmark;
|
||||||
@@ -81,11 +84,11 @@ static const simdjson::padded_string &get_built_json() {
|
|||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<bool threaded>
|
||||||
struct simdjson_dom;
|
struct simdjson_dom;
|
||||||
|
|
||||||
template<typename I> simdjson_really_inline static void large_amazon_cellphones(benchmark::State &state) {
|
template<typename I> simdjson_really_inline static void large_amazon_cellphones(benchmark::State &state) {
|
||||||
run_json_benchmark<runner<I>, runner<simdjson_dom>>(state);
|
run_json_benchmark<runner<I>, runner<simdjson_dom<UNTHREADED>>>(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace large_amazon_cellphones
|
} // namespace large_amazon_cellphones
|
||||||
@@ -9,12 +9,16 @@ namespace large_amazon_cellphones {
|
|||||||
|
|
||||||
using namespace simdjson;
|
using namespace simdjson;
|
||||||
|
|
||||||
|
template<bool threaded>
|
||||||
struct simdjson_dom {
|
struct simdjson_dom {
|
||||||
using StringType = std::string;
|
using StringType = std::string;
|
||||||
|
|
||||||
dom::parser parser{};
|
dom::parser parser{};
|
||||||
|
|
||||||
bool run(simdjson::padded_string &json, std::map<StringType, brand> &result) {
|
bool run(simdjson::padded_string &json, std::map<StringType, brand> &result) {
|
||||||
|
#ifdef SIMDJSON_THREADS_ENABLED
|
||||||
|
parser.threaded = threaded;
|
||||||
|
#endif
|
||||||
auto stream = parser.parse_many(json);
|
auto stream = parser.parse_many(json);
|
||||||
auto i = stream.begin();
|
auto i = stream.begin();
|
||||||
++i; // Skip first line
|
++i; // Skip first line
|
||||||
@@ -38,7 +42,10 @@ struct simdjson_dom {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
BENCHMARK_TEMPLATE(large_amazon_cellphones, simdjson_dom)->UseManualTime();
|
BENCHMARK_TEMPLATE(large_amazon_cellphones, simdjson_dom<UNTHREADED>)->UseManualTime();
|
||||||
|
#ifdef SIMDJSON_THREADS_ENABLED
|
||||||
|
BENCHMARK_TEMPLATE(large_amazon_cellphones, simdjson_dom<THREADED>)->UseManualTime();
|
||||||
|
#endif
|
||||||
|
|
||||||
} // namespace large_amazon_cellphones
|
} // namespace large_amazon_cellphones
|
||||||
|
|
||||||
|
|||||||
@@ -8,17 +8,21 @@ namespace large_amazon_cellphones {
|
|||||||
|
|
||||||
using namespace simdjson;
|
using namespace simdjson;
|
||||||
|
|
||||||
|
template<bool threaded>
|
||||||
struct simdjson_ondemand {
|
struct simdjson_ondemand {
|
||||||
using StringType = std::string;
|
using StringType = std::string;
|
||||||
|
|
||||||
ondemand::parser parser{};
|
ondemand::parser parser{};
|
||||||
|
|
||||||
bool run(simdjson::padded_string &json, std::map<StringType, brand> &result) {
|
bool run(simdjson::padded_string &json, std::map<StringType, brand> &result) {
|
||||||
|
#ifdef SIMDJSON_THREADS_ENABLED
|
||||||
|
parser.threaded = threaded;
|
||||||
|
#endif
|
||||||
ondemand::document_stream stream = parser.iterate_many(json);
|
ondemand::document_stream stream = parser.iterate_many(json);
|
||||||
ondemand::document_stream::iterator i = stream.begin();
|
ondemand::document_stream::iterator i = stream.begin();
|
||||||
++i; // Skip first line
|
++i; // Skip first line
|
||||||
for (;i != stream.end(); ++i) {
|
for (;i != stream.end(); ++i) {
|
||||||
auto & doc = *i;
|
auto doc = *i;
|
||||||
size_t index{0};
|
size_t index{0};
|
||||||
StringType copy;
|
StringType copy;
|
||||||
double rating;
|
double rating;
|
||||||
@@ -58,7 +62,10 @@ struct simdjson_ondemand {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
BENCHMARK_TEMPLATE(large_amazon_cellphones, simdjson_ondemand)->UseManualTime();
|
BENCHMARK_TEMPLATE(large_amazon_cellphones, simdjson_ondemand<UNTHREADED>)->UseManualTime();
|
||||||
|
#ifdef SIMDJSON_THREADS_ENABLED
|
||||||
|
BENCHMARK_TEMPLATE(large_amazon_cellphones, simdjson_ondemand<THREADED>)->UseManualTime();
|
||||||
|
#endif
|
||||||
|
|
||||||
} // namespace amazon_cellphones
|
} // namespace amazon_cellphones
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,12 @@
|
|||||||
#
|
#
|
||||||
add_library(simdjson-internal-flags INTERFACE)
|
add_library(simdjson-internal-flags INTERFACE)
|
||||||
|
|
||||||
|
|
||||||
|
option(SIMDJSON_CHECK_EOF "Check for the end of the input buffer. The setting is unnecessary since we require padding of the inputs. You should expect tests to fail with this option turned on." OFF)
|
||||||
|
if(SIMDJSON_CHECK_EOF)
|
||||||
|
add_compile_definitions(SIMDJSON_CHECK_EOF=1)
|
||||||
|
endif()
|
||||||
|
|
||||||
option(SIMDJSON_SANITIZE_UNDEFINED "Sanitize undefined behavior" OFF)
|
option(SIMDJSON_SANITIZE_UNDEFINED "Sanitize undefined behavior" OFF)
|
||||||
if(SIMDJSON_SANITIZE_UNDEFINED)
|
if(SIMDJSON_SANITIZE_UNDEFINED)
|
||||||
add_compile_options(-fsanitize=undefined -fno-sanitize-recover=all)
|
add_compile_options(-fsanitize=undefined -fno-sanitize-recover=all)
|
||||||
@@ -169,6 +175,18 @@ if(CMAKE_C_COMPILER_ID MATCHES "Intel")
|
|||||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -static-intel")
|
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -static-intel")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
option(
|
||||||
|
SIMDJSON_AVX512_ALLOWED
|
||||||
|
"Enable AVX-512 instructions (only affects processors and compilers with AVX-512 support)."
|
||||||
|
ON
|
||||||
|
)
|
||||||
|
if(SIMDJSON_AVX512_ALLOWED)
|
||||||
|
add_compile_definitions(SIMDJSON_AVX512_ALLOWED=1)
|
||||||
|
else()
|
||||||
|
add_compile_definitions(SIMDJSON_AVX512_ALLOWED=0)
|
||||||
|
message(STATUS "AVX-512 instructions are not allowed.")
|
||||||
|
endif()
|
||||||
|
|
||||||
include(CheckSymbolExists)
|
include(CheckSymbolExists)
|
||||||
check_symbol_exists(fork unistd.h HAVE_POSIX_FORK)
|
check_symbol_exists(fork unistd.h HAVE_POSIX_FORK)
|
||||||
check_symbol_exists(wait sys/wait.h HAVE_POSIX_WAIT)
|
check_symbol_exists(wait sys/wait.h HAVE_POSIX_WAIT)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#
|
#
|
||||||
# Implementation selection
|
# Implementation selection
|
||||||
#
|
#
|
||||||
set(SIMDJSON_ALL_IMPLEMENTATIONS fallback westmere haswell arm64 ppc64)
|
set(SIMDJSON_ALL_IMPLEMENTATIONS fallback westmere haswell icelake arm64 ppc64)
|
||||||
|
|
||||||
set(
|
set(
|
||||||
SIMDJSON_IMPLEMENTATION ""
|
SIMDJSON_IMPLEMENTATION ""
|
||||||
@@ -15,7 +15,7 @@ set(
|
|||||||
SIMDJSON_EXCLUDE_IMPLEMENTATION ""
|
SIMDJSON_EXCLUDE_IMPLEMENTATION ""
|
||||||
CACHE STRING "\
|
CACHE STRING "\
|
||||||
Semicolon-separated list of implementations to exclude \
|
Semicolon-separated list of implementations to exclude \
|
||||||
(haswell/westmere/arm64/ppc64/fallback). By default, excludes any \
|
(icelake/haswell/westmere/arm64/ppc64/fallback). By default, excludes any \
|
||||||
implementations that are unsupported at compile time or cannot be selected at \
|
implementations that are unsupported at compile time or cannot be selected at \
|
||||||
runtime."
|
runtime."
|
||||||
)
|
)
|
||||||
|
|||||||
Vendored
+2
-1
@@ -13,8 +13,9 @@ cmake_dependent_option(SIMDJSON_GOOGLE_BENCHMARKS "compile the Google Benchmark
|
|||||||
if(SIMDJSON_GOOGLE_BENCHMARKS)
|
if(SIMDJSON_GOOGLE_BENCHMARKS)
|
||||||
set_off(BENCHMARK_ENABLE_TESTING)
|
set_off(BENCHMARK_ENABLE_TESTING)
|
||||||
set_off(BENCHMARK_ENABLE_INSTALL)
|
set_off(BENCHMARK_ENABLE_INSTALL)
|
||||||
|
set_off(BENCHMARK_ENABLE_WERROR)
|
||||||
|
|
||||||
import_dependency(google_benchmarks google/benchmark 8982e1e)
|
import_dependency(google_benchmarks google/benchmark f91b6b4)
|
||||||
add_dependency(google_benchmarks)
|
add_dependency(google_benchmarks)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|||||||
+775
-347
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,5 @@
|
|||||||
|
We take our documentation seriously. Please start reading the documentation before you attempt to use simdjson. We hope you will enjoy reading us.
|
||||||
|
|
||||||
* Basics: https://github.com/simdjson/simdjson/blob/master/doc/basics.md is an overview of how to use simdjson and its APIs.
|
* Basics: https://github.com/simdjson/simdjson/blob/master/doc/basics.md is an overview of how to use simdjson and its APIs.
|
||||||
* parse_many: https://github.com/simdjson/simdjson/blob/master/doc/parse_many.md describes an interface providing features to work with files or streams containing multiple small JSON documents. As fast and convenient as possible.
|
* parse_many: https://github.com/simdjson/simdjson/blob/master/doc/parse_many.md describes an interface providing features to work with files or streams containing multiple small JSON documents. As fast and convenient as possible.
|
||||||
* Performance: https://github.com/simdjson/simdjson/blob/master/doc/performance.md shows some more advanced scenarios and how to tune for them.
|
* Performance: https://github.com/simdjson/simdjson/blob/master/doc/performance.md shows some more advanced scenarios and how to tune for them.
|
||||||
|
|||||||
+15
-5
@@ -3,8 +3,8 @@ The Document-Object-Model (DOM) front-end
|
|||||||
|
|
||||||
An overview of what you need to know to use simdjson, with examples.
|
An overview of what you need to know to use simdjson, with examples.
|
||||||
|
|
||||||
* [DOM vs On Demand](#dom-vs-ondemand)
|
* [DOM vs On Demand](#dom-vs-on-demand)
|
||||||
* [The Basics: Loading and Parsing JSON Documents](#the-basics-loading-and-parsing-json-documents)
|
* [The Basics: Loading and Parsing JSON Documents](#the-basics-loading-and-parsing-json-documents-using-the-dom-front-end)
|
||||||
* [Using the Parsed JSON](#using-the-parsed-json)
|
* [Using the Parsed JSON](#using-the-parsed-json)
|
||||||
* [C++17 Support](#c17-support)
|
* [C++17 Support](#c17-support)
|
||||||
* [JSON Pointer](#json-pointer)
|
* [JSON Pointer](#json-pointer)
|
||||||
@@ -64,7 +64,7 @@ Once you have an element, you can navigate it with idiomatic C++ iterators, oper
|
|||||||
|
|
||||||
* **Extracting Values (with exceptions):** You can cast a JSON element to a native type: `double(element)` or
|
* **Extracting Values (with exceptions):** You can cast a JSON element to a native type: `double(element)` or
|
||||||
`double x = json_element`. This works for double, uint64_t, int64_t, bool,
|
`double x = json_element`. This works for double, uint64_t, int64_t, bool,
|
||||||
dom::object and dom::array. An exception is thrown if the cast is not possible.
|
dom::object and dom::array. An exception (`simdjson::simdjson_error`) is thrown if the cast is not possible.
|
||||||
* **Extracting Values (without exceptions):** You can use a variant usage of `get()` with error codes to avoid exceptions. You first declare the variable of the appropriate type (`double`, `uint64_t`, `int64_t`, `bool`,
|
* **Extracting Values (without exceptions):** You can use a variant usage of `get()` with error codes to avoid exceptions. You first declare the variable of the appropriate type (`double`, `uint64_t`, `int64_t`, `bool`,
|
||||||
`dom::object` and `dom::array`) and pass it by reference to `get()` which gives you back an error code: e.g.,
|
`dom::object` and `dom::array`) and pass it by reference to `get()` which gives you back an error code: e.g.,
|
||||||
```c++
|
```c++
|
||||||
@@ -81,7 +81,7 @@ Once you have an element, you can navigate it with idiomatic C++ iterators, oper
|
|||||||
know the type of the value, you can cast it right there, too! `for (double value : array) { ... }`
|
know the type of the value, you can cast it right there, too! `for (double value : array) { ... }`
|
||||||
* **Object Iteration:** You can iterate through an object's fields, too: `for (auto [key, value] : object)`
|
* **Object Iteration:** You can iterate through an object's fields, too: `for (auto [key, value] : object)`
|
||||||
* **Array Index:** To get at an array value by index, use the at() method: `array.at(0)` gets the
|
* **Array Index:** To get at an array value by index, use the at() method: `array.at(0)` gets the
|
||||||
first element.
|
first element. The at() method has linear-time complexity so it should not be used to iterate over the values of an array.
|
||||||
> Note that array[0] does not compile, because implementing [] gives the impression indexing is a
|
> Note that array[0] does not compile, because implementing [] gives the impression indexing is a
|
||||||
> O(1) operation, which it is not presently in simdjson. Instead, you should iterate over the elements
|
> O(1) operation, which it is not presently in simdjson. Instead, you should iterate over the elements
|
||||||
> using a for-loop, as in our examples.
|
> using a for-loop, as in our examples.
|
||||||
@@ -249,7 +249,11 @@ auto error = parser.parse(json).get(doc);
|
|||||||
if (error) { cerr << error << endl; exit(1); }
|
if (error) { cerr << error << endl; exit(1); }
|
||||||
```
|
```
|
||||||
|
|
||||||
When you use the code this way, it is your responsibility to check for error before using the
|
When there is no error, the error code simdjson::SUCCESS is returned: it evaluates as false as a Boolean.
|
||||||
|
We have several error codes to indicate errors, they all evaluate to true as a Boolean: your software should not generally not depend on exact
|
||||||
|
error codes. We may change the error codes in future releases and the exact error codes could vary depending on your system.
|
||||||
|
|
||||||
|
When you use the code without exceptions, it is your responsibility to check for error before using the
|
||||||
result: if there is an error, the result value will not be valid and using it will caused undefined
|
result: if there is an error, the result value will not be valid and using it will caused undefined
|
||||||
behavior.
|
behavior.
|
||||||
|
|
||||||
@@ -274,6 +278,7 @@ Our program loads the file, selects value corresponding to key "search_metadata"
|
|||||||
it selects the key "count" within that object.
|
it selects the key "count" within that object.
|
||||||
|
|
||||||
```C++
|
```C++
|
||||||
|
#include <iostream>
|
||||||
#include "simdjson.h"
|
#include "simdjson.h"
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
@@ -301,6 +306,7 @@ triggering exceptions. To do this, we use `["statuses"].at(0)["id"]`. We break t
|
|||||||
Observe how we use the `at` method when querying an index into an array, and not the bracket operator.
|
Observe how we use the `at` method when querying an index into an array, and not the bracket operator.
|
||||||
|
|
||||||
```C++
|
```C++
|
||||||
|
#include <iostream>
|
||||||
#include "simdjson.h"
|
#include "simdjson.h"
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
@@ -316,6 +322,9 @@ int main(void) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
The `at()` method has linear-time complexity: it should not be used to iterate
|
||||||
|
over the content of an array.
|
||||||
|
|
||||||
### Error Handling Example
|
### Error Handling Example
|
||||||
|
|
||||||
This is how the example in "Using the Parsed JSON" could be written using only error code checking:
|
This is how the example in "Using the Parsed JSON" could be written using only error code checking:
|
||||||
@@ -457,6 +466,7 @@ program from continuing if there was an error.
|
|||||||
If one is willing to trigger exceptions, it is possible to write simpler code:
|
If one is willing to trigger exceptions, it is possible to write simpler code:
|
||||||
|
|
||||||
```C++
|
```C++
|
||||||
|
#include <iostream>
|
||||||
#include "simdjson.h"
|
#include "simdjson.h"
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
|
|||||||
@@ -50,9 +50,9 @@ Inspecting the Detected Implementation
|
|||||||
You can check what implementation is running with `active_implementation`:
|
You can check what implementation is running with `active_implementation`:
|
||||||
|
|
||||||
```c++
|
```c++
|
||||||
cout << "simdjson v" << STRINGIFY(SIMDJSON_VERSION) << endl;
|
cout << "simdjson v" << SIMDJSON_STRINGIFY(SIMDJSON_VERSION) << endl;
|
||||||
cout << "Detected the best implementation for your machine: " << simdjson::active_implementation->name();
|
cout << "Detected the best implementation for your machine: " << simdjson::get_active_implementation()->name();
|
||||||
cout << "(" << simdjson::active_implementation->description() << ")" << endl;
|
cout << "(" << simdjson::get_active_implementation()->description() << ")" << endl;
|
||||||
```
|
```
|
||||||
|
|
||||||
Implementation detection will happen in this case when you first call `name()`.
|
Implementation detection will happen in this case when you first call `name()`.
|
||||||
@@ -63,7 +63,7 @@ Querying Available Implementations
|
|||||||
You can list all available implementations, regardless of which one was selected:
|
You can list all available implementations, regardless of which one was selected:
|
||||||
|
|
||||||
```c++
|
```c++
|
||||||
for (auto implementation : simdjson::available_implementations) {
|
for (auto implementation : simdjson::get_available_implementations()) {
|
||||||
cout << implementation->name() << ": " << implementation->description() << endl;
|
cout << implementation->name() << ": " << implementation->description() << endl;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -71,10 +71,10 @@ for (auto implementation : simdjson::available_implementations) {
|
|||||||
And look them up by name:
|
And look them up by name:
|
||||||
|
|
||||||
```c++
|
```c++
|
||||||
cout << simdjson::available_implementations["fallback"]->description() << endl;
|
cout << simdjson::get_available_implementations()["fallback"]->description() << endl;
|
||||||
```
|
```
|
||||||
Though the fallback implementation should always be available, others might be missing. When
|
Though the fallback implementation should always be available, others might be missing. When
|
||||||
an implementation is not available, the bracket call `simdjson::available_implementations[name]`
|
an implementation is not available, the bracket call `simdjson::get_available_implementations()[name]`
|
||||||
will return the null pointer.
|
will return the null pointer.
|
||||||
|
|
||||||
The available implementations have been compiled but may not necessarily be run safely on your system
|
The available implementations have been compiled but may not necessarily be run safely on your system
|
||||||
@@ -90,18 +90,18 @@ can select the CPU architecture yourself:
|
|||||||
|
|
||||||
```c++
|
```c++
|
||||||
// Use the fallback implementation, even though my machine is fast enough for anything
|
// Use the fallback implementation, even though my machine is fast enough for anything
|
||||||
simdjson::active_implementation = simdjson::available_implementations["fallback"];
|
simdjson::get_active_implementation() = simdjson::get_available_implementations()["fallback"];
|
||||||
```
|
```
|
||||||
|
|
||||||
You are responsible for ensuring that the requirements of the selected implementation match your current system.
|
You are responsible for ensuring that the requirements of the selected implementation match your current system.
|
||||||
Furthermore, you should check that the implementation is available before setting it to `simdjson::active_implementation`
|
Furthermore, you should check that the implementation is available before setting it to `simdjson::get_active_implementation()`
|
||||||
by comparing it with the null pointer.
|
by comparing it with the null pointer.
|
||||||
|
|
||||||
```c++
|
```c++
|
||||||
auto my_implementation = simdjson::available_implementations["haswell"];
|
auto my_implementation = simdjson::get_available_implementations()["haswell"];
|
||||||
if(! my_implementation) { exit(1); }
|
if(! my_implementation) { exit(1); }
|
||||||
if(! my_implementation->supported_by_runtime_system()) { exit(1); }
|
if(! my_implementation->supported_by_runtime_system()) { exit(1); }
|
||||||
simdjson::active_implementation = my_implementation;
|
simdjson::get_active_implementation() = my_implementation;
|
||||||
```
|
```
|
||||||
|
|
||||||
Checking that an Implementation can Run on your System
|
Checking that an Implementation can Run on your System
|
||||||
@@ -110,12 +110,12 @@ Checking that an Implementation can Run on your System
|
|||||||
You should call `supported_by_runtime_system()` to compare the processor's features with the need of the implementation.
|
You should call `supported_by_runtime_system()` to compare the processor's features with the need of the implementation.
|
||||||
|
|
||||||
```c++
|
```c++
|
||||||
for (auto implementation : simdjson::available_implementations) {
|
for (auto implementation : simdjson::get_available_implementations()) {
|
||||||
if(implementation->supported_by_runtime_system()) {
|
if(implementation->supported_by_runtime_system()) {
|
||||||
cout << implementation->name() << ": " << implementation->description() << endl;
|
cout << implementation->name() << ": " << implementation->description() << endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The call to `supported_by_runtime_system()` maybe relatively expensive. Do not call `supported_by_runtime_system()` each
|
The call to `supported_by_runtime_system()` may be relatively expensive. Do not call `supported_by_runtime_system()` each
|
||||||
time you parse a JSON input (for example). It is meant to be called a handful of times at most in the life of a program.
|
time you parse a JSON input (for example). It is meant to be called a handful of times at most in the life of a program.
|
||||||
+14
-4
@@ -1,8 +1,16 @@
|
|||||||
iterate_many
|
iterate_many
|
||||||
==========
|
==========
|
||||||
|
|
||||||
An interface providing features to work with files or streams containing multiple small JSON documents.
|
When serializing large databases, it is often better to write out many independent JSON
|
||||||
As fast and convenient as possible.
|
documents, instead of one large monolithic document containing many records. The simdjson
|
||||||
|
library provides high-speed access to files or streams containing multiple small JSON documents separated by ASCII white-space characters. Given an input such as
|
||||||
|
```JSON
|
||||||
|
{"text":"a"}
|
||||||
|
{"text":"b"}
|
||||||
|
{"text":"c"}
|
||||||
|
...
|
||||||
|
```
|
||||||
|
... you want to read the entries (individual JSON documents) as quickly and as conveniently as possible. Importantly, the input might span several gigabytes, but you want to use a small (fixed) amount of memory. Ideally, you'd also like the parallelize the processing (using more than one core) to speed up the process.
|
||||||
|
|
||||||
Contents
|
Contents
|
||||||
--------
|
--------
|
||||||
@@ -108,7 +116,9 @@ Whitespace Characters:
|
|||||||
- **Linefeed**
|
- **Linefeed**
|
||||||
- **Carriage return**
|
- **Carriage return**
|
||||||
- **Horizontal tab**
|
- **Horizontal tab**
|
||||||
- **Nothing**
|
|
||||||
|
If your documents are all objects or arrays, then you may even have nothing between them.
|
||||||
|
E.g., `[1,2]{"32":1}` is recognized as two documents.
|
||||||
|
|
||||||
Some official formats **(non-exhaustive list)**:
|
Some official formats **(non-exhaustive list)**:
|
||||||
- [Newline-Delimited JSON (NDJSON)](http://ndjson.org/)
|
- [Newline-Delimited JSON (NDJSON)](http://ndjson.org/)
|
||||||
@@ -175,7 +185,7 @@ Let us illustrate the idea with code:
|
|||||||
auto i = stream.begin();
|
auto i = stream.begin();
|
||||||
size_t count{0};
|
size_t count{0};
|
||||||
for(; i != stream.end(); ++i) {
|
for(; i != stream.end(); ++i) {
|
||||||
auto & doc = *i;
|
auto doc = *i;
|
||||||
if(!i.error()) {
|
if(!i.error()) {
|
||||||
std::cout << "got full document at " << i.current_index() << std::endl;
|
std::cout << "got full document at " << i.current_index() << std::endl;
|
||||||
std::cout << i.source() << std::endl;
|
std::cout << i.source() << std::endl;
|
||||||
|
|||||||
@@ -709,42 +709,6 @@ in production systems:
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### Long-Running Processes and Memory Capacity
|
|
||||||
|
|
||||||
The On Demand approach also automatically expands its memory capacity when larger documents are parsed. However, for longer processes where very large files are processed (such as server loops), this capacity is not resized down. Similarly to the DOM-based approach (see [here](https://github.com/simdjson/simdjson/blob/master/doc/dom.md#server-loops-long-running-processes-and-memory-capacity)]), On Demand also lets you adjust the maximal capacity that the parser can process:
|
|
||||||
|
|
||||||
* You can set an upper bound (*max_capacity*) when construction the parser:
|
|
||||||
```C++
|
|
||||||
ondemand::parser parser(1000*1000); // Never grows past documents > 1 MB
|
|
||||||
auto doc = parser.iterate(json);
|
|
||||||
for (web_request request : listen()) {
|
|
||||||
padded_string json;
|
|
||||||
padded_string json = padded_string::load(request.body);
|
|
||||||
auto error = parser.iterate(json);
|
|
||||||
// If the document was above our limit, emit 413 = payload too large
|
|
||||||
if (error == CAPACITY) { request.respond(413); continue; }
|
|
||||||
// ...
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
The capacity will grow as the parser encounters larger documents up to 1 MB.
|
|
||||||
|
|
||||||
* You can also allocate a *fixed capacity* that will never grow:
|
|
||||||
```C++
|
|
||||||
ondemand::parser parser(1000*1000);
|
|
||||||
parser.allocate(1000*1000) // Fix the capacity to 1 MB
|
|
||||||
auto doc = parser.iterate(json);
|
|
||||||
for (web_request request : listen()) {
|
|
||||||
padded_string json;
|
|
||||||
padded_string json = padded_string::load(request.body);
|
|
||||||
auto error = parser.iterate(json);
|
|
||||||
// If the document was above our limit, emit 413 = payload too large
|
|
||||||
if (error == CAPACITY) { request.respond(413); continue; }
|
|
||||||
// ...
|
|
||||||
}
|
|
||||||
```
|
|
||||||
You can also manually set the maximal capacity using the method `set_max_capacity()`.
|
|
||||||
### Benefits of the On Demand Approach
|
### Benefits of the On Demand Approach
|
||||||
|
|
||||||
We expect that the On Demand approach has many of the performance benefits of the schema-based approach, while providing a flexibility that is similar to that of the DOM-based approach.
|
We expect that the On Demand approach has many of the performance benefits of the schema-based approach, while providing a flexibility that is similar to that of the DOM-based approach.
|
||||||
@@ -764,7 +728,6 @@ There are currently additional technical limitations which we expect to resolve
|
|||||||
|
|
||||||
* The simdjson library offers runtime dispatching which allows you to compile one binary and have it run at full speed on different processors, taking advantage of the specific features of the processor. The On Demand API has limited runtime dispatch support. Under x64 systems, to fully benefit from the On Demand API, we recommend that you compile your code for a specific processor. E.g., if your processor supports AVX2 instructions, you should compile your binary executable with AVX2 instruction support (by using your compiler's commands). If you are sufficiently technically proficient, you can implement runtime dispatching within your application, by compiling your On Demand code for different processors.
|
* The simdjson library offers runtime dispatching which allows you to compile one binary and have it run at full speed on different processors, taking advantage of the specific features of the processor. The On Demand API has limited runtime dispatch support. Under x64 systems, to fully benefit from the On Demand API, we recommend that you compile your code for a specific processor. E.g., if your processor supports AVX2 instructions, you should compile your binary executable with AVX2 instruction support (by using your compiler's commands). If you are sufficiently technically proficient, you can implement runtime dispatching within your application, by compiling your On Demand code for different processors.
|
||||||
* There is an initial phase which scans the entire document quickly, irrespective of the size of the document. We plan to break this phase into distinct steps for large files in a future release as we have done with other components of our API (e.g., `parse_many`).
|
* There is an initial phase which scans the entire document quickly, irrespective of the size of the document. We plan to break this phase into distinct steps for large files in a future release as we have done with other components of our API (e.g., `parse_many`).
|
||||||
* The On Demand API does not support JSON Pointer. This capability is currently limited to our core API.
|
|
||||||
|
|
||||||
### Applicability of the On Demand Approach
|
### Applicability of the On Demand Approach
|
||||||
|
|
||||||
|
|||||||
+8
-2
@@ -1,8 +1,14 @@
|
|||||||
parse_many
|
parse_many
|
||||||
==========
|
==========
|
||||||
|
|
||||||
An interface providing features to work with files or streams containing multiple small JSON documents.
|
An interface providing features to work with files or streams containing multiple small JSON documents. Given an input such as
|
||||||
As fast and convenient as possible.
|
```JSON
|
||||||
|
{"text":"a"}
|
||||||
|
{"text":"b"}
|
||||||
|
{"text":"c"}
|
||||||
|
...
|
||||||
|
```
|
||||||
|
... you want to read the entries (individual JSON documents) as quickly and as conveniently as possible. Importantly, the input might span several gigabytes, but you want to use a small (fixed) amount of memory. Ideally, you'd also like the parallelize the processing (using more than one core) to speed up the process.
|
||||||
|
|
||||||
Contents
|
Contents
|
||||||
--------
|
--------
|
||||||
|
|||||||
+44
-9
@@ -10,7 +10,7 @@ are still some scenarios where tuning can enhance performance.
|
|||||||
* [Large files and huge page support](#large-files-and-huge-page-support)
|
* [Large files and huge page support](#large-files-and-huge-page-support)
|
||||||
* [Number parsing](#number-parsing)
|
* [Number parsing](#number-parsing)
|
||||||
* [Visual Studio](#visual-studio)
|
* [Visual Studio](#visual-studio)
|
||||||
* [Downclocking](#downclocking)
|
* [Power Usage and Downclocking](#power-usage-and-downclocking)
|
||||||
|
|
||||||
Reusing the parser for maximum efficiency
|
Reusing the parser for maximum efficiency
|
||||||
-----------------------------------------
|
-----------------------------------------
|
||||||
@@ -56,6 +56,43 @@ or simply
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Server Loops: Long-Running Processes and Memory Capacity
|
||||||
|
---------------------------------
|
||||||
|
|
||||||
|
The On Demand approach also automatically expands its memory capacity when larger documents are parsed. However, for longer processes where very large files are processed (such as server loops), this capacity is not resized down. On Demand also lets you adjust the maximal capacity that the parser can process:
|
||||||
|
|
||||||
|
* You can set an upper bound (*max_capacity*) when construction the parser:
|
||||||
|
```C++
|
||||||
|
ondemand::parser parser(1000*1000); // Never grows past documents > 1 MB
|
||||||
|
auto doc = parser.iterate(json);
|
||||||
|
for (web_request request : listen()) {
|
||||||
|
padded_string json;
|
||||||
|
padded_string json = padded_string::load(request.body);
|
||||||
|
auto error = parser.iterate(json);
|
||||||
|
// If the document was above our limit, emit 413 = payload too large
|
||||||
|
if (error == CAPACITY) { request.respond(413); continue; }
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The capacity will grow as the parser encounters larger documents up to 1 MB.
|
||||||
|
|
||||||
|
* You can also allocate a *fixed capacity* that will never grow:
|
||||||
|
```C++
|
||||||
|
ondemand::parser parser(1000*1000);
|
||||||
|
parser.allocate(1000*1000) // Fix the capacity to 1 MB
|
||||||
|
auto doc = parser.iterate(json);
|
||||||
|
for (web_request request : listen()) {
|
||||||
|
padded_string json;
|
||||||
|
padded_string json = padded_string::load(request.body);
|
||||||
|
auto error = parser.iterate(json);
|
||||||
|
// If the document was above our limit, emit 413 = payload too large
|
||||||
|
if (error == CAPACITY) { request.respond(413); continue; }
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
You can also manually set the maximal capacity using the method `set_max_capacity()`.
|
||||||
|
|
||||||
Large files and huge page support
|
Large files and huge page support
|
||||||
---------------------------------
|
---------------------------------
|
||||||
|
|
||||||
@@ -110,23 +147,21 @@ Recent versions of Microsoft Visual Studio on Windows provides support for the L
|
|||||||
Under Windows, we also support the GNU GCC compiler via MSYS2. The performance of 64-bit MSYS2 under Windows excellent (on par with Linux).
|
Under Windows, we also support the GNU GCC compiler via MSYS2. The performance of 64-bit MSYS2 under Windows excellent (on par with Linux).
|
||||||
|
|
||||||
|
|
||||||
Downclocking
|
Power Usage and Downclocking
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
|
The simdjson library relies on SIMD instructions. SIMD instructions are the public transportation of computing. Instead of using 4 distinct instructions to add numbers, you can replace them with a single instruction that does the same work. Though the one instruction is slightly more expensive, the energy used per unit of work is much less with SIMD. If you can increase your speed using SIMD instructions (NEON, SSE, AVX), you should expect to reduce your power usage.
|
||||||
|
|
||||||
SIMD instructions are the public transportation of computing. Instead of using 4 distinct instructions to add numbers, you can replace them with a single instruction that does the same work. Though the one instruction is slightly more expensive, the energy used per unit of work is much less with SIMD. If you can increase your speed using SIMD instructions (NEON, SSE, AVX), you should expect to reduce your power usage.
|
|
||||||
|
|
||||||
The SIMD instructions that simdjson relies upon (SSE and AVX under x64, NEON under ARM, ALTIVEC under PPC) are routinely part of runtime libraries (e.g., [Go](https://golang.org/src/runtime/memmove_amd64.s), [Glibc](https://github.com/ihtsae/glibc/commit/5f3d0b78e011d2a72f9e88b0e9ef5bc081d18f97), [LLVM](https://github.com/llvm/llvm-project/blob/96f3ea0d21b48ca088355db10d4d1a2e9bc9f884/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp), [Rust](https://github.com/rust-lang/rust/commit/070fad1701fb36b112853b0a6a9787a7bb7ff34c), [Java](http://hg.openjdk.java.net/jdk8u/jdk8u/hotspot/file/c1374141598c/src/cpu/x86/vm/stubGenerator_x86_64.cpp#l1297), [PHP](https://github.com/php/php-src/blob/e5cb53ec68603d4dbdd780fd3ecfca943b4fd383/ext/standard/string.c)). What distinguishes the simdjson library is that it is built from the ground up to benefit from these instructions.
|
The SIMD instructions that simdjson relies upon (SSE and AVX under x64, NEON under ARM, ALTIVEC under PPC) are routinely part of runtime libraries (e.g., [Go](https://golang.org/src/runtime/memmove_amd64.s), [Glibc](https://github.com/ihtsae/glibc/commit/5f3d0b78e011d2a72f9e88b0e9ef5bc081d18f97), [LLVM](https://github.com/llvm/llvm-project/blob/96f3ea0d21b48ca088355db10d4d1a2e9bc9f884/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp), [Rust](https://github.com/rust-lang/rust/commit/070fad1701fb36b112853b0a6a9787a7bb7ff34c), [Java](http://hg.openjdk.java.net/jdk8u/jdk8u/hotspot/file/c1374141598c/src/cpu/x86/vm/stubGenerator_x86_64.cpp#l1297), [PHP](https://github.com/php/php-src/blob/e5cb53ec68603d4dbdd780fd3ecfca943b4fd383/ext/standard/string.c)). What distinguishes the simdjson library is that it is built from the ground up to benefit from these instructions.
|
||||||
|
|
||||||
|
|
||||||
You should not expect the simdjson library to cause *downclocking* of your recent Intel CPU cores.
|
You should not expect the simdjson library to cause *downclocking* of your recent Intel CPU cores. On some Intel processors, using SIMD instructions in a sustained manner on the same CPU core may result in a phenomenon called downclocking whereas the processor initially runs these instructions at a slow speed before reducing the frequency of the core for a short time (milliseconds). Intel refers to these states as licenses. On some current Intel processors, it occurs under two scenarios:
|
||||||
|
|
||||||
On some Intel processors, using SIMD instructions in a sustained manner on the same CPU core may result in a phenomenon called downclocking whereas the processor initially runs these instructions at a slow speed before reducing the frequency of the core for a short time (milliseconds). Intel refers to these states as licenses. On some current Intel processors, it occurs under two scenarios:
|
|
||||||
|
|
||||||
- [Whenever 512-bit AVX-512 instructions are used](https://lemire.me/blog/2018/09/07/avx-512-when-and-how-to-use-these-new-instructions/).
|
- [Whenever 512-bit AVX-512 instructions are used](https://lemire.me/blog/2018/09/07/avx-512-when-and-how-to-use-these-new-instructions/).
|
||||||
- Whenever heavy 256-bit or wider instructions are used. Heavy instructions are those involving floating point operations or integer multiplications (since these execute on the floating point unit).
|
- Whenever heavy 256-bit or wider instructions are used. Heavy instructions are those involving floating point operations or integer multiplications (since these execute on the floating point unit).
|
||||||
|
|
||||||
The simdjson library does not currently support AVX-512 instructions and it does not make use of heavy 256-bit instructions. We do use vectorized multiplications, but only using 128-bit registers. Thus there should be no downclocking due to simdjson on recent processors.
|
The simdjson library does not make use of heavy 256-bit instructions. We do use vectorized multiplications, but only using 128-bit registers. Thus there should be no downclocking due to simdjson on recent processors, except when AVX-512 is allowed and
|
||||||
|
detected. However, we only allow AVX-512 on recent processors (Ice Lake/Tiger Lake or better) where [little to no frequency throttling is expected](https://travisdowns.github.io/blog/2020/08/19/icl-avx512-freq.html). If you can still concerned, you can easily disable AVX-512 with the CMake option `SIMDJSON_AVX512_ALLOWED` set to `OFF` (e.g., `cmake -D SIMDJSON_AVX512_ALLOWED=OFF -B build && cmake --build build`) or by setting
|
||||||
|
the macro `SIMDJSON_AVX512_ALLOWED` to `0` in C++ prior to importing the headers.
|
||||||
|
|
||||||
You may still be worried about which SIMD instruction set is used by simdjson. Thankfully, [you can always determine and change which architecture-specific implementation is used](implementation-selection.md) by simdjson. Thus even if your CPU supports AVX2, you do not need to use AVX2. You are in control.
|
You may still be worried about which SIMD instruction set is used by simdjson. Thankfully, [you can always determine and change which architecture-specific implementation is used](implementation-selection.md) by simdjson. Thus even if your CPU supports AVX2, you do not need to use AVX2. You are in control.
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
#include <iostream>
|
||||||
#include "simdjson.h"
|
#include "simdjson.h"
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
#include <iostream>
|
||||||
#include "simdjson.h"
|
#include "simdjson.h"
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
#include <iostream>
|
||||||
#include "simdjson.h"
|
#include "simdjson.h"
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
#include <iostream>
|
||||||
#include "simdjson.h"
|
#include "simdjson.h"
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
#include <iostream>
|
||||||
#include "simdjson.h"
|
#include "simdjson.h"
|
||||||
using namespace simdjson;
|
using namespace simdjson;
|
||||||
int main(void) {
|
int main(void) {
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
#include <iostream>
|
||||||
#include "simdjson.h"
|
#include "simdjson.h"
|
||||||
using namespace simdjson;
|
using namespace simdjson;
|
||||||
int main(void) {
|
int main(void) {
|
||||||
|
|||||||
+2
-2
@@ -18,7 +18,7 @@ The fuzzers are used in several ways.
|
|||||||
* oss-fuzz - heavy duty 24/7 fuzzing provided by the google driven oss-fuzz project
|
* oss-fuzz - heavy duty 24/7 fuzzing provided by the google driven oss-fuzz project
|
||||||
|
|
||||||
## Local fuzzing
|
## Local fuzzing
|
||||||
Just invoke fuzz/quick_check.sh, it will download the latest corpus from bintray (kept up to date by the CI fuzzers) and run the fuzzers for a short time. In case you want to run the fuzzers for longer, modify the timeout value in the script or invoke the fuzzer directly.
|
Just invoke fuzz/quick_check.sh, it will download the latest corpus (kept up to date by the CI fuzzers) and run the fuzzers for a short time. In case you want to run the fuzzers for longer, modify the timeout value in the script or invoke the fuzzer directly.
|
||||||
|
|
||||||
This requires linux with clang and cmake installed (recent Debian and Ubuntu are known to work fine).
|
This requires linux with clang and cmake installed (recent Debian and Ubuntu are known to work fine).
|
||||||
|
|
||||||
@@ -69,7 +69,7 @@ As little code as possible is kept at oss-fuzz since it is inconvenient to chang
|
|||||||
|
|
||||||
The simdjson library does not benefit from a corpus as much as other projects, because the library is very fast and explores the input space very well. With that said, it is still beneficial to have one. The CI job stores the corpus on a remote server between runs, and is available at [www.pauldreik.se](https://readonly:readonly@www.pauldreik.se/fuzzdata/index.php?project=simdjson).
|
The simdjson library does not benefit from a corpus as much as other projects, because the library is very fast and explores the input space very well. With that said, it is still beneficial to have one. The CI job stores the corpus on a remote server between runs, and is available at [www.pauldreik.se](https://readonly:readonly@www.pauldreik.se/fuzzdata/index.php?project=simdjson).
|
||||||
|
|
||||||
One can also grab the corpus as an artifact from the github actions job. Pick a run, then go to artifacts and download.
|
One can also grab the corpus as an artifact from the github actions job if you are logged in at github. Pick a run, then go to artifacts and download.
|
||||||
|
|
||||||
## Fuzzing coverage
|
## Fuzzing coverage
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include "supported_implementations.h"
|
#include "supported_implementations.h"
|
||||||
@@ -92,7 +93,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
|
|||||||
std::size_t nerrors=0;
|
std::size_t nerrors=0;
|
||||||
for(std::size_t i=0; i<Nimplementations; ++i) {
|
for(std::size_t i=0; i<Nimplementations; ++i) {
|
||||||
auto& e=implementations[i];
|
auto& e=implementations[i];
|
||||||
simdjson::active_implementation=e.impl;
|
simdjson::get_active_implementation()=e.impl;
|
||||||
e.error=e.parser.parse(Data,Size).get(e.element);
|
e.error=e.parser.parse(Data,Size).get(e.element);
|
||||||
if(e.error) {
|
if(e.error) {
|
||||||
++nerrors;
|
++nerrors;
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
#include "simdjson.h"
|
#include "simdjson.h"
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
#include <iostream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "supported_implementations.h"
|
#include "supported_implementations.h"
|
||||||
|
|
||||||
|
|||||||
+17
-15
@@ -8,24 +8,26 @@
|
|||||||
|
|
||||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
|
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
|
||||||
FuzzData fd(Data, Size);
|
FuzzData fd(Data, Size);
|
||||||
const auto batch_size=static_cast<size_t>(fd.getInt<0,1000>());
|
const auto batch_size = static_cast<size_t>(fd.getInt<0,1000>());
|
||||||
const auto json=simdjson::padded_string{fd.remainder_as_stringview()};
|
const auto json = simdjson::padded_string{fd.remainder_as_stringview()};
|
||||||
simdjson::dom::parser parser;
|
simdjson::dom::parser parser;
|
||||||
#if SIMDJSON_EXCEPTIONS
|
simdjson::dom::document_stream docs;
|
||||||
try {
|
if(parser.parse_many(json,batch_size).get(docs)) { return 0; }
|
||||||
#endif
|
size_t bool_count1 = 0;
|
||||||
simdjson::dom::document_stream docs;
|
size_t total_count1 = 0;
|
||||||
if(parser.parse_many(json,batch_size).get(docs)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t bool_count=0;
|
|
||||||
for (auto doc : docs) {
|
for (auto doc : docs) {
|
||||||
bool_count+=doc.is_bool();
|
total_count1++;
|
||||||
|
bool_count1 += doc.is_bool();
|
||||||
}
|
}
|
||||||
#if SIMDJSON_EXCEPTIONS
|
// Restart, if we made it this far, the document *must* be accessible.
|
||||||
} catch(...) {
|
if(parser.parse_many(json,batch_size).get(docs)) { return EXIT_FAILURE; }
|
||||||
|
size_t bool_count2 = 0;
|
||||||
|
size_t total_count2 = 0;
|
||||||
|
for (auto doc : docs) {
|
||||||
|
total_count2++;
|
||||||
|
bool_count2 += doc.is_bool();
|
||||||
}
|
}
|
||||||
#endif
|
// They should agree!!!
|
||||||
|
if((total_count2 != total_count1) || (bool_count2 != bool_count1)) { return EXIT_FAILURE; }
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
#include "simdjson.h"
|
#include "simdjson.h"
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
#include <iostream>
|
||||||
#include "supported_implementations.h"
|
#include "supported_implementations.h"
|
||||||
|
|
||||||
extern "C" int VerboseTestOneInput(const uint8_t *Data, size_t Size) {
|
extern "C" int VerboseTestOneInput(const uint8_t *Data, size_t Size) {
|
||||||
|
|||||||
+4
-5
@@ -4,7 +4,7 @@
|
|||||||
# good when working locally developing the fuzzers or making
|
# good when working locally developing the fuzzers or making
|
||||||
# sure code changes still pass the fuzzers.
|
# sure code changes still pass the fuzzers.
|
||||||
#
|
#
|
||||||
# It will download the corpus from bintray (kept up to date
|
# It will download the corpus from external store (kept up to date
|
||||||
# by the crontab github actions) unless a local out/ directory
|
# by the crontab github actions) unless a local out/ directory
|
||||||
# already exists.
|
# already exists.
|
||||||
#
|
#
|
||||||
@@ -23,10 +23,9 @@ done
|
|||||||
|
|
||||||
#download the corpus if it does not already exist
|
#download the corpus if it does not already exist
|
||||||
if [ ! -d out ] ; then
|
if [ ! -d out ] ; then
|
||||||
# ideally, we would download the github artifact but that requires being logged in which can not
|
# the corpus is also available for download from the artifacts page on https://github.com/simdjson/simdjson/actions/workflows/fuzzers.yml
|
||||||
# easily be fixed from this shell script.
|
# but that requires being logged in so can not be easily done from this script.
|
||||||
echo "NOTE! please go to the artifacts page on https://github.com/simdjson/simdjson/actions/workflows/fuzzers.yml and download the latest corpus.tar.zip artifact manually to speed up fuzzing"
|
wget -O - https://readonly:readonly@www.pauldreik.se/fuzzdata/index.php?project=simdjson |tar xzf -
|
||||||
sleep 5s
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# By default, use the debug friendly variant since this script is intended
|
# By default, use the debug friendly variant since this script is intended
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
std::vector<const simdjson::implementation*>
|
std::vector<const simdjson::implementation*>
|
||||||
get_runtime_supported_implementations() {
|
get_runtime_supported_implementations() {
|
||||||
std::vector<const simdjson::implementation*> ret;
|
std::vector<const simdjson::implementation*> ret;
|
||||||
for(auto& e: simdjson::available_implementations) {
|
for(auto& e: simdjson::get_available_implementations()) {
|
||||||
if(e->supported_by_runtime_system()) {
|
if(e->supported_by_runtime_system()) {
|
||||||
ret.emplace_back(e);
|
ret.emplace_back(e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,7 @@
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "simdjson/simdjson_version.h"
|
||||||
#include "simdjson/dom.h"
|
#include "simdjson/dom.h"
|
||||||
#include "simdjson/builtin.h"
|
#include "simdjson/builtin.h"
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ namespace {
|
|||||||
// We sometimes call trailing_zero on inputs that are zero,
|
// We sometimes call trailing_zero on inputs that are zero,
|
||||||
// but the algorithms do not end up using the returned value.
|
// but the algorithms do not end up using the returned value.
|
||||||
// Sadly, sanitizers are not smart enough to figure it out.
|
// Sadly, sanitizers are not smart enough to figure it out.
|
||||||
NO_SANITIZE_UNDEFINED
|
SIMDJSON_NO_SANITIZE_UNDEFINED
|
||||||
simdjson_really_inline int trailing_zeroes(uint64_t input_num) {
|
simdjson_really_inline int trailing_zeroes(uint64_t input_num) {
|
||||||
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
|
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||||
unsigned long ret;
|
unsigned long ret;
|
||||||
@@ -73,7 +73,7 @@ simdjson_really_inline uint64_t reverse_bits(uint64_t input_num) {
|
|||||||
* greating or equal to 63 in which case we trigger undefined behavior, but the output
|
* greating or equal to 63 in which case we trigger undefined behavior, but the output
|
||||||
* of such undefined behavior is never used.
|
* of such undefined behavior is never used.
|
||||||
**/
|
**/
|
||||||
NO_SANITIZE_UNDEFINED
|
SIMDJSON_NO_SANITIZE_UNDEFINED
|
||||||
simdjson_really_inline uint64_t zero_leading_bit(uint64_t rev_bits, int leading_zeroes) {
|
simdjson_really_inline uint64_t zero_leading_bit(uint64_t rev_bits, int leading_zeroes) {
|
||||||
return rev_bits ^ (uint64_t(0x8000000000000000) >> leading_zeroes);
|
return rev_bits ^ (uint64_t(0x8000000000000000) >> leading_zeroes);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ static simdjson_really_inline uint32_t parse_eight_digits_unrolled(const uint8_t
|
|||||||
} // namespace SIMDJSON_IMPLEMENTATION
|
} // namespace SIMDJSON_IMPLEMENTATION
|
||||||
} // namespace simdjson
|
} // namespace simdjson
|
||||||
|
|
||||||
#define SWAR_NUMBER_PARSING
|
#define SIMDJSON_SWAR_NUMBER_PARSING 1
|
||||||
|
|
||||||
#include "simdjson/generic/numberparsing.h"
|
#include "simdjson/generic/numberparsing.h"
|
||||||
|
|
||||||
|
|||||||
@@ -57,6 +57,19 @@ simdjson_really_inline uint8x16_t make_uint8x16_t(uint8_t x1, uint8_t x2, uint
|
|||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
simdjson_really_inline uint8x8_t make_uint8x8_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) {
|
||||||
|
uint8x8_t x{};
|
||||||
|
x = vset_lane_u8(x1, x, 0);
|
||||||
|
x = vset_lane_u8(x2, x, 1);
|
||||||
|
x = vset_lane_u8(x3, x, 2);
|
||||||
|
x = vset_lane_u8(x4, x, 3);
|
||||||
|
x = vset_lane_u8(x5, x, 4);
|
||||||
|
x = vset_lane_u8(x6, x, 5);
|
||||||
|
x = vset_lane_u8(x7, x, 6);
|
||||||
|
x = vset_lane_u8(x8, x, 7);
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
// We have to do the same work for make_int8x16_t
|
// We have to do the same work for make_int8x16_t
|
||||||
simdjson_really_inline int8x16_t make_int8x16_t(int8_t x1, int8_t x2, int8_t x3, int8_t x4,
|
simdjson_really_inline int8x16_t make_int8x16_t(int8_t x1, int8_t x2, int8_t x3, int8_t x4,
|
||||||
@@ -119,7 +132,7 @@ simdjson_really_inline int8x16_t make_int8x16_t(int8_t x1, int8_t x2, int8_t x
|
|||||||
simdjson_really_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_really_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_really_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_really_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_really_inline Mask operator==(const simd8<T> other) const { return vceqq_u8(*this, other); }
|
friend simdjson_really_inline Mask operator==(const simd8<T> lhs, const simd8<T> rhs) { return vceqq_u8(lhs, rhs); }
|
||||||
|
|
||||||
template<int N=1>
|
template<int N=1>
|
||||||
simdjson_really_inline simd8<T> prev(const simd8<T> prev_chunk) const {
|
simdjson_really_inline simd8<T> prev(const simd8<T> prev_chunk) const {
|
||||||
@@ -289,6 +302,27 @@ simdjson_really_inline int8x16_t make_int8x16_t(int8_t x1, int8_t x2, int8_t x
|
|||||||
vst1q_u8(reinterpret_cast<uint8_t*>(output), answer);
|
vst1q_u8(reinterpret_cast<uint8_t*>(output), answer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Copies all bytes corresponding to a 0 in the low half of the mask (interpreted as a
|
||||||
|
// bitset) to output1, then those corresponding to a 0 in the high half to output2.
|
||||||
|
template<typename L>
|
||||||
|
simdjson_really_inline void compress_halves(uint16_t mask, L *output1, L *output2) const {
|
||||||
|
using internal::thintable_epi8;
|
||||||
|
uint8_t mask1 = uint8_t(mask); // least significant 8 bits
|
||||||
|
uint8_t mask2 = uint8_t(mask >> 8); // most significant 8 bits
|
||||||
|
uint8x8_t compactmask1 = vcreate_u8(thintable_epi8[mask1]);
|
||||||
|
uint8x8_t compactmask2 = vcreate_u8(thintable_epi8[mask2]);
|
||||||
|
// we increment by 0x08 the second half of the mask
|
||||||
|
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||||
|
uint8x8_t inc = make_uint8x8_t(0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08);
|
||||||
|
#else
|
||||||
|
uint8x8_t inc = {0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08};
|
||||||
|
#endif
|
||||||
|
compactmask2 = vadd_u8(compactmask2, inc);
|
||||||
|
// store each result (with the second store possibly overlapping the first)
|
||||||
|
vst1_u8((uint8_t*)output1, vqtbl1_u8(*this, compactmask1));
|
||||||
|
vst1_u8((uint8_t*)output2, vqtbl1_u8(*this, compactmask2));
|
||||||
|
}
|
||||||
|
|
||||||
template<typename L>
|
template<typename L>
|
||||||
simdjson_really_inline simd8<L> lookup_16(
|
simdjson_really_inline simd8<L> lookup_16(
|
||||||
L replace0, L replace1, L replace2, L replace3,
|
L replace0, L replace1, L replace2, L replace3,
|
||||||
@@ -439,11 +473,15 @@ simdjson_really_inline int8x16_t make_int8x16_t(int8_t x1, int8_t x2, int8_t x
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
simdjson_really_inline void compress(uint64_t mask, T * output) const {
|
simdjson_really_inline uint64_t compress(uint64_t mask, T * output) const {
|
||||||
this->chunks[0].compress(uint16_t(mask), output);
|
uint64_t popcounts = vget_lane_u64(vreinterpret_u64_u8(vcnt_u8(vcreate_u8(~mask))), 0);
|
||||||
this->chunks[1].compress(uint16_t(mask >> 16), output + 16 - count_ones(mask & 0xFFFF));
|
// compute the prefix sum of the popcounts of each byte
|
||||||
this->chunks[2].compress(uint16_t(mask >> 32), output + 32 - count_ones(mask & 0xFFFFFFFF));
|
uint64_t offsets = popcounts * 0x0101010101010101;
|
||||||
this->chunks[3].compress(uint16_t(mask >> 48), output + 48 - count_ones(mask & 0xFFFFFFFFFFFF));
|
this->chunks[0].compress_halves(uint16_t(mask), output, &output[popcounts & 0xFF]);
|
||||||
|
this->chunks[1].compress_halves(uint16_t(mask >> 16), &output[(offsets >> 8) & 0xFF], &output[(offsets >> 16) & 0xFF]);
|
||||||
|
this->chunks[2].compress_halves(uint16_t(mask >> 32), &output[(offsets >> 24) & 0xFF], &output[(offsets >> 32) & 0xFF]);
|
||||||
|
this->chunks[3].compress_halves(uint16_t(mask >> 48), &output[(offsets >> 40) & 0xFF], &output[(offsets >> 48) & 0xFF]);
|
||||||
|
return offsets >> 56;
|
||||||
}
|
}
|
||||||
|
|
||||||
simdjson_really_inline uint64_t to_bitmask() const {
|
simdjson_really_inline uint64_t to_bitmask() const {
|
||||||
|
|||||||
@@ -5,7 +5,9 @@
|
|||||||
|
|
||||||
// Determine the best builtin implementation
|
// Determine the best builtin implementation
|
||||||
#ifndef SIMDJSON_BUILTIN_IMPLEMENTATION
|
#ifndef SIMDJSON_BUILTIN_IMPLEMENTATION
|
||||||
#if SIMDJSON_CAN_ALWAYS_RUN_HASWELL
|
#if SIMDJSON_CAN_ALWAYS_RUN_ICELAKE
|
||||||
|
#define SIMDJSON_BUILTIN_IMPLEMENTATION icelake
|
||||||
|
#elif SIMDJSON_CAN_ALWAYS_RUN_HASWELL
|
||||||
#define SIMDJSON_BUILTIN_IMPLEMENTATION haswell
|
#define SIMDJSON_BUILTIN_IMPLEMENTATION haswell
|
||||||
#elif SIMDJSON_CAN_ALWAYS_RUN_WESTMERE
|
#elif SIMDJSON_CAN_ALWAYS_RUN_WESTMERE
|
||||||
#define SIMDJSON_BUILTIN_IMPLEMENTATION westmere
|
#define SIMDJSON_BUILTIN_IMPLEMENTATION westmere
|
||||||
|
|||||||
@@ -122,6 +122,9 @@ constexpr size_t DEFAULT_MAX_DEPTH = 1024;
|
|||||||
|
|
||||||
#define SIMDJSON_PUSH_DISABLE_WARNINGS _Pragma("GCC diagnostic push")
|
#define SIMDJSON_PUSH_DISABLE_WARNINGS _Pragma("GCC diagnostic push")
|
||||||
// gcc doesn't seem to disable all warnings with all and extra, add warnings here as necessary
|
// gcc doesn't seem to disable all warnings with all and extra, add warnings here as necessary
|
||||||
|
// We do it separately for clang since it has different warnings.
|
||||||
|
#ifdef __clang__
|
||||||
|
// clang is missing -Wmaybe-uninitialized.
|
||||||
#define SIMDJSON_PUSH_DISABLE_ALL_WARNINGS SIMDJSON_PUSH_DISABLE_WARNINGS \
|
#define SIMDJSON_PUSH_DISABLE_ALL_WARNINGS SIMDJSON_PUSH_DISABLE_WARNINGS \
|
||||||
SIMDJSON_DISABLE_GCC_WARNING(-Weffc++) \
|
SIMDJSON_DISABLE_GCC_WARNING(-Weffc++) \
|
||||||
SIMDJSON_DISABLE_GCC_WARNING(-Wall) \
|
SIMDJSON_DISABLE_GCC_WARNING(-Wall) \
|
||||||
@@ -134,6 +137,22 @@ 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)
|
||||||
|
#else // __clang__
|
||||||
|
#define SIMDJSON_PUSH_DISABLE_ALL_WARNINGS SIMDJSON_PUSH_DISABLE_WARNINGS \
|
||||||
|
SIMDJSON_DISABLE_GCC_WARNING(-Weffc++) \
|
||||||
|
SIMDJSON_DISABLE_GCC_WARNING(-Wall) \
|
||||||
|
SIMDJSON_DISABLE_GCC_WARNING(-Wconversion) \
|
||||||
|
SIMDJSON_DISABLE_GCC_WARNING(-Wextra) \
|
||||||
|
SIMDJSON_DISABLE_GCC_WARNING(-Wattributes) \
|
||||||
|
SIMDJSON_DISABLE_GCC_WARNING(-Wimplicit-fallthrough) \
|
||||||
|
SIMDJSON_DISABLE_GCC_WARNING(-Wnon-virtual-dtor) \
|
||||||
|
SIMDJSON_DISABLE_GCC_WARNING(-Wreturn-type) \
|
||||||
|
SIMDJSON_DISABLE_GCC_WARNING(-Wshadow) \
|
||||||
|
SIMDJSON_DISABLE_GCC_WARNING(-Wunused-parameter) \
|
||||||
|
SIMDJSON_DISABLE_GCC_WARNING(-Wunused-variable) \
|
||||||
|
SIMDJSON_DISABLE_GCC_WARNING(-Wmaybe-uninitialized)
|
||||||
|
#endif // __clang__
|
||||||
|
|
||||||
#define SIMDJSON_PRAGMA(P) _Pragma(#P)
|
#define SIMDJSON_PRAGMA(P) _Pragma(#P)
|
||||||
#define SIMDJSON_DISABLE_GCC_WARNING(WARNING) SIMDJSON_PRAGMA(GCC diagnostic ignored #WARNING)
|
#define SIMDJSON_DISABLE_GCC_WARNING(WARNING) SIMDJSON_PRAGMA(GCC diagnostic ignored #WARNING)
|
||||||
#if defined(SIMDJSON_CLANG_VISUAL_STUDIO)
|
#if defined(SIMDJSON_CLANG_VISUAL_STUDIO)
|
||||||
@@ -253,11 +272,8 @@ namespace std {
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Feature flag for partially-implemented "don't require padding" feature
|
// The SIMDJSON_CHECK_EOF macro is a feature flag for the "don't require padding"
|
||||||
// TODO remove once feature complete.
|
// feature.
|
||||||
#ifndef __SIMDJSON_CHECK_EOF
|
|
||||||
# define __SIMDJSON_CHECK_EOF 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if SIMDJSON_CPLUSPLUS17
|
#if SIMDJSON_CPLUSPLUS17
|
||||||
// if we have C++, then fallthrough is a default attribute
|
// if we have C++, then fallthrough is a default attribute
|
||||||
@@ -268,11 +284,11 @@ namespace std {
|
|||||||
#if __has_attribute(__fallthrough__)
|
#if __has_attribute(__fallthrough__)
|
||||||
// we are good to go:
|
// we are good to go:
|
||||||
# define simdjson_fallthrough __attribute__((__fallthrough__))
|
# define simdjson_fallthrough __attribute__((__fallthrough__))
|
||||||
#endif
|
#endif // __has_attribute(__fallthrough__)
|
||||||
#endif
|
#endif // SIMDJSON_CPLUSPLUS17
|
||||||
// on some systems, we simply do not have support for fallthrough, so use a default:
|
// on some systems, we simply do not have support for fallthrough, so use a default:
|
||||||
#ifndef simdjson_fallthrough
|
#ifndef simdjson_fallthrough
|
||||||
# define simdjson_fallthrough do {} while (0) /* fallthrough */
|
# define simdjson_fallthrough do {} while (0) /* fallthrough */
|
||||||
#endif
|
#endif // simdjson_fallthrough
|
||||||
|
|
||||||
#endif // SIMDJSON_COMMON_DEFS_H
|
#endif // SIMDJSON_COMMON_DEFS_H
|
||||||
|
|||||||
@@ -256,6 +256,7 @@ inline size_t document_stream::size_in_bytes() const noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline size_t document_stream::truncated_bytes() const noexcept {
|
inline size_t document_stream::truncated_bytes() const noexcept {
|
||||||
|
if(error == CAPACITY) { return len - batch_start; }
|
||||||
return parser->implementation->structural_indexes[parser->implementation->n_structural_indexes] - parser->implementation->structural_indexes[parser->implementation->n_structural_indexes + 1];
|
return parser->implementation->structural_indexes[parser->implementation->n_structural_indexes] - parser->implementation->structural_indexes[parser->implementation->n_structural_indexes + 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <iostream>
|
#include <ostream>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|||||||
@@ -176,7 +176,7 @@ inline error_code parser::allocate(size_t capacity, size_t max_depth) noexcept {
|
|||||||
if (implementation) {
|
if (implementation) {
|
||||||
err = implementation->allocate(capacity, max_depth);
|
err = implementation->allocate(capacity, max_depth);
|
||||||
} else {
|
} else {
|
||||||
err = simdjson::active_implementation->create_dom_parser_implementation(capacity, max_depth, implementation);
|
err = simdjson::get_active_implementation()->create_dom_parser_implementation(capacity, max_depth, implementation);
|
||||||
}
|
}
|
||||||
if (err) { return err; }
|
if (err) { return err; }
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
|
|||||||
@@ -157,7 +157,10 @@ simdjson_really_inline void mini_formatter::string(std::string_view unescaped) {
|
|||||||
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.
|
||||||
// This should include most keys.
|
// This should include most keys.
|
||||||
constexpr static bool needs_escaping[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
//
|
||||||
|
// We would like to use 'bool' but some compilers take offense to bitwise operation
|
||||||
|
// with bool types.
|
||||||
|
constexpr static char needs_escaping[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
|
||||||
@@ -169,6 +172,8 @@ simdjson_really_inline void mini_formatter::string(std::string_view unescaped) {
|
|||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||||
for(;i + 8 <= unescaped.length(); i += 8) {
|
for(;i + 8 <= unescaped.length(); i += 8) {
|
||||||
// Poor's man vectorization. This could get much faster if we used SIMD.
|
// Poor's man vectorization. This could get much faster if we used SIMD.
|
||||||
|
//
|
||||||
|
// It is not the case that replacing '|' with '||' would be neutral performance-wise.
|
||||||
if(needs_escaping[uint8_t(unescaped[i])] | needs_escaping[uint8_t(unescaped[i+1])]
|
if(needs_escaping[uint8_t(unescaped[i])] | needs_escaping[uint8_t(unescaped[i+1])]
|
||||||
| needs_escaping[uint8_t(unescaped[i+2])] | needs_escaping[uint8_t(unescaped[i+3])]
|
| needs_escaping[uint8_t(unescaped[i+2])] | needs_escaping[uint8_t(unescaped[i+3])]
|
||||||
| needs_escaping[uint8_t(unescaped[i+4])] | needs_escaping[uint8_t(unescaped[i+5])]
|
| needs_escaping[uint8_t(unescaped[i+4])] | needs_escaping[uint8_t(unescaped[i+5])]
|
||||||
|
|||||||
@@ -7,7 +7,12 @@
|
|||||||
namespace simdjson {
|
namespace simdjson {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All possible errors returned by simdjson.
|
* All possible errors returned by simdjson. These error codes are subject to change
|
||||||
|
* and not all simdjson kernel returns the same error code given the same input: it is not
|
||||||
|
* well defined which error a given input should produce.
|
||||||
|
*
|
||||||
|
* Only SUCCESS evaluates to false as a Boolean. All other error codes will evaluate
|
||||||
|
* to true as a Boolean.
|
||||||
*/
|
*/
|
||||||
enum error_code {
|
enum error_code {
|
||||||
SUCCESS = 0, ///< No error
|
SUCCESS = 0, ///< No error
|
||||||
@@ -38,6 +43,8 @@ enum error_code {
|
|||||||
OUT_OF_ORDER_ITERATION, ///< tried to iterate an array or object out of order
|
OUT_OF_ORDER_ITERATION, ///< tried to iterate an array or object out of order
|
||||||
INSUFFICIENT_PADDING, ///< The JSON doesn't have enough padding for simdjson to safely parse it.
|
INSUFFICIENT_PADDING, ///< The JSON doesn't have enough padding for simdjson to safely parse it.
|
||||||
INCOMPLETE_ARRAY_OR_OBJECT, ///< The document ends early.
|
INCOMPLETE_ARRAY_OR_OBJECT, ///< The document ends early.
|
||||||
|
SCALAR_DOCUMENT_AS_VALUE, ///< A scalar document is treated as a value.
|
||||||
|
OUT_OF_BOUNDS, ///< Attempted to access location outside of document.
|
||||||
NUM_ERROR_CODES
|
NUM_ERROR_CODES
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -287,7 +294,7 @@ struct simdjson_result : public internal::simdjson_result_base<T> {
|
|||||||
#if SIMDJSON_EXCEPTIONS
|
#if SIMDJSON_EXCEPTIONS
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline std::ostream& operator<<(std::ostream& out, simdjson_result<T> value) noexcept { return out << value.value(); }
|
inline std::ostream& operator<<(std::ostream& out, simdjson_result<T> value) { return out << value.value(); }
|
||||||
#endif // SIMDJSON_EXCEPTIONS
|
#endif // SIMDJSON_EXCEPTIONS
|
||||||
|
|
||||||
#ifndef SIMDJSON_DISABLE_DEPRECATED_API
|
#ifndef SIMDJSON_DISABLE_DEPRECATED_API
|
||||||
|
|||||||
@@ -27,7 +27,8 @@ static simdjson_really_inline uint32_t parse_eight_digits_unrolled(const uint8_t
|
|||||||
} // namespace SIMDJSON_IMPLEMENTATION
|
} // namespace SIMDJSON_IMPLEMENTATION
|
||||||
} // namespace simdjson
|
} // namespace simdjson
|
||||||
|
|
||||||
#define SWAR_NUMBER_PARSING
|
#define SIMDJSON_SWAR_NUMBER_PARSING 1
|
||||||
|
|
||||||
#include "simdjson/generic/numberparsing.h"
|
#include "simdjson/generic/numberparsing.h"
|
||||||
|
|
||||||
#endif // SIMDJSON_FALLBACK_NUMBERPARSING_H
|
#endif // SIMDJSON_FALLBACK_NUMBERPARSING_H
|
||||||
|
|||||||
@@ -49,18 +49,23 @@ simdjson_really_inline implementation_simdjson_result_base<T>::operator T&&() &&
|
|||||||
return std::forward<implementation_simdjson_result_base<T>>(*this).take_value();
|
return std::forward<implementation_simdjson_result_base<T>>(*this).take_value();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // SIMDJSON_EXCEPTIONS
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
simdjson_really_inline const T& implementation_simdjson_result_base<T>::value_unsafe() const& noexcept {
|
simdjson_really_inline const T& implementation_simdjson_result_base<T>::value_unsafe() const& noexcept {
|
||||||
return this->first;
|
return this->first;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
simdjson_really_inline T& implementation_simdjson_result_base<T>::value_unsafe() & noexcept {
|
||||||
|
return this->first;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
simdjson_really_inline T&& implementation_simdjson_result_base<T>::value_unsafe() && noexcept {
|
simdjson_really_inline T&& implementation_simdjson_result_base<T>::value_unsafe() && noexcept {
|
||||||
return std::forward<T>(this->first);
|
return std::forward<T>(this->first);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // SIMDJSON_EXCEPTIONS
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
simdjson_really_inline implementation_simdjson_result_base<T>::implementation_simdjson_result_base(T &&value, error_code error) noexcept
|
simdjson_really_inline implementation_simdjson_result_base<T>::implementation_simdjson_result_base(T &&value, error_code error) noexcept
|
||||||
: first{std::forward<T>(value)}, second{error} {}
|
: first{std::forward<T>(value)}, second{error} {}
|
||||||
|
|||||||
@@ -97,22 +97,28 @@ struct implementation_simdjson_result_base {
|
|||||||
*/
|
*/
|
||||||
simdjson_really_inline operator T&&() && noexcept(false);
|
simdjson_really_inline operator T&&() && noexcept(false);
|
||||||
|
|
||||||
|
|
||||||
|
#endif // SIMDJSON_EXCEPTIONS
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the result value. This function is safe if and only
|
* Get the result value. This function is safe if and only
|
||||||
* the error() method returns a value that evaluates to false.
|
* the error() method returns a value that evaluates to false.
|
||||||
*/
|
*/
|
||||||
simdjson_really_inline const T& value_unsafe() const& noexcept;
|
simdjson_really_inline const T& value_unsafe() const& noexcept;
|
||||||
|
/**
|
||||||
|
* Get the result value. This function is safe if and only
|
||||||
|
* the error() method returns a value that evaluates to false.
|
||||||
|
*/
|
||||||
|
simdjson_really_inline T& value_unsafe() & noexcept;
|
||||||
/**
|
/**
|
||||||
* Take the result value (move it). This function is safe if and only
|
* Take the result value (move it). This function is safe if and only
|
||||||
* the error() method returns a value that evaluates to false.
|
* the error() method returns a value that evaluates to false.
|
||||||
*/
|
*/
|
||||||
simdjson_really_inline T&& value_unsafe() && noexcept;
|
simdjson_really_inline T&& value_unsafe() && noexcept;
|
||||||
|
protected:
|
||||||
#endif // SIMDJSON_EXCEPTIONS
|
/** users should never directly access first and second. **/
|
||||||
|
T first{}; /** Users should never directly access 'first'. **/
|
||||||
T first{};
|
error_code second{UNINITIALIZED}; /** Users should never directly access 'second'. **/
|
||||||
error_code second{UNINITIALIZED};
|
|
||||||
}; // struct implementation_simdjson_result_base
|
}; // struct implementation_simdjson_result_base
|
||||||
|
|
||||||
} // namespace SIMDJSON_IMPLEMENTATION
|
} // namespace SIMDJSON_IMPLEMENTATION
|
||||||
|
|||||||
@@ -3,6 +3,18 @@
|
|||||||
|
|
||||||
namespace simdjson {
|
namespace simdjson {
|
||||||
namespace SIMDJSON_IMPLEMENTATION {
|
namespace SIMDJSON_IMPLEMENTATION {
|
||||||
|
|
||||||
|
namespace ondemand {
|
||||||
|
/**
|
||||||
|
* 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 {
|
namespace {
|
||||||
/// @private
|
/// @private
|
||||||
namespace numberparsing {
|
namespace numberparsing {
|
||||||
@@ -349,7 +361,7 @@ error_code slow_float_parsing(simdjson_unused const uint8_t * src, W writer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename I>
|
template<typename I>
|
||||||
NO_SANITIZE_UNDEFINED // We deliberately allow overflow here and check later
|
SIMDJSON_NO_SANITIZE_UNDEFINED // We deliberately allow overflow here and check later
|
||||||
simdjson_really_inline bool parse_digit(const uint8_t c, I &i) {
|
simdjson_really_inline bool parse_digit(const uint8_t c, I &i) {
|
||||||
const uint8_t digit = static_cast<uint8_t>(c - '0');
|
const uint8_t digit = static_cast<uint8_t>(c - '0');
|
||||||
if (digit > 9) {
|
if (digit > 9) {
|
||||||
@@ -367,14 +379,16 @@ simdjson_really_inline error_code parse_decimal(simdjson_unused const uint8_t *c
|
|||||||
// the integer into a float in a lossless manner.
|
// the integer into a float in a lossless manner.
|
||||||
const uint8_t *const first_after_period = p;
|
const uint8_t *const first_after_period = p;
|
||||||
|
|
||||||
#ifdef SWAR_NUMBER_PARSING
|
#ifdef SIMDJSON_SWAR_NUMBER_PARSING
|
||||||
|
#if SIMDJSON_SWAR_NUMBER_PARSING
|
||||||
// this helps if we have lots of decimals!
|
// this helps if we have lots of decimals!
|
||||||
// this turns out to be frequent enough.
|
// this turns out to be frequent enough.
|
||||||
if (is_made_of_eight_digits_fast(p)) {
|
if (is_made_of_eight_digits_fast(p)) {
|
||||||
i = i * 100000000 + parse_eight_digits_unrolled(p);
|
i = i * 100000000 + parse_eight_digits_unrolled(p);
|
||||||
p += 8;
|
p += 8;
|
||||||
}
|
}
|
||||||
#endif
|
#endif // SIMDJSON_SWAR_NUMBER_PARSING
|
||||||
|
#endif // #ifdef SIMDJSON_SWAR_NUMBER_PARSING
|
||||||
// Unrolling the first digit makes a small difference on some implementations (e.g. westmere)
|
// Unrolling the first digit makes a small difference on some implementations (e.g. westmere)
|
||||||
if (parse_digit(*p, i)) { ++p; }
|
if (parse_digit(*p, i)) { ++p; }
|
||||||
while (parse_digit(*p, i)) { p++; }
|
while (parse_digit(*p, i)) { p++; }
|
||||||
@@ -441,9 +455,7 @@ simdjson_really_inline size_t significant_digits(const uint8_t * start_digits, s
|
|||||||
// It is possible that the integer had an overflow.
|
// It is possible that the integer had an overflow.
|
||||||
// We have to handle the case where we have 0.0000somenumber.
|
// We have to handle the case where we have 0.0000somenumber.
|
||||||
const uint8_t *start = start_digits;
|
const uint8_t *start = start_digits;
|
||||||
while ((*start == '0') || (*start == '.')) {
|
while ((*start == '0') || (*start == '.')) { ++start; }
|
||||||
start++;
|
|
||||||
}
|
|
||||||
// we over-decrement by one when there is a '.'
|
// we over-decrement by one when there is a '.'
|
||||||
return digit_count - size_t(start - start_digits);
|
return digit_count - size_t(start - start_digits);
|
||||||
}
|
}
|
||||||
@@ -513,7 +525,12 @@ simdjson_really_inline error_code parse_number(const uint8_t *const, W &writer)
|
|||||||
simdjson_unused simdjson_really_inline simdjson_result<uint64_t> parse_unsigned(const uint8_t * const src) noexcept { return 0; }
|
simdjson_unused simdjson_really_inline simdjson_result<uint64_t> parse_unsigned(const uint8_t * const src) noexcept { return 0; }
|
||||||
simdjson_unused simdjson_really_inline simdjson_result<int64_t> parse_integer(const uint8_t * const src) noexcept { return 0; }
|
simdjson_unused simdjson_really_inline simdjson_result<int64_t> parse_integer(const uint8_t * const src) noexcept { return 0; }
|
||||||
simdjson_unused simdjson_really_inline simdjson_result<double> parse_double(const uint8_t * const src) noexcept { return 0; }
|
simdjson_unused simdjson_really_inline simdjson_result<double> parse_double(const uint8_t * const src) noexcept { return 0; }
|
||||||
|
simdjson_unused simdjson_really_inline simdjson_result<uint64_t> parse_unsigned_in_string(const uint8_t * const src) noexcept { return 0; }
|
||||||
|
simdjson_unused simdjson_really_inline simdjson_result<int64_t> parse_integer_in_string(const uint8_t * const src) noexcept { return 0; }
|
||||||
|
simdjson_unused simdjson_really_inline simdjson_result<double> parse_double_in_string(const uint8_t * const src) noexcept { return 0; }
|
||||||
|
simdjson_unused simdjson_really_inline bool is_negative(const uint8_t * src) noexcept { return false; }
|
||||||
|
simdjson_unused simdjson_really_inline simdjson_result<bool> is_integer(const uint8_t * src) noexcept { return false; }
|
||||||
|
simdjson_unused simdjson_really_inline simdjson_result<ondemand::number_type> get_number_type(const uint8_t * src) noexcept { return ondemand::number_type::signed_integer; }
|
||||||
#else
|
#else
|
||||||
|
|
||||||
// parse the number at src
|
// parse the number at src
|
||||||
@@ -592,7 +609,7 @@ simdjson_really_inline error_code parse_number(const uint8_t *const src, W &writ
|
|||||||
// - That is smaller than the smallest possible 20-digit number the user could write:
|
// - That is smaller than the smallest possible 20-digit number the user could write:
|
||||||
// 10,000,000,000,000,000,000.
|
// 10,000,000,000,000,000,000.
|
||||||
// - Therefore, if the number is positive and lower than that, it's overflow.
|
// - Therefore, if the number is positive and lower than that, it's overflow.
|
||||||
// - The value we are looking at is less than or equal to 9,223,372,036,854,775,808 (INT64_MAX).
|
// - The value we are looking at is less than or equal to INT64_MAX.
|
||||||
//
|
//
|
||||||
} else if (src[0] != uint8_t('1') || i <= uint64_t(INT64_MAX)) { return INVALID_NUMBER(src); }
|
} else if (src[0] != uint8_t('1') || i <= uint64_t(INT64_MAX)) { return INVALID_NUMBER(src); }
|
||||||
}
|
}
|
||||||
@@ -715,7 +732,7 @@ simdjson_unused simdjson_really_inline simdjson_result<uint64_t> parse_unsigned(
|
|||||||
// - That is smaller than the smallest possible 20-digit number the user could write:
|
// - That is smaller than the smallest possible 20-digit number the user could write:
|
||||||
// 10,000,000,000,000,000,000.
|
// 10,000,000,000,000,000,000.
|
||||||
// - Therefore, if the number is positive and lower than that, it's overflow.
|
// - Therefore, if the number is positive and lower than that, it's overflow.
|
||||||
// - The value we are looking at is less than or equal to 9,223,372,036,854,775,808 (INT64_MAX).
|
// - The value we are looking at is less than or equal to INT64_MAX.
|
||||||
//
|
//
|
||||||
if (src[0] != uint8_t('1') || i <= uint64_t(INT64_MAX)) { return INCORRECT_TYPE; }
|
if (src[0] != uint8_t('1') || i <= uint64_t(INT64_MAX)) { return INCORRECT_TYPE; }
|
||||||
}
|
}
|
||||||
@@ -765,7 +782,7 @@ simdjson_unused simdjson_really_inline simdjson_result<uint64_t> parse_unsigned(
|
|||||||
// - That is smaller than the smallest possible 20-digit number the user could write:
|
// - That is smaller than the smallest possible 20-digit number the user could write:
|
||||||
// 10,000,000,000,000,000,000.
|
// 10,000,000,000,000,000,000.
|
||||||
// - Therefore, if the number is positive and lower than that, it's overflow.
|
// - Therefore, if the number is positive and lower than that, it's overflow.
|
||||||
// - The value we are looking at is less than or equal to 9,223,372,036,854,775,808 (INT64_MAX).
|
// - The value we are looking at is less than or equal to INT64_MAX.
|
||||||
//
|
//
|
||||||
if (src[0] != uint8_t('1') || i <= uint64_t(INT64_MAX)) { return INCORRECT_TYPE; }
|
if (src[0] != uint8_t('1') || i <= uint64_t(INT64_MAX)) { return INCORRECT_TYPE; }
|
||||||
}
|
}
|
||||||
@@ -773,6 +790,56 @@ simdjson_unused simdjson_really_inline simdjson_result<uint64_t> parse_unsigned(
|
|||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Parse any number from 0 to 18,446,744,073,709,551,615
|
||||||
|
simdjson_unused simdjson_really_inline simdjson_result<uint64_t> parse_unsigned_in_string(const uint8_t * const src) noexcept {
|
||||||
|
const uint8_t *p = src + 1;
|
||||||
|
//
|
||||||
|
// Parse the integer part.
|
||||||
|
//
|
||||||
|
// PERF NOTE: we don't use is_made_of_eight_digits_fast because large integers like 123456789 are rare
|
||||||
|
const uint8_t *const start_digits = p;
|
||||||
|
uint64_t i = 0;
|
||||||
|
while (parse_digit(*p, i)) { p++; }
|
||||||
|
|
||||||
|
// If there were no digits, or if the integer starts with 0 and has more than one digit, it's an error.
|
||||||
|
// Optimization note: size_t is expected to be unsigned.
|
||||||
|
size_t digit_count = size_t(p - start_digits);
|
||||||
|
// The longest positive 64-bit number is 20 digits.
|
||||||
|
// We do it this way so we don't trigger this branch unless we must.
|
||||||
|
// Optimization note: the compiler can probably merge
|
||||||
|
// ((digit_count == 0) || (digit_count > 20))
|
||||||
|
// into a single branch since digit_count is unsigned.
|
||||||
|
if ((digit_count == 0) || (digit_count > 20)) { return INCORRECT_TYPE; }
|
||||||
|
// Here digit_count > 0.
|
||||||
|
if (('0' == *start_digits) && (digit_count > 1)) { return NUMBER_ERROR; }
|
||||||
|
// We can do the following...
|
||||||
|
// if (!jsoncharutils::is_structural_or_whitespace(*p)) {
|
||||||
|
// return (*p == '.' || *p == 'e' || *p == 'E') ? INCORRECT_TYPE : NUMBER_ERROR;
|
||||||
|
// }
|
||||||
|
// as a single table lookup:
|
||||||
|
if (*p != '"') { return NUMBER_ERROR; }
|
||||||
|
|
||||||
|
if (digit_count == 20) {
|
||||||
|
// Positive overflow check:
|
||||||
|
// - A 20 digit number starting with 2-9 is overflow, because 18,446,744,073,709,551,615 is the
|
||||||
|
// biggest uint64_t.
|
||||||
|
// - A 20 digit number starting with 1 is overflow if it is less than INT64_MAX.
|
||||||
|
// If we got here, it's a 20 digit number starting with the digit "1".
|
||||||
|
// - If a 20 digit number starting with 1 overflowed (i*10+digit), the result will be smaller
|
||||||
|
// than 1,553,255,926,290,448,384.
|
||||||
|
// - That is smaller than the smallest possible 20-digit number the user could write:
|
||||||
|
// 10,000,000,000,000,000,000.
|
||||||
|
// - Therefore, if the number is positive and lower than that, it's overflow.
|
||||||
|
// - The value we are looking at is less than or equal to INT64_MAX.
|
||||||
|
//
|
||||||
|
// Note: we use src[1] and not src[0] because src[0] is the quote character in this
|
||||||
|
// instance.
|
||||||
|
if (src[1] != uint8_t('1') || i <= uint64_t(INT64_MAX)) { return INCORRECT_TYPE; }
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
// Parse any number from -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
|
// Parse any number from -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
|
||||||
simdjson_unused simdjson_really_inline simdjson_result<int64_t> parse_integer(const uint8_t *src) noexcept {
|
simdjson_unused simdjson_really_inline simdjson_result<int64_t> parse_integer(const uint8_t *src) noexcept {
|
||||||
//
|
//
|
||||||
@@ -859,6 +926,48 @@ simdjson_unused simdjson_really_inline simdjson_result<int64_t> parse_integer(co
|
|||||||
return negative ? (~i+1) : i;
|
return negative ? (~i+1) : i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Parse any number from -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
|
||||||
|
simdjson_unused simdjson_really_inline simdjson_result<int64_t> parse_integer_in_string(const uint8_t *src) noexcept {
|
||||||
|
//
|
||||||
|
// Check for minus sign
|
||||||
|
//
|
||||||
|
bool negative = (*(src + 1) == '-');
|
||||||
|
const uint8_t *p = src + negative + 1;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Parse the integer part.
|
||||||
|
//
|
||||||
|
// PERF NOTE: we don't use is_made_of_eight_digits_fast because large integers like 123456789 are rare
|
||||||
|
const uint8_t *const start_digits = p;
|
||||||
|
uint64_t i = 0;
|
||||||
|
while (parse_digit(*p, i)) { p++; }
|
||||||
|
|
||||||
|
// If there were no digits, or if the integer starts with 0 and has more than one digit, it's an error.
|
||||||
|
// Optimization note: size_t is expected to be unsigned.
|
||||||
|
size_t digit_count = size_t(p - start_digits);
|
||||||
|
// We go from
|
||||||
|
// -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
|
||||||
|
// so we can never represent numbers that have more than 19 digits.
|
||||||
|
size_t longest_digit_count = 19;
|
||||||
|
// Optimization note: the compiler can probably merge
|
||||||
|
// ((digit_count == 0) || (digit_count > longest_digit_count))
|
||||||
|
// into a single branch since digit_count is unsigned.
|
||||||
|
if ((digit_count == 0) || (digit_count > longest_digit_count)) { return INCORRECT_TYPE; }
|
||||||
|
// Here digit_count > 0.
|
||||||
|
if (('0' == *start_digits) && (digit_count > 1)) { return NUMBER_ERROR; }
|
||||||
|
// We can do the following...
|
||||||
|
// if (!jsoncharutils::is_structural_or_whitespace(*p)) {
|
||||||
|
// return (*p == '.' || *p == 'e' || *p == 'E') ? INCORRECT_TYPE : NUMBER_ERROR;
|
||||||
|
// }
|
||||||
|
// as a single table lookup:
|
||||||
|
if(*p != '"') { return NUMBER_ERROR; }
|
||||||
|
// Negative numbers have can go down to - INT64_MAX - 1 whereas positive numbers are limited to INT64_MAX.
|
||||||
|
// Performance note: This check is only needed when digit_count == longest_digit_count but it is
|
||||||
|
// so cheap that we might as well always make it.
|
||||||
|
if(i > uint64_t(INT64_MAX) + uint64_t(negative)) { return INCORRECT_TYPE; }
|
||||||
|
return negative ? (~i+1) : i;
|
||||||
|
}
|
||||||
|
|
||||||
simdjson_unused simdjson_really_inline simdjson_result<double> parse_double(const uint8_t * src) noexcept {
|
simdjson_unused simdjson_really_inline simdjson_result<double> parse_double(const uint8_t * src) noexcept {
|
||||||
//
|
//
|
||||||
// Check for minus sign
|
// Check for minus sign
|
||||||
@@ -937,6 +1046,44 @@ simdjson_unused simdjson_really_inline simdjson_result<double> parse_double(cons
|
|||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
simdjson_unused simdjson_really_inline bool is_negative(const uint8_t * src) noexcept {
|
||||||
|
return (*src == '-');
|
||||||
|
}
|
||||||
|
|
||||||
|
simdjson_unused simdjson_really_inline simdjson_result<bool> is_integer(const uint8_t * src) noexcept {
|
||||||
|
bool negative = (*src == '-');
|
||||||
|
src += negative;
|
||||||
|
const uint8_t *p = src;
|
||||||
|
while(static_cast<uint8_t>(*p - '0') <= 9) { p++; }
|
||||||
|
if ( p == src ) { return NUMBER_ERROR; }
|
||||||
|
if (jsoncharutils::is_structural_or_whitespace(*p)) { return true; }
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
simdjson_unused simdjson_really_inline simdjson_result<ondemand::number_type> get_number_type(const uint8_t * src) noexcept {
|
||||||
|
bool negative = (*src == '-');
|
||||||
|
src += negative;
|
||||||
|
const uint8_t *p = src;
|
||||||
|
while(static_cast<uint8_t>(*p - '0') <= 9) { p++; }
|
||||||
|
if ( p == src ) { return NUMBER_ERROR; }
|
||||||
|
if (jsoncharutils::is_structural_or_whitespace(*p)) {
|
||||||
|
// We have an integer.
|
||||||
|
// If the number is negative and valid, it must be a signed integer.
|
||||||
|
if(negative) { return ondemand::number_type::signed_integer; }
|
||||||
|
// We want values larger or equal to 9223372036854775808 to be unsigned
|
||||||
|
// integers, and the other values to be signed integers.
|
||||||
|
int digit_count = int(p - src);
|
||||||
|
if(digit_count >= 19) {
|
||||||
|
const uint8_t * smaller_big_integer = reinterpret_cast<const uint8_t *>("9223372036854775808");
|
||||||
|
if((digit_count >= 20) || (memcmp(src, smaller_big_integer, 19) >= 0)) {
|
||||||
|
return ondemand::number_type::unsigned_integer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ondemand::number_type::signed_integer;
|
||||||
|
}
|
||||||
|
// Hopefully, we have 'e' or 'E' or '.'.
|
||||||
|
return ondemand::number_type::floating_point_number;
|
||||||
|
}
|
||||||
|
|
||||||
// Never read at src_end or beyond
|
// Never read at src_end or beyond
|
||||||
simdjson_unused simdjson_really_inline simdjson_result<double> parse_double(const uint8_t * src, const uint8_t * const src_end) noexcept {
|
simdjson_unused simdjson_really_inline simdjson_result<double> parse_double(const uint8_t * src, const uint8_t * const src_end) noexcept {
|
||||||
@@ -1020,6 +1167,83 @@ simdjson_unused simdjson_really_inline simdjson_result<double> parse_double(cons
|
|||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
simdjson_unused simdjson_really_inline simdjson_result<double> parse_double_in_string(const uint8_t * src) noexcept {
|
||||||
|
//
|
||||||
|
// Check for minus sign
|
||||||
|
//
|
||||||
|
bool negative = (*(src + 1) == '-');
|
||||||
|
src += negative + 1;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Parse the integer part.
|
||||||
|
//
|
||||||
|
uint64_t i = 0;
|
||||||
|
const uint8_t *p = src;
|
||||||
|
p += parse_digit(*p, i);
|
||||||
|
bool leading_zero = (i == 0);
|
||||||
|
while (parse_digit(*p, i)) { p++; }
|
||||||
|
// no integer digits, or 0123 (zero must be solo)
|
||||||
|
if ( p == src ) { return INCORRECT_TYPE; }
|
||||||
|
if ( (leading_zero && p != src+1)) { return NUMBER_ERROR; }
|
||||||
|
|
||||||
|
//
|
||||||
|
// Parse the decimal part.
|
||||||
|
//
|
||||||
|
int64_t exponent = 0;
|
||||||
|
bool overflow;
|
||||||
|
if (simdjson_likely(*p == '.')) {
|
||||||
|
p++;
|
||||||
|
const uint8_t *start_decimal_digits = p;
|
||||||
|
if (!parse_digit(*p, i)) { return NUMBER_ERROR; } // no decimal digits
|
||||||
|
p++;
|
||||||
|
while (parse_digit(*p, i)) { p++; }
|
||||||
|
exponent = -(p - start_decimal_digits);
|
||||||
|
|
||||||
|
// Overflow check. More than 19 digits (minus the decimal) may be overflow.
|
||||||
|
overflow = p-src-1 > 19;
|
||||||
|
if (simdjson_unlikely(overflow && leading_zero)) {
|
||||||
|
// Skip leading 0.00000 and see if it still overflows
|
||||||
|
const uint8_t *start_digits = src + 2;
|
||||||
|
while (*start_digits == '0') { start_digits++; }
|
||||||
|
overflow = start_digits-src > 19;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
overflow = p-src > 19;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Parse the exponent
|
||||||
|
//
|
||||||
|
if (*p == 'e' || *p == 'E') {
|
||||||
|
p++;
|
||||||
|
bool exp_neg = *p == '-';
|
||||||
|
p += exp_neg || *p == '+';
|
||||||
|
|
||||||
|
uint64_t exp = 0;
|
||||||
|
const uint8_t *start_exp_digits = p;
|
||||||
|
while (parse_digit(*p, exp)) { p++; }
|
||||||
|
// no exp digits, or 20+ exp digits
|
||||||
|
if (p-start_exp_digits == 0 || p-start_exp_digits > 19) { return NUMBER_ERROR; }
|
||||||
|
|
||||||
|
exponent += exp_neg ? 0-exp : exp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*p != '"') { return NUMBER_ERROR; }
|
||||||
|
|
||||||
|
overflow = overflow || exponent < simdjson::internal::smallest_power || exponent > simdjson::internal::largest_power;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Assemble (or slow-parse) the float
|
||||||
|
//
|
||||||
|
double d;
|
||||||
|
if (simdjson_likely(!overflow)) {
|
||||||
|
if (compute_float_64(exponent, i, negative, d)) { return d; }
|
||||||
|
}
|
||||||
|
if (!parse_float_fallback(src-negative, &d)) {
|
||||||
|
return NUMBER_ERROR;
|
||||||
|
}
|
||||||
|
return d;
|
||||||
|
}
|
||||||
} //namespace {}
|
} //namespace {}
|
||||||
#endif // SIMDJSON_SKIPNUMBERPARSING
|
#endif // SIMDJSON_SKIPNUMBERPARSING
|
||||||
|
|
||||||
|
|||||||
@@ -82,10 +82,14 @@ simdjson_really_inline simdjson_result<std::string_view> array::raw_json() noexc
|
|||||||
const uint8_t * starting_point{iter.peek_start()};
|
const uint8_t * starting_point{iter.peek_start()};
|
||||||
auto error = consume();
|
auto error = consume();
|
||||||
if(error) { return error; }
|
if(error) { return error; }
|
||||||
const uint8_t * final_point{iter._json_iter->peek(0)};
|
// After 'consume()', we could be left pointing just beyond the document, but that
|
||||||
|
// is ok because we are not going to dereference the final pointer position, we just
|
||||||
|
// use it to compute the length in bytes.
|
||||||
|
const uint8_t * final_point{iter._json_iter->unsafe_pointer()};
|
||||||
return std::string_view(reinterpret_cast<const char*>(starting_point), size_t(final_point - starting_point));
|
return std::string_view(reinterpret_cast<const char*>(starting_point), size_t(final_point - starting_point));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING
|
||||||
simdjson_really_inline simdjson_result<size_t> array::count_elements() & noexcept {
|
simdjson_really_inline simdjson_result<size_t> array::count_elements() & noexcept {
|
||||||
size_t count{0};
|
size_t count{0};
|
||||||
// Important: we do not consume any of the values.
|
// Important: we do not consume any of the values.
|
||||||
@@ -98,6 +102,17 @@ simdjson_really_inline simdjson_result<size_t> array::count_elements() & noexcep
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
simdjson_really_inline simdjson_result<bool> array::is_empty() & noexcept {
|
||||||
|
bool is_not_empty;
|
||||||
|
auto error = iter.reset_array().get(is_not_empty);
|
||||||
|
if(error) { return error; }
|
||||||
|
return !is_not_empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline simdjson_result<bool> array::reset() & noexcept {
|
||||||
|
return iter.reset_array();
|
||||||
|
}
|
||||||
|
|
||||||
inline simdjson_result<value> array::at_pointer(std::string_view json_pointer) noexcept {
|
inline simdjson_result<value> array::at_pointer(std::string_view json_pointer) noexcept {
|
||||||
if (json_pointer[0] != '/') { return INVALID_JSON_POINTER; }
|
if (json_pointer[0] != '/') { return INVALID_JSON_POINTER; }
|
||||||
json_pointer = json_pointer.substr(1);
|
json_pointer = json_pointer.substr(1);
|
||||||
@@ -176,6 +191,10 @@ simdjson_really_inline simdjson_result<size_t> simdjson_result<SIMDJSON_IMPLEME
|
|||||||
if (error()) { return error(); }
|
if (error()) { return error(); }
|
||||||
return first.count_elements();
|
return first.count_elements();
|
||||||
}
|
}
|
||||||
|
simdjson_really_inline simdjson_result<bool> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array>::is_empty() & noexcept {
|
||||||
|
if (error()) { return error(); }
|
||||||
|
return first.is_empty();
|
||||||
|
}
|
||||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array>::at(size_t index) noexcept {
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array>::at(size_t index) noexcept {
|
||||||
if (error()) { return error(); }
|
if (error()) { return error(); }
|
||||||
return first.at(index);
|
return first.at(index);
|
||||||
|
|||||||
@@ -41,9 +41,32 @@ public:
|
|||||||
* beginning as if it had never been accessed. If the JSON is malformed (e.g.,
|
* beginning as if it had never been accessed. If the JSON is malformed (e.g.,
|
||||||
* there is a missing comma), then an error is returned and it is no longer
|
* there is a missing comma), then an error is returned and it is no longer
|
||||||
* safe to continue.
|
* safe to continue.
|
||||||
|
*
|
||||||
|
* To check that an array is empty, it is more performant to use
|
||||||
|
* the is_empty() method.
|
||||||
*/
|
*/
|
||||||
simdjson_really_inline simdjson_result<size_t> count_elements() & noexcept;
|
simdjson_really_inline simdjson_result<size_t> count_elements() & noexcept;
|
||||||
|
/**
|
||||||
|
* This method scans the beginning of the array and checks whether the
|
||||||
|
* array is empty.
|
||||||
|
* The runtime complexity is constant time. After
|
||||||
|
* calling this function, if successful, the array is 'rewinded' at its
|
||||||
|
* beginning as if it had never been accessed. If the JSON is malformed (e.g.,
|
||||||
|
* there is a missing comma), then an error is returned and it is no longer
|
||||||
|
* safe to continue.
|
||||||
|
*/
|
||||||
|
simdjson_really_inline simdjson_result<bool> is_empty() & noexcept;
|
||||||
|
/**
|
||||||
|
* Reset the iterator so that we are pointing back at the
|
||||||
|
* beginning of the array. You should still consume values only once even if you
|
||||||
|
* can iterate through the array more than once. If you unescape a string
|
||||||
|
* within the array more than once, you have unsafe code. Note that rewinding
|
||||||
|
* an array means that you may need to reparse it anew: it is not a free
|
||||||
|
* operation.
|
||||||
|
*
|
||||||
|
* @returns true if the array contains some elements (not empty)
|
||||||
|
*/
|
||||||
|
inline simdjson_result<bool> reset() & noexcept;
|
||||||
/**
|
/**
|
||||||
* Get the value associated with the given JSON pointer. We use the RFC 6901
|
* Get the value associated with the given JSON pointer. We use the RFC 6901
|
||||||
* https://tools.ietf.org/html/rfc6901 standard, interpreting the current node
|
* https://tools.ietf.org/html/rfc6901 standard, interpreting the current node
|
||||||
@@ -79,6 +102,14 @@ public:
|
|||||||
*/
|
*/
|
||||||
simdjson_really_inline simdjson_result<std::string_view> raw_json() noexcept;
|
simdjson_really_inline simdjson_result<std::string_view> raw_json() noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value at the given index. This function has linear-time complexity.
|
||||||
|
* This function should only be called once on an array instance since the array iterator is not reset between each call.
|
||||||
|
*
|
||||||
|
* @return The value at the given index, or:
|
||||||
|
* - INDEX_OUT_OF_BOUNDS if the array index is larger than an array length
|
||||||
|
*/
|
||||||
|
simdjson_really_inline simdjson_result<value> at(size_t index) noexcept;
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
* Go to the end of the array, no matter where you are right now.
|
* Go to the end of the array, no matter where you are right now.
|
||||||
@@ -121,15 +152,6 @@ protected:
|
|||||||
*/
|
*/
|
||||||
simdjson_really_inline array(const value_iterator &iter) noexcept;
|
simdjson_really_inline array(const value_iterator &iter) noexcept;
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the value at the given index. This function has linear-time complexity.
|
|
||||||
* This function should only be called once as the array iterator is not reset between each call.
|
|
||||||
*
|
|
||||||
* @return The value at the given index, or:
|
|
||||||
* - INDEX_OUT_OF_BOUNDS if the array index is larger than an array length
|
|
||||||
*/
|
|
||||||
simdjson_really_inline simdjson_result<value> at(size_t index) noexcept;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Iterator marking current position.
|
* Iterator marking current position.
|
||||||
*
|
*
|
||||||
@@ -159,7 +181,9 @@ public:
|
|||||||
|
|
||||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator> begin() noexcept;
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator> begin() noexcept;
|
||||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator> end() noexcept;
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator> end() noexcept;
|
||||||
simdjson_really_inline simdjson_result<size_t> count_elements() & noexcept;
|
inline simdjson_result<size_t> count_elements() & noexcept;
|
||||||
|
inline simdjson_result<bool> is_empty() & noexcept;
|
||||||
|
inline simdjson_result<bool> reset() & noexcept;
|
||||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> at(size_t index) noexcept;
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> at(size_t index) noexcept;
|
||||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> at_pointer(std::string_view json_pointer) noexcept;
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> at_pointer(std::string_view json_pointer) noexcept;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -20,6 +20,17 @@ inline std::string document::to_debug_string() noexcept {
|
|||||||
return iter.to_string();
|
return iter.to_string();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline simdjson_result<const char *> document::current_location() noexcept {
|
||||||
|
return iter.current_location();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int32_t document::current_depth() const noexcept {
|
||||||
|
return iter.depth();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool document::is_alive() noexcept {
|
||||||
|
return iter.is_alive();
|
||||||
|
}
|
||||||
simdjson_really_inline value_iterator document::resume_value_iterator() noexcept {
|
simdjson_really_inline value_iterator document::resume_value_iterator() noexcept {
|
||||||
return value_iterator(&iter, 1, iter.root_position());
|
return value_iterator(&iter, 1, iter.root_position());
|
||||||
}
|
}
|
||||||
@@ -33,24 +44,19 @@ simdjson_really_inline simdjson_result<object> document::start_or_resume_object(
|
|||||||
return object::resume(resume_value_iterator());
|
return object::resume(resume_value_iterator());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
simdjson_really_inline simdjson_result<value> document::get_value_unsafe() noexcept {
|
simdjson_really_inline simdjson_result<value> document::get_value() noexcept {
|
||||||
// Make sure we start any arrays or objects before returning, so that start_root_<object/array>()
|
// Make sure we start any arrays or objects before returning, so that start_root_<object/array>()
|
||||||
// gets called.
|
// gets called.
|
||||||
|
iter.assert_at_document_depth();
|
||||||
switch (*iter.peek()) {
|
switch (*iter.peek()) {
|
||||||
case '[': {
|
case '[':
|
||||||
array result;
|
case '{':
|
||||||
SIMDJSON_TRY( get_array().get(result) );
|
|
||||||
return value(result.iter);
|
|
||||||
}
|
|
||||||
case '{': {
|
|
||||||
object result;
|
|
||||||
SIMDJSON_TRY( get_object().get(result) );
|
|
||||||
return value(result.iter);
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
// TODO it is still wrong to convert this to a value! get_root_bool / etc. will not be
|
|
||||||
// called if you do this.
|
|
||||||
return value(get_root_value_iterator());
|
return value(get_root_value_iterator());
|
||||||
|
default:
|
||||||
|
// Unfortunately, scalar documents are a special case in simdjson and they cannot
|
||||||
|
// be safely converted to value instances.
|
||||||
|
return SCALAR_DOCUMENT_AS_VALUE;
|
||||||
|
// return value(get_root_value_iterator());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
simdjson_really_inline simdjson_result<array> document::get_array() & noexcept {
|
simdjson_really_inline simdjson_result<array> document::get_array() & noexcept {
|
||||||
@@ -64,12 +70,21 @@ simdjson_really_inline simdjson_result<object> document::get_object() & noexcept
|
|||||||
simdjson_really_inline simdjson_result<uint64_t> document::get_uint64() noexcept {
|
simdjson_really_inline simdjson_result<uint64_t> document::get_uint64() noexcept {
|
||||||
return get_root_value_iterator().get_root_uint64();
|
return get_root_value_iterator().get_root_uint64();
|
||||||
}
|
}
|
||||||
|
simdjson_really_inline simdjson_result<uint64_t> document::get_uint64_in_string() noexcept {
|
||||||
|
return get_root_value_iterator().get_root_uint64_in_string();
|
||||||
|
}
|
||||||
simdjson_really_inline simdjson_result<int64_t> document::get_int64() noexcept {
|
simdjson_really_inline simdjson_result<int64_t> document::get_int64() noexcept {
|
||||||
return get_root_value_iterator().get_root_int64();
|
return get_root_value_iterator().get_root_int64();
|
||||||
}
|
}
|
||||||
|
simdjson_really_inline simdjson_result<int64_t> document::get_int64_in_string() noexcept {
|
||||||
|
return get_root_value_iterator().get_root_int64_in_string();
|
||||||
|
}
|
||||||
simdjson_really_inline simdjson_result<double> document::get_double() noexcept {
|
simdjson_really_inline simdjson_result<double> document::get_double() noexcept {
|
||||||
return get_root_value_iterator().get_root_double();
|
return get_root_value_iterator().get_root_double();
|
||||||
}
|
}
|
||||||
|
simdjson_really_inline simdjson_result<double> document::get_double_in_string() noexcept {
|
||||||
|
return get_root_value_iterator().get_root_double_in_string();
|
||||||
|
}
|
||||||
simdjson_really_inline simdjson_result<std::string_view> document::get_string() noexcept {
|
simdjson_really_inline simdjson_result<std::string_view> document::get_string() noexcept {
|
||||||
return get_root_value_iterator().get_root_string();
|
return get_root_value_iterator().get_root_string();
|
||||||
}
|
}
|
||||||
@@ -91,6 +106,7 @@ template<> simdjson_really_inline simdjson_result<double> document::get() & noex
|
|||||||
template<> simdjson_really_inline simdjson_result<uint64_t> document::get() & noexcept { return get_uint64(); }
|
template<> simdjson_really_inline simdjson_result<uint64_t> document::get() & noexcept { return get_uint64(); }
|
||||||
template<> simdjson_really_inline simdjson_result<int64_t> document::get() & noexcept { return get_int64(); }
|
template<> simdjson_really_inline simdjson_result<int64_t> document::get() & noexcept { return get_int64(); }
|
||||||
template<> simdjson_really_inline simdjson_result<bool> document::get() & noexcept { return get_bool(); }
|
template<> simdjson_really_inline simdjson_result<bool> document::get() & noexcept { return get_bool(); }
|
||||||
|
template<> simdjson_really_inline simdjson_result<value> document::get() & noexcept { return get_value(); }
|
||||||
|
|
||||||
template<> simdjson_really_inline simdjson_result<raw_json_string> document::get() && noexcept { return get_raw_json_string(); }
|
template<> simdjson_really_inline simdjson_result<raw_json_string> document::get() && noexcept { return get_raw_json_string(); }
|
||||||
template<> simdjson_really_inline simdjson_result<std::string_view> document::get() && noexcept { return get_string(); }
|
template<> simdjson_really_inline simdjson_result<std::string_view> document::get() && noexcept { return get_string(); }
|
||||||
@@ -98,6 +114,7 @@ template<> simdjson_really_inline simdjson_result<double> document::get() && noe
|
|||||||
template<> simdjson_really_inline simdjson_result<uint64_t> document::get() && noexcept { return std::forward<document>(*this).get_uint64(); }
|
template<> simdjson_really_inline simdjson_result<uint64_t> document::get() && noexcept { return std::forward<document>(*this).get_uint64(); }
|
||||||
template<> simdjson_really_inline simdjson_result<int64_t> document::get() && noexcept { return std::forward<document>(*this).get_int64(); }
|
template<> simdjson_really_inline simdjson_result<int64_t> document::get() && noexcept { return std::forward<document>(*this).get_int64(); }
|
||||||
template<> simdjson_really_inline simdjson_result<bool> document::get() && noexcept { return std::forward<document>(*this).get_bool(); }
|
template<> simdjson_really_inline simdjson_result<bool> document::get() && noexcept { return std::forward<document>(*this).get_bool(); }
|
||||||
|
template<> simdjson_really_inline simdjson_result<value> document::get() && noexcept { return get_value(); }
|
||||||
|
|
||||||
template<typename T> simdjson_really_inline error_code document::get(T &out) & noexcept {
|
template<typename T> simdjson_really_inline error_code document::get(T &out) & noexcept {
|
||||||
return get<T>().get(out);
|
return get<T>().get(out);
|
||||||
@@ -115,14 +132,33 @@ simdjson_really_inline document::operator double() noexcept(false) { return get_
|
|||||||
simdjson_really_inline document::operator std::string_view() noexcept(false) { return get_string(); }
|
simdjson_really_inline document::operator std::string_view() noexcept(false) { return get_string(); }
|
||||||
simdjson_really_inline document::operator raw_json_string() noexcept(false) { return get_raw_json_string(); }
|
simdjson_really_inline document::operator raw_json_string() noexcept(false) { return get_raw_json_string(); }
|
||||||
simdjson_really_inline document::operator bool() noexcept(false) { return get_bool(); }
|
simdjson_really_inline document::operator bool() noexcept(false) { return get_bool(); }
|
||||||
|
simdjson_really_inline document::operator value() noexcept(false) { return get_value(); }
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
simdjson_really_inline simdjson_result<size_t> document::count_elements() & noexcept {
|
simdjson_really_inline simdjson_result<size_t> document::count_elements() & noexcept {
|
||||||
auto a = get_array();
|
auto a = get_array();
|
||||||
simdjson_result<size_t> answer = a.count_elements();
|
simdjson_result<size_t> answer = a.count_elements();
|
||||||
/* If there was an array, we are now left pointing at its first element. */
|
/* If there was an array, we are now left pointing at its first element. */
|
||||||
if(answer.error() == SUCCESS) { iter._depth -= 1 ; /* undoing the increment so we go back at the doc depth.*/ }
|
if(answer.error() == SUCCESS) {
|
||||||
|
iter._depth = 1 ; /* undoing the increment so we go back at the doc depth.*/
|
||||||
|
iter.assert_at_document_depth();
|
||||||
|
}
|
||||||
return answer;
|
return answer;
|
||||||
}
|
}
|
||||||
|
simdjson_really_inline simdjson_result<size_t> document::count_fields() & noexcept {
|
||||||
|
auto a = get_object();
|
||||||
|
simdjson_result<size_t> answer = a.count_fields();
|
||||||
|
/* If there was an array, we are now left pointing at its first element. */
|
||||||
|
if(answer.error() == SUCCESS) {
|
||||||
|
iter._depth = 1 ; /* undoing the increment so we go back at the doc depth.*/
|
||||||
|
iter.assert_at_document_depth();
|
||||||
|
}
|
||||||
|
return answer;
|
||||||
|
}
|
||||||
|
simdjson_really_inline simdjson_result<value> document::at(size_t index) & noexcept {
|
||||||
|
auto a = get_array();
|
||||||
|
return a.at(index);
|
||||||
|
}
|
||||||
simdjson_really_inline simdjson_result<array_iterator> document::begin() & noexcept {
|
simdjson_really_inline simdjson_result<array_iterator> document::begin() & noexcept {
|
||||||
return get_array().begin();
|
return get_array().begin();
|
||||||
}
|
}
|
||||||
@@ -156,12 +192,14 @@ simdjson_really_inline error_code document::consume() noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
simdjson_really_inline simdjson_result<std::string_view> document::raw_json() noexcept {
|
simdjson_really_inline simdjson_result<std::string_view> document::raw_json() noexcept {
|
||||||
printf("document::raw_json()\n");
|
|
||||||
auto _iter = get_root_value_iterator();
|
auto _iter = get_root_value_iterator();
|
||||||
const uint8_t * starting_point{_iter.peek_start()};
|
const uint8_t * starting_point{_iter.peek_start()};
|
||||||
auto error = consume();
|
auto error = consume();
|
||||||
if(error) { return error; }
|
if(error) { return error; }
|
||||||
const uint8_t * final_point{iter.peek(0)};
|
// After 'consume()', we could be left pointing just beyond the document, but that
|
||||||
|
// is ok because we are not going to dereference the final pointer position, we just
|
||||||
|
// use it to compute the length in bytes.
|
||||||
|
const uint8_t * final_point{iter.unsafe_pointer()};
|
||||||
return std::string_view(reinterpret_cast<const char*>(starting_point), size_t(final_point - starting_point));
|
return std::string_view(reinterpret_cast<const char*>(starting_point), size_t(final_point - starting_point));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,6 +207,30 @@ simdjson_really_inline simdjson_result<json_type> document::type() noexcept {
|
|||||||
return get_root_value_iterator().type();
|
return get_root_value_iterator().type();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
simdjson_really_inline simdjson_result<bool> document::is_scalar() noexcept {
|
||||||
|
json_type this_type;
|
||||||
|
auto error = type().get(this_type);
|
||||||
|
if(error) { return error; }
|
||||||
|
return ! ((this_type == json_type::array) || (this_type == json_type::object));
|
||||||
|
}
|
||||||
|
|
||||||
|
simdjson_really_inline bool document::is_negative() noexcept {
|
||||||
|
return get_root_value_iterator().is_root_negative();
|
||||||
|
}
|
||||||
|
|
||||||
|
simdjson_really_inline simdjson_result<bool> document::is_integer() noexcept {
|
||||||
|
return get_root_value_iterator().is_root_integer();
|
||||||
|
}
|
||||||
|
|
||||||
|
simdjson_really_inline simdjson_result<number_type> document::get_number_type() noexcept {
|
||||||
|
return get_root_value_iterator().get_root_number_type();
|
||||||
|
}
|
||||||
|
|
||||||
|
simdjson_really_inline simdjson_result<number> document::get_number() noexcept {
|
||||||
|
return get_root_value_iterator().get_root_number();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
simdjson_really_inline simdjson_result<std::string_view> document::raw_json_token() noexcept {
|
simdjson_really_inline simdjson_result<std::string_view> document::raw_json_token() noexcept {
|
||||||
auto _iter = get_root_value_iterator();
|
auto _iter = get_root_value_iterator();
|
||||||
return std::string_view(reinterpret_cast<const char*>(_iter.peek_start()), _iter.peek_start_length());
|
return std::string_view(reinterpret_cast<const char*>(_iter.peek_start()), _iter.peek_start_length());
|
||||||
@@ -177,7 +239,7 @@ simdjson_really_inline simdjson_result<std::string_view> document::raw_json_toke
|
|||||||
simdjson_really_inline simdjson_result<value> document::at_pointer(std::string_view json_pointer) noexcept {
|
simdjson_really_inline simdjson_result<value> document::at_pointer(std::string_view json_pointer) noexcept {
|
||||||
rewind(); // Rewind the document each time at_pointer is called
|
rewind(); // Rewind the document each time at_pointer is called
|
||||||
if (json_pointer.empty()) {
|
if (json_pointer.empty()) {
|
||||||
return this->get_value_unsafe();
|
return this->get_value();
|
||||||
}
|
}
|
||||||
json_type t;
|
json_type t;
|
||||||
SIMDJSON_TRY(type().get(t));
|
SIMDJSON_TRY(type().get(t));
|
||||||
@@ -218,6 +280,14 @@ simdjson_really_inline simdjson_result<size_t> simdjson_result<SIMDJSON_IMPLEMEN
|
|||||||
if (error()) { return error(); }
|
if (error()) { return error(); }
|
||||||
return first.count_elements();
|
return first.count_elements();
|
||||||
}
|
}
|
||||||
|
simdjson_really_inline simdjson_result<size_t> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::count_fields() & noexcept {
|
||||||
|
if (error()) { return error(); }
|
||||||
|
return first.count_fields();
|
||||||
|
}
|
||||||
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::at(size_t index) & noexcept {
|
||||||
|
if (error()) { return error(); }
|
||||||
|
return first.at(index);
|
||||||
|
}
|
||||||
simdjson_really_inline error_code simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::rewind() noexcept {
|
simdjson_really_inline error_code simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::rewind() noexcept {
|
||||||
if (error()) { return error(); }
|
if (error()) { return error(); }
|
||||||
first.rewind();
|
first.rewind();
|
||||||
@@ -286,6 +356,10 @@ simdjson_really_inline simdjson_result<bool> simdjson_result<SIMDJSON_IMPLEMENTA
|
|||||||
if (error()) { return error(); }
|
if (error()) { return error(); }
|
||||||
return first.get_bool();
|
return first.get_bool();
|
||||||
}
|
}
|
||||||
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::get_value() noexcept {
|
||||||
|
if (error()) { return error(); }
|
||||||
|
return first.get_value();
|
||||||
|
}
|
||||||
simdjson_really_inline bool simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::is_null() noexcept {
|
simdjson_really_inline bool simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::is_null() noexcept {
|
||||||
if (error()) { return error(); }
|
if (error()) { return error(); }
|
||||||
return first.is_null();
|
return first.is_null();
|
||||||
@@ -329,6 +403,33 @@ simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::json_t
|
|||||||
return first.type();
|
return first.type();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
simdjson_really_inline simdjson_result<bool> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::is_scalar() noexcept {
|
||||||
|
if (error()) { return error(); }
|
||||||
|
return first.is_scalar();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
simdjson_really_inline bool simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::is_negative() noexcept {
|
||||||
|
if (error()) { return error(); }
|
||||||
|
return first.is_negative();
|
||||||
|
}
|
||||||
|
|
||||||
|
simdjson_really_inline simdjson_result<bool> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::is_integer() noexcept {
|
||||||
|
if (error()) { return error(); }
|
||||||
|
return first.is_integer();
|
||||||
|
}
|
||||||
|
|
||||||
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::number_type> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::get_number_type() noexcept {
|
||||||
|
if (error()) { return error(); }
|
||||||
|
return first.get_number_type();
|
||||||
|
}
|
||||||
|
|
||||||
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::number> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::get_number() noexcept {
|
||||||
|
if (error()) { return error(); }
|
||||||
|
return first.get_number();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#if SIMDJSON_EXCEPTIONS
|
#if SIMDJSON_EXCEPTIONS
|
||||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::operator SIMDJSON_IMPLEMENTATION::ondemand::array() & noexcept(false) {
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::operator SIMDJSON_IMPLEMENTATION::ondemand::array() & noexcept(false) {
|
||||||
if (error()) { throw simdjson_error(error()); }
|
if (error()) { throw simdjson_error(error()); }
|
||||||
@@ -362,8 +463,23 @@ simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::docume
|
|||||||
if (error()) { throw simdjson_error(error()); }
|
if (error()) { throw simdjson_error(error()); }
|
||||||
return first;
|
return first;
|
||||||
}
|
}
|
||||||
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::operator SIMDJSON_IMPLEMENTATION::ondemand::value() noexcept(false) {
|
||||||
|
if (error()) { throw simdjson_error(error()); }
|
||||||
|
return first;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
simdjson_really_inline simdjson_result<const char *> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::current_location() noexcept {
|
||||||
|
if (error()) { return error(); }
|
||||||
|
return first.current_location();
|
||||||
|
}
|
||||||
|
|
||||||
|
simdjson_really_inline int32_t simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::current_depth() const noexcept {
|
||||||
|
if (error()) { return error(); }
|
||||||
|
return first.current_depth();
|
||||||
|
}
|
||||||
|
|
||||||
simdjson_really_inline simdjson_result<std::string_view> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::raw_json_token() noexcept {
|
simdjson_really_inline simdjson_result<std::string_view> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::raw_json_token() noexcept {
|
||||||
if (error()) { return error(); }
|
if (error()) { return error(); }
|
||||||
return first.raw_json_token();
|
return first.raw_json_token();
|
||||||
@@ -374,4 +490,239 @@ simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>
|
|||||||
return first.at_pointer(json_pointer);
|
return first.at_pointer(json_pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace simdjson
|
||||||
|
|
||||||
|
|
||||||
|
namespace simdjson {
|
||||||
|
namespace SIMDJSON_IMPLEMENTATION {
|
||||||
|
namespace ondemand {
|
||||||
|
|
||||||
|
simdjson_really_inline document_reference::document_reference() noexcept : doc{nullptr} {}
|
||||||
|
simdjson_really_inline document_reference::document_reference(document &d) noexcept : doc(&d) {}
|
||||||
|
simdjson_really_inline void document_reference::rewind() noexcept { doc->rewind(); }
|
||||||
|
simdjson_really_inline simdjson_result<array> document_reference::get_array() & noexcept { return doc->get_array(); }
|
||||||
|
simdjson_really_inline simdjson_result<object> document_reference::get_object() & noexcept { return doc->get_object(); }
|
||||||
|
simdjson_really_inline simdjson_result<uint64_t> document_reference::get_uint64() noexcept { return doc->get_uint64(); }
|
||||||
|
simdjson_really_inline simdjson_result<int64_t> document_reference::get_int64() noexcept { return doc->get_int64(); }
|
||||||
|
simdjson_really_inline simdjson_result<double> document_reference::get_double() noexcept { return doc->get_double(); }
|
||||||
|
simdjson_really_inline simdjson_result<std::string_view> document_reference::get_string() noexcept { return doc->get_string(); }
|
||||||
|
simdjson_really_inline simdjson_result<raw_json_string> document_reference::get_raw_json_string() noexcept { return doc->get_raw_json_string(); }
|
||||||
|
simdjson_really_inline simdjson_result<bool> document_reference::get_bool() noexcept { return doc->get_bool(); }
|
||||||
|
simdjson_really_inline simdjson_result<value> document_reference::get_value() noexcept { return doc->get_value(); }
|
||||||
|
simdjson_really_inline bool document_reference::is_null() noexcept { return doc->is_null(); }
|
||||||
|
|
||||||
|
#if SIMDJSON_EXCEPTIONS
|
||||||
|
simdjson_really_inline document_reference::operator array() & noexcept(false) { return array(*doc); }
|
||||||
|
simdjson_really_inline document_reference::operator object() & noexcept(false) { return object(*doc); }
|
||||||
|
simdjson_really_inline document_reference::operator uint64_t() noexcept(false) { return uint64_t(*doc); }
|
||||||
|
simdjson_really_inline document_reference::operator int64_t() noexcept(false) { return int64_t(*doc); }
|
||||||
|
simdjson_really_inline document_reference::operator double() noexcept(false) { return double(*doc); }
|
||||||
|
simdjson_really_inline document_reference::operator std::string_view() noexcept(false) { return std::string_view(*doc); }
|
||||||
|
simdjson_really_inline document_reference::operator raw_json_string() noexcept(false) { return raw_json_string(*doc); }
|
||||||
|
simdjson_really_inline document_reference::operator bool() noexcept(false) { return bool(*doc); }
|
||||||
|
simdjson_really_inline document_reference::operator value() noexcept(false) { return value(*doc); }
|
||||||
|
#endif
|
||||||
|
simdjson_really_inline simdjson_result<size_t> document_reference::count_elements() & noexcept { return doc->count_elements(); }
|
||||||
|
simdjson_really_inline simdjson_result<size_t> document_reference::count_fields() & noexcept { return doc->count_fields(); }
|
||||||
|
simdjson_really_inline simdjson_result<value> document_reference::at(size_t index) & noexcept { return doc->at(index); }
|
||||||
|
simdjson_really_inline simdjson_result<array_iterator> document_reference::begin() & noexcept { return doc->begin(); }
|
||||||
|
simdjson_really_inline simdjson_result<array_iterator> document_reference::end() & noexcept { return doc->end(); }
|
||||||
|
simdjson_really_inline simdjson_result<value> document_reference::find_field(std::string_view key) & noexcept { return doc->find_field(key); }
|
||||||
|
simdjson_really_inline simdjson_result<value> document_reference::find_field(const char *key) & noexcept { return doc->find_field(key); }
|
||||||
|
simdjson_really_inline simdjson_result<value> document_reference::operator[](std::string_view key) & noexcept { return (*doc)[key]; }
|
||||||
|
simdjson_really_inline simdjson_result<value> document_reference::operator[](const char *key) & noexcept { return (*doc)[key]; }
|
||||||
|
simdjson_really_inline simdjson_result<value> document_reference::find_field_unordered(std::string_view key) & noexcept { return doc->find_field_unordered(key); }
|
||||||
|
simdjson_really_inline simdjson_result<value> document_reference::find_field_unordered(const char *key) & noexcept { return doc->find_field_unordered(key); }
|
||||||
|
simdjson_really_inline simdjson_result<json_type> document_reference::type() noexcept { return doc->type(); }
|
||||||
|
simdjson_really_inline simdjson_result<bool> document_reference::is_scalar() noexcept { return doc->is_scalar(); }
|
||||||
|
simdjson_really_inline simdjson_result<const char *> document_reference::current_location() noexcept { return doc->current_location(); }
|
||||||
|
simdjson_really_inline int32_t document_reference::current_depth() const noexcept { return doc->current_depth(); }
|
||||||
|
simdjson_really_inline bool document_reference::is_negative() noexcept { return doc->is_negative(); }
|
||||||
|
simdjson_really_inline simdjson_result<bool> document_reference::is_integer() noexcept { return doc->is_integer(); }
|
||||||
|
simdjson_really_inline simdjson_result<number_type> document_reference::get_number_type() noexcept { return doc->get_number_type(); }
|
||||||
|
simdjson_really_inline simdjson_result<number> document_reference::get_number() noexcept { return doc->get_number(); }
|
||||||
|
simdjson_really_inline simdjson_result<std::string_view> document_reference::raw_json_token() noexcept { return doc->raw_json_token(); }
|
||||||
|
simdjson_really_inline simdjson_result<value> document_reference::at_pointer(std::string_view json_pointer) noexcept { return doc->at_pointer(json_pointer); }
|
||||||
|
simdjson_really_inline simdjson_result<std::string_view> document_reference::raw_json() noexcept { return doc->raw_json();}
|
||||||
|
simdjson_really_inline document_reference::operator document&() const noexcept { return *doc; }
|
||||||
|
|
||||||
|
} // namespace ondemand
|
||||||
|
} // namespace SIMDJSON_IMPLEMENTATION
|
||||||
|
} // namespace simdjson
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
namespace simdjson {
|
||||||
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::simdjson_result(SIMDJSON_IMPLEMENTATION::ondemand::document_reference value, error_code error)
|
||||||
|
noexcept : implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>(std::forward<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>(value), error) {}
|
||||||
|
|
||||||
|
|
||||||
|
simdjson_really_inline simdjson_result<size_t> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::count_elements() & noexcept {
|
||||||
|
if (error()) { return error(); }
|
||||||
|
return first.count_elements();
|
||||||
|
}
|
||||||
|
simdjson_really_inline simdjson_result<size_t> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::count_fields() & noexcept {
|
||||||
|
if (error()) { return error(); }
|
||||||
|
return first.count_fields();
|
||||||
|
}
|
||||||
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::at(size_t index) & noexcept {
|
||||||
|
if (error()) { return error(); }
|
||||||
|
return first.at(index);
|
||||||
|
}
|
||||||
|
simdjson_really_inline error_code simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::rewind() noexcept {
|
||||||
|
if (error()) { return error(); }
|
||||||
|
first.rewind();
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::begin() & noexcept {
|
||||||
|
if (error()) { return error(); }
|
||||||
|
return first.begin();
|
||||||
|
}
|
||||||
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::end() & noexcept {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::find_field_unordered(std::string_view key) & noexcept {
|
||||||
|
if (error()) { return error(); }
|
||||||
|
return first.find_field_unordered(key);
|
||||||
|
}
|
||||||
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::find_field_unordered(const char *key) & noexcept {
|
||||||
|
if (error()) { return error(); }
|
||||||
|
return first.find_field_unordered(key);
|
||||||
|
}
|
||||||
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::operator[](std::string_view key) & noexcept {
|
||||||
|
if (error()) { return error(); }
|
||||||
|
return first[key];
|
||||||
|
}
|
||||||
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::operator[](const char *key) & noexcept {
|
||||||
|
if (error()) { return error(); }
|
||||||
|
return first[key];
|
||||||
|
}
|
||||||
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::find_field(std::string_view key) & noexcept {
|
||||||
|
if (error()) { return error(); }
|
||||||
|
return first.find_field(key);
|
||||||
|
}
|
||||||
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::find_field(const char *key) & noexcept {
|
||||||
|
if (error()) { return error(); }
|
||||||
|
return first.find_field(key);
|
||||||
|
}
|
||||||
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::get_array() & noexcept {
|
||||||
|
if (error()) { return error(); }
|
||||||
|
return first.get_array();
|
||||||
|
}
|
||||||
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::get_object() & noexcept {
|
||||||
|
if (error()) { return error(); }
|
||||||
|
return first.get_object();
|
||||||
|
}
|
||||||
|
simdjson_really_inline simdjson_result<uint64_t> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::get_uint64() noexcept {
|
||||||
|
if (error()) { return error(); }
|
||||||
|
return first.get_uint64();
|
||||||
|
}
|
||||||
|
simdjson_really_inline simdjson_result<int64_t> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::get_int64() noexcept {
|
||||||
|
if (error()) { return error(); }
|
||||||
|
return first.get_int64();
|
||||||
|
}
|
||||||
|
simdjson_really_inline simdjson_result<double> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::get_double() noexcept {
|
||||||
|
if (error()) { return error(); }
|
||||||
|
return first.get_double();
|
||||||
|
}
|
||||||
|
simdjson_really_inline simdjson_result<std::string_view> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::get_string() noexcept {
|
||||||
|
if (error()) { return error(); }
|
||||||
|
return first.get_string();
|
||||||
|
}
|
||||||
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::get_raw_json_string() noexcept {
|
||||||
|
if (error()) { return error(); }
|
||||||
|
return first.get_raw_json_string();
|
||||||
|
}
|
||||||
|
simdjson_really_inline simdjson_result<bool> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::get_bool() noexcept {
|
||||||
|
if (error()) { return error(); }
|
||||||
|
return first.get_bool();
|
||||||
|
}
|
||||||
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::get_value() noexcept {
|
||||||
|
if (error()) { return error(); }
|
||||||
|
return first.get_value();
|
||||||
|
}
|
||||||
|
simdjson_really_inline bool simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::is_null() noexcept {
|
||||||
|
if (error()) { return error(); }
|
||||||
|
return first.is_null();
|
||||||
|
}
|
||||||
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::json_type> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::type() noexcept {
|
||||||
|
if (error()) { return error(); }
|
||||||
|
return first.type();
|
||||||
|
}
|
||||||
|
simdjson_really_inline simdjson_result<bool> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::is_scalar() noexcept {
|
||||||
|
if (error()) { return error(); }
|
||||||
|
return first.is_scalar();
|
||||||
|
}
|
||||||
|
simdjson_really_inline bool simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::is_negative() noexcept {
|
||||||
|
if (error()) { return error(); }
|
||||||
|
return first.is_negative();
|
||||||
|
}
|
||||||
|
simdjson_really_inline simdjson_result<bool> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::is_integer() noexcept {
|
||||||
|
if (error()) { return error(); }
|
||||||
|
return first.is_integer();
|
||||||
|
}
|
||||||
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::number_type> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::get_number_type() noexcept {
|
||||||
|
if (error()) { return error(); }
|
||||||
|
return first.get_number_type();
|
||||||
|
}
|
||||||
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::number> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::get_number() noexcept {
|
||||||
|
if (error()) { return error(); }
|
||||||
|
return first.get_number();
|
||||||
|
}
|
||||||
|
#if SIMDJSON_EXCEPTIONS
|
||||||
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::operator SIMDJSON_IMPLEMENTATION::ondemand::array() & noexcept(false) {
|
||||||
|
if (error()) { throw simdjson_error(error()); }
|
||||||
|
return first;
|
||||||
|
}
|
||||||
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::operator SIMDJSON_IMPLEMENTATION::ondemand::object() & noexcept(false) {
|
||||||
|
if (error()) { throw simdjson_error(error()); }
|
||||||
|
return first;
|
||||||
|
}
|
||||||
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::operator uint64_t() noexcept(false) {
|
||||||
|
if (error()) { throw simdjson_error(error()); }
|
||||||
|
return first;
|
||||||
|
}
|
||||||
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::operator int64_t() noexcept(false) {
|
||||||
|
if (error()) { throw simdjson_error(error()); }
|
||||||
|
return first;
|
||||||
|
}
|
||||||
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::operator double() noexcept(false) {
|
||||||
|
if (error()) { throw simdjson_error(error()); }
|
||||||
|
return first;
|
||||||
|
}
|
||||||
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::operator std::string_view() noexcept(false) {
|
||||||
|
if (error()) { throw simdjson_error(error()); }
|
||||||
|
return first;
|
||||||
|
}
|
||||||
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::operator SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string() noexcept(false) {
|
||||||
|
if (error()) { throw simdjson_error(error()); }
|
||||||
|
return first;
|
||||||
|
}
|
||||||
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::operator bool() noexcept(false) {
|
||||||
|
if (error()) { throw simdjson_error(error()); }
|
||||||
|
return first;
|
||||||
|
}
|
||||||
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::operator SIMDJSON_IMPLEMENTATION::ondemand::value() noexcept(false) {
|
||||||
|
if (error()) { throw simdjson_error(error()); }
|
||||||
|
return first;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
simdjson_really_inline simdjson_result<const char *> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::current_location() noexcept {
|
||||||
|
if (error()) { return error(); }
|
||||||
|
return first.current_location();
|
||||||
|
}
|
||||||
|
|
||||||
|
simdjson_really_inline simdjson_result<std::string_view> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::raw_json_token() noexcept {
|
||||||
|
if (error()) { return error(); }
|
||||||
|
return first.raw_json_token();
|
||||||
|
}
|
||||||
|
|
||||||
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::at_pointer(std::string_view json_pointer) noexcept {
|
||||||
|
if (error()) { return error(); }
|
||||||
|
return first.at_pointer(json_pointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} // namespace simdjson
|
} // namespace simdjson
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ class array_iterator;
|
|||||||
class document_stream;
|
class document_stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A JSON document iteration.
|
* A JSON document. It holds a json_iterator instance.
|
||||||
*
|
*
|
||||||
* Used by tokens to get text, and string buffer location.
|
* Used by tokens to get text, and string buffer location.
|
||||||
*
|
*
|
||||||
@@ -27,7 +27,7 @@ public:
|
|||||||
* Exists so you can declare a variable and later assign to it before use.
|
* Exists so you can declare a variable and later assign to it before use.
|
||||||
*/
|
*/
|
||||||
simdjson_really_inline document() noexcept = default;
|
simdjson_really_inline document() noexcept = default;
|
||||||
simdjson_really_inline document(const document &other) noexcept = delete;
|
simdjson_really_inline document(const document &other) noexcept = delete; // pass your documents by reference, not by copy
|
||||||
simdjson_really_inline document(document &&other) noexcept = default;
|
simdjson_really_inline document(document &&other) noexcept = default;
|
||||||
simdjson_really_inline document &operator=(const document &other) noexcept = delete;
|
simdjson_really_inline document &operator=(const document &other) noexcept = delete;
|
||||||
simdjson_really_inline document &operator=(document &&other) noexcept = default;
|
simdjson_really_inline document &operator=(document &&other) noexcept = default;
|
||||||
@@ -53,6 +53,13 @@ public:
|
|||||||
* @returns INCORRECT_TYPE If the JSON value is not a 64-bit unsigned integer.
|
* @returns INCORRECT_TYPE If the JSON value is not a 64-bit unsigned integer.
|
||||||
*/
|
*/
|
||||||
simdjson_really_inline simdjson_result<uint64_t> get_uint64() noexcept;
|
simdjson_really_inline simdjson_result<uint64_t> get_uint64() noexcept;
|
||||||
|
/**
|
||||||
|
* Cast this JSON value (inside string) to an unsigned integer.
|
||||||
|
*
|
||||||
|
* @returns A signed 64-bit integer.
|
||||||
|
* @returns INCORRECT_TYPE If the JSON value is not a 64-bit unsigned integer.
|
||||||
|
*/
|
||||||
|
simdjson_really_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
|
||||||
/**
|
/**
|
||||||
* Cast this JSON value to a signed integer.
|
* Cast this JSON value to a signed integer.
|
||||||
*
|
*
|
||||||
@@ -60,6 +67,13 @@ public:
|
|||||||
* @returns INCORRECT_TYPE If the JSON value is not a 64-bit integer.
|
* @returns INCORRECT_TYPE If the JSON value is not a 64-bit integer.
|
||||||
*/
|
*/
|
||||||
simdjson_really_inline simdjson_result<int64_t> get_int64() noexcept;
|
simdjson_really_inline simdjson_result<int64_t> get_int64() noexcept;
|
||||||
|
/**
|
||||||
|
* Cast this JSON value (inside string) to a signed integer.
|
||||||
|
*
|
||||||
|
* @returns A signed 64-bit integer.
|
||||||
|
* @returns INCORRECT_TYPE If the JSON value is not a 64-bit integer.
|
||||||
|
*/
|
||||||
|
simdjson_really_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
|
||||||
/**
|
/**
|
||||||
* Cast this JSON value to a double.
|
* Cast this JSON value to a double.
|
||||||
*
|
*
|
||||||
@@ -67,11 +81,21 @@ public:
|
|||||||
* @returns INCORRECT_TYPE If the JSON value is not a valid floating-point number.
|
* @returns INCORRECT_TYPE If the JSON value is not a valid floating-point number.
|
||||||
*/
|
*/
|
||||||
simdjson_really_inline simdjson_result<double> get_double() noexcept;
|
simdjson_really_inline simdjson_result<double> get_double() noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cast this JSON value (inside string) to a double.
|
||||||
|
*
|
||||||
|
* @returns A double.
|
||||||
|
* @returns INCORRECT_TYPE If the JSON value is not a valid floating-point number.
|
||||||
|
*/
|
||||||
|
simdjson_really_inline simdjson_result<double> get_double_in_string() noexcept;
|
||||||
/**
|
/**
|
||||||
* Cast this JSON value to a string.
|
* Cast this JSON value to a string.
|
||||||
*
|
*
|
||||||
* The string is guaranteed to be valid UTF-8.
|
* The string is guaranteed to be valid UTF-8.
|
||||||
*
|
*
|
||||||
|
* Important: Calling get_string() twice on the same document is an error.
|
||||||
|
*
|
||||||
* @returns An UTF-8 string. The string is stored in the parser and will be invalidated the next
|
* @returns An UTF-8 string. The string is stored in the parser and will be invalidated the next
|
||||||
* time it parses a document or when it is destroyed.
|
* time it parses a document or when it is destroyed.
|
||||||
* @returns INCORRECT_TYPE if the JSON value is not a string.
|
* @returns INCORRECT_TYPE if the JSON value is not a string.
|
||||||
@@ -93,6 +117,14 @@ public:
|
|||||||
* @returns INCORRECT_TYPE if the JSON value is not true or false.
|
* @returns INCORRECT_TYPE if the JSON value is not true or false.
|
||||||
*/
|
*/
|
||||||
simdjson_really_inline simdjson_result<bool> get_bool() noexcept;
|
simdjson_really_inline simdjson_result<bool> get_bool() noexcept;
|
||||||
|
/**
|
||||||
|
* Cast this JSON value to a value when the document is an object or an array.
|
||||||
|
*
|
||||||
|
* @returns A value if a JSON array or object cannot be found.
|
||||||
|
* @returns SCALAR_DOCUMENT_AS_VALUE error is the document is a scalar (see is_scalar() function).
|
||||||
|
*/
|
||||||
|
simdjson_really_inline simdjson_result<value> get_value() noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if this JSON value is null.
|
* Checks if this JSON value is null.
|
||||||
*
|
*
|
||||||
@@ -126,7 +158,9 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Get this value as the given type.
|
* Get this value as the given type.
|
||||||
*
|
*
|
||||||
* Supported types: object, array, raw_json_string, string_view, uint64_t, int64_t, double, bool
|
* Supported types: object, array, raw_json_string, string_view, uint64_t, int64_t, double, bool, value
|
||||||
|
*
|
||||||
|
* Be mindful that the document instance must remain in scope while you are accessing object, array and value instances.
|
||||||
*
|
*
|
||||||
* @param out This is set to a value of the given type, parsed from the JSON. If there is an error, this may not be initialized.
|
* @param out This is set to a value of the given type, parsed from the JSON. If there is an error, this may not be initialized.
|
||||||
* @returns INCORRECT_TYPE If the JSON value is not an object.
|
* @returns INCORRECT_TYPE If the JSON value is not an object.
|
||||||
@@ -198,6 +232,13 @@ public:
|
|||||||
* @exception simdjson_error(INCORRECT_TYPE) if the JSON value is not true or false.
|
* @exception simdjson_error(INCORRECT_TYPE) if the JSON value is not true or false.
|
||||||
*/
|
*/
|
||||||
simdjson_really_inline operator bool() noexcept(false);
|
simdjson_really_inline operator bool() noexcept(false);
|
||||||
|
/**
|
||||||
|
* Cast this JSON value to a value.
|
||||||
|
*
|
||||||
|
* @returns A value value.
|
||||||
|
* @exception if a JSON value cannot be found
|
||||||
|
*/
|
||||||
|
simdjson_really_inline operator value() noexcept(false);
|
||||||
#endif
|
#endif
|
||||||
/**
|
/**
|
||||||
* This method scans the array and counts the number of elements.
|
* This method scans the array and counts the number of elements.
|
||||||
@@ -211,6 +252,29 @@ public:
|
|||||||
* safe to continue.
|
* safe to continue.
|
||||||
*/
|
*/
|
||||||
simdjson_really_inline simdjson_result<size_t> count_elements() & noexcept;
|
simdjson_really_inline simdjson_result<size_t> count_elements() & noexcept;
|
||||||
|
/**
|
||||||
|
* This method scans the object and counts the number of key-value pairs.
|
||||||
|
* The count_fields method should always be called before you have begun
|
||||||
|
* iterating through the object: it is expected that you are pointing at
|
||||||
|
* the beginning of the object.
|
||||||
|
* The runtime complexity is linear in the size of the object. After
|
||||||
|
* calling this function, if successful, the object is 'rewinded' at its
|
||||||
|
* beginning as if it had never been accessed. If the JSON is malformed (e.g.,
|
||||||
|
* there is a missing comma), then an error is returned and it is no longer
|
||||||
|
* safe to continue.
|
||||||
|
*
|
||||||
|
* To check that an object is empty, it is more performant to use
|
||||||
|
* the is_empty() method.
|
||||||
|
*/
|
||||||
|
simdjson_really_inline simdjson_result<size_t> count_fields() & noexcept;
|
||||||
|
/**
|
||||||
|
* Get the value at the given index in the array. This function has linear-time complexity.
|
||||||
|
* This function should only be called once on an array instance since the array iterator is not reset between each call.
|
||||||
|
*
|
||||||
|
* @return The value at the given index, or:
|
||||||
|
* - INDEX_OUT_OF_BOUNDS if the array index is larger than an array length
|
||||||
|
*/
|
||||||
|
simdjson_really_inline simdjson_result<value> at(size_t index) & noexcept;
|
||||||
/**
|
/**
|
||||||
* Begin array iteration.
|
* Begin array iteration.
|
||||||
*
|
*
|
||||||
@@ -241,6 +305,18 @@ public:
|
|||||||
* **Raw Keys:** The lookup will be done against the *raw* key, and will not unescape keys.
|
* **Raw Keys:** The lookup will be done against the *raw* key, and will not unescape keys.
|
||||||
* e.g. `object["a"]` will match `{ "a": 1 }`, but will *not* match `{ "\u0061": 1 }`.
|
* e.g. `object["a"]` will match `{ "a": 1 }`, but will *not* match `{ "\u0061": 1 }`.
|
||||||
*
|
*
|
||||||
|
*
|
||||||
|
* You must consume the fields on an object one at a time. A request for a new key
|
||||||
|
* invalidates previous field values: it makes them unsafe. E.g., the array
|
||||||
|
* given by content["bids"].get_array() should not be accessed after you have called
|
||||||
|
* content["asks"].get_array(). You can detect such mistakes by first compiling and running
|
||||||
|
* the code in Debug mode (or with the macro `SIMDJSON_DEVELOPMENT_CHECKS` set to 1): an
|
||||||
|
* OUT_OF_ORDER_ITERATION error is generated.
|
||||||
|
*
|
||||||
|
* You are expected to access keys only once. You should access the value corresponding to
|
||||||
|
* a key a single time. Doing object["mykey"].to_string()and then again object["mykey"].to_string()
|
||||||
|
* is an error.
|
||||||
|
*
|
||||||
* @param key The key to look up.
|
* @param key The key to look up.
|
||||||
* @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
|
* @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
|
||||||
*/
|
*/
|
||||||
@@ -264,6 +340,17 @@ public:
|
|||||||
* Use find_field() if you are sure fields will be in order (or are willing to treat it as if the
|
* Use find_field() if you are sure fields will be in order (or are willing to treat it as if the
|
||||||
* field wasn't there when they aren't).
|
* field wasn't there when they aren't).
|
||||||
*
|
*
|
||||||
|
* You must consume the fields on an object one at a time. A request for a new key
|
||||||
|
* invalidates previous field values: it makes them unsafe. E.g., the array
|
||||||
|
* given by content["bids"].get_array() should not be accessed after you have called
|
||||||
|
* content["asks"].get_array(). You can detect such mistakes by first compiling and running
|
||||||
|
* the code in Debug mode (or with the macro `SIMDJSON_DEVELOPMENT_CHECKS` set to 1): an
|
||||||
|
* OUT_OF_ORDER_ITERATION error is generated.
|
||||||
|
*
|
||||||
|
* You are expected to access keys only once. You should access the value corresponding to a key
|
||||||
|
* a single time. Doing object["mykey"].to_string() and then again object["mykey"].to_string()
|
||||||
|
* is an error.
|
||||||
|
*
|
||||||
* @param key The key to look up.
|
* @param key The key to look up.
|
||||||
* @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
|
* @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
|
||||||
*/
|
*/
|
||||||
@@ -286,6 +373,83 @@ public:
|
|||||||
*/
|
*/
|
||||||
simdjson_really_inline simdjson_result<json_type> type() noexcept;
|
simdjson_really_inline simdjson_result<json_type> type() noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the document is a scalar (string, number, null, Boolean).
|
||||||
|
* Returns false when there it is an array or object.
|
||||||
|
*
|
||||||
|
* @returns true if the type is string, number, null, Boolean
|
||||||
|
* @error TAPE_ERROR when the JSON value is a bad token like "}" "," or "alse".
|
||||||
|
*/
|
||||||
|
simdjson_really_inline simdjson_result<bool> is_scalar() noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the document is a negative number.
|
||||||
|
*
|
||||||
|
* @returns true if the number if negative.
|
||||||
|
*/
|
||||||
|
simdjson_really_inline bool is_negative() noexcept;
|
||||||
|
/**
|
||||||
|
* Checks whether the document is an integer number. Note that
|
||||||
|
* this requires to partially parse the number string. If
|
||||||
|
* the value is determined to be an integer, it may still
|
||||||
|
* not parse properly as an integer in subsequent steps
|
||||||
|
* (e.g., it might overflow).
|
||||||
|
*
|
||||||
|
* @returns true if the number if negative.
|
||||||
|
*/
|
||||||
|
simdjson_really_inline simdjson_result<bool> is_integer() noexcept;
|
||||||
|
/**
|
||||||
|
* Determine the number type (integer or floating-point number) as quickly
|
||||||
|
* as possible. This function does not fully validate the input. It is
|
||||||
|
* useful when you only need to classify the numbers, without parsing them.
|
||||||
|
*
|
||||||
|
* If you are planning to retrieve the value or you need full validation,
|
||||||
|
* consider using the get_number() method instead: it will fully parse
|
||||||
|
* and validate the input, and give you access to the type:
|
||||||
|
* get_number().get_number_type().
|
||||||
|
*
|
||||||
|
* get_number_type() is number_type::unsigned_integer if we have
|
||||||
|
* an integer greater or equal to 9223372036854775808
|
||||||
|
* get_number_type() is number_type::signed_integer if we have an
|
||||||
|
* integer that is less than 9223372036854775808
|
||||||
|
* Otherwise, get_number_type() has value number_type::floating_point_number
|
||||||
|
*
|
||||||
|
* This function requires processing the number string, but it is expected
|
||||||
|
* to be faster than get_number().get_number_type() because it is does not
|
||||||
|
* parse the number value.
|
||||||
|
*
|
||||||
|
* @returns the type of the number
|
||||||
|
*/
|
||||||
|
simdjson_really_inline simdjson_result<number_type> get_number_type() noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempt to parse an ondemand::number. An ondemand::number may
|
||||||
|
* contain an integer value or a floating-point value, the simdjson
|
||||||
|
* library will autodetect the type. Thus it is a dynamically typed
|
||||||
|
* number. Before accessing the value, you must determine the detected
|
||||||
|
* type.
|
||||||
|
*
|
||||||
|
* number.get_number_type() is number_type::signed_integer if we have
|
||||||
|
* an integer in [-9223372036854775808,9223372036854775808)
|
||||||
|
* You can recover the value by calling number.get_int64() and you
|
||||||
|
* have that number.is_int64() is true.
|
||||||
|
*
|
||||||
|
* number.get_number_type() is number_type::unsigned_integer if we have
|
||||||
|
* an integer in [9223372036854775808,18446744073709551616)
|
||||||
|
* You can recover the value by calling number.get_uint64() and you
|
||||||
|
* have that number.is_uint64() is true.
|
||||||
|
*
|
||||||
|
* Otherwise, number.get_number_type() has value number_type::floating_point_number
|
||||||
|
* and we have a binary64 number.
|
||||||
|
* You can recover the value by calling number.get_double() and you
|
||||||
|
* have that number.is_double() is true.
|
||||||
|
*
|
||||||
|
* You must check the type before accessing the value: it is an error
|
||||||
|
* to call "get_int64()" when number.get_number_type() is not
|
||||||
|
* number_type::signed_integer and when number.is_int64() is false.
|
||||||
|
*/
|
||||||
|
simdjson_warn_unused simdjson_really_inline simdjson_result<number> get_number() noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the raw JSON for this token.
|
* Get the raw JSON for this token.
|
||||||
*
|
*
|
||||||
@@ -320,6 +484,27 @@ public:
|
|||||||
* Returns debugging information.
|
* Returns debugging information.
|
||||||
*/
|
*/
|
||||||
inline std::string to_debug_string() noexcept;
|
inline std::string to_debug_string() noexcept;
|
||||||
|
/**
|
||||||
|
* Some unrecoverable error conditions may render the document instance unusable.
|
||||||
|
* The is_alive() method returns true when the document is still suitable.
|
||||||
|
*/
|
||||||
|
inline bool is_alive() noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current location in the document if in bounds.
|
||||||
|
*/
|
||||||
|
inline simdjson_result<const char *> current_location() noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current depth in the document if in bounds.
|
||||||
|
*
|
||||||
|
* E.g.,
|
||||||
|
* 0 = finished with document
|
||||||
|
* 1 = document root value (could be [ or {, not yet known)
|
||||||
|
* 2 = , or } inside root array/object
|
||||||
|
* 3 = key or value inside root array/object.
|
||||||
|
*/
|
||||||
|
simdjson_really_inline int32_t current_depth() const noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the value associated with the given JSON pointer. We use the RFC 6901
|
* Get the value associated with the given JSON pointer. We use the RFC 6901
|
||||||
@@ -350,11 +535,12 @@ public:
|
|||||||
* - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
|
* - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
|
||||||
* - INCORRECT_TYPE if a non-integer is used to access an array
|
* - INCORRECT_TYPE if a non-integer is used to access an array
|
||||||
* - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
|
* - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
|
||||||
|
* - SCALAR_DOCUMENT_AS_VALUE if the json_pointer is empty and the document is not a scalar (see is_scalar() function).
|
||||||
*/
|
*/
|
||||||
simdjson_really_inline simdjson_result<value> at_pointer(std::string_view json_pointer) noexcept;
|
simdjson_really_inline simdjson_result<value> at_pointer(std::string_view json_pointer) noexcept;
|
||||||
/**
|
/**
|
||||||
* Consumes the document and returns a string_view instance corresponding to the
|
* Consumes the document and returns a string_view instance corresponding to the
|
||||||
* document as represented in JSON. It points inside the original byte array containg
|
* document as represented in JSON. It points inside the original byte array containing
|
||||||
* the JSON document.
|
* the JSON document.
|
||||||
*/
|
*/
|
||||||
simdjson_really_inline simdjson_result<std::string_view> raw_json() noexcept;
|
simdjson_really_inline simdjson_result<std::string_view> raw_json() noexcept;
|
||||||
@@ -369,7 +555,6 @@ protected:
|
|||||||
|
|
||||||
simdjson_really_inline value_iterator resume_value_iterator() noexcept;
|
simdjson_really_inline value_iterator resume_value_iterator() noexcept;
|
||||||
simdjson_really_inline value_iterator get_root_value_iterator() noexcept;
|
simdjson_really_inline value_iterator get_root_value_iterator() noexcept;
|
||||||
simdjson_really_inline simdjson_result<value> get_value_unsafe() noexcept;
|
|
||||||
simdjson_really_inline simdjson_result<object> start_or_resume_object() noexcept;
|
simdjson_really_inline simdjson_result<object> start_or_resume_object() noexcept;
|
||||||
static simdjson_really_inline document start(ondemand::json_iterator &&iter) noexcept;
|
static simdjson_really_inline document start(ondemand::json_iterator &&iter) noexcept;
|
||||||
|
|
||||||
@@ -389,6 +574,68 @@ protected:
|
|||||||
friend class document_stream;
|
friend class document_stream;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A document_reference is a thin wrapper around a document reference instance.
|
||||||
|
*/
|
||||||
|
class document_reference {
|
||||||
|
public:
|
||||||
|
simdjson_really_inline document_reference() noexcept;
|
||||||
|
simdjson_really_inline document_reference(document &d) noexcept;
|
||||||
|
simdjson_really_inline document_reference(const document_reference &other) noexcept = default;
|
||||||
|
simdjson_really_inline document_reference& operator=(const document_reference &other) noexcept = default;
|
||||||
|
simdjson_really_inline void rewind() noexcept;
|
||||||
|
simdjson_really_inline simdjson_result<array> get_array() & noexcept;
|
||||||
|
simdjson_really_inline simdjson_result<object> get_object() & noexcept;
|
||||||
|
simdjson_really_inline simdjson_result<uint64_t> get_uint64() noexcept;
|
||||||
|
simdjson_really_inline simdjson_result<int64_t> get_int64() noexcept;
|
||||||
|
simdjson_really_inline simdjson_result<double> get_double() noexcept;
|
||||||
|
simdjson_really_inline simdjson_result<std::string_view> get_string() noexcept;
|
||||||
|
simdjson_really_inline simdjson_result<raw_json_string> get_raw_json_string() noexcept;
|
||||||
|
simdjson_really_inline simdjson_result<bool> get_bool() noexcept;
|
||||||
|
simdjson_really_inline simdjson_result<value> get_value() noexcept;
|
||||||
|
|
||||||
|
simdjson_really_inline bool is_null() noexcept;
|
||||||
|
simdjson_really_inline simdjson_result<std::string_view> raw_json() noexcept;
|
||||||
|
simdjson_really_inline operator document&() const noexcept;
|
||||||
|
|
||||||
|
#if SIMDJSON_EXCEPTIONS
|
||||||
|
simdjson_really_inline operator array() & noexcept(false);
|
||||||
|
simdjson_really_inline operator object() & noexcept(false);
|
||||||
|
simdjson_really_inline operator uint64_t() noexcept(false);
|
||||||
|
simdjson_really_inline operator int64_t() noexcept(false);
|
||||||
|
simdjson_really_inline operator double() noexcept(false);
|
||||||
|
simdjson_really_inline operator std::string_view() noexcept(false);
|
||||||
|
simdjson_really_inline operator raw_json_string() noexcept(false);
|
||||||
|
simdjson_really_inline operator bool() noexcept(false);
|
||||||
|
simdjson_really_inline operator value() noexcept(false);
|
||||||
|
#endif
|
||||||
|
simdjson_really_inline simdjson_result<size_t> count_elements() & noexcept;
|
||||||
|
simdjson_really_inline simdjson_result<size_t> count_fields() & noexcept;
|
||||||
|
simdjson_really_inline simdjson_result<value> at(size_t index) & noexcept;
|
||||||
|
simdjson_really_inline simdjson_result<array_iterator> begin() & noexcept;
|
||||||
|
simdjson_really_inline simdjson_result<array_iterator> end() & noexcept;
|
||||||
|
simdjson_really_inline simdjson_result<value> find_field(std::string_view key) & noexcept;
|
||||||
|
simdjson_really_inline simdjson_result<value> find_field(const char *key) & noexcept;
|
||||||
|
simdjson_really_inline simdjson_result<value> operator[](std::string_view key) & noexcept;
|
||||||
|
simdjson_really_inline simdjson_result<value> operator[](const char *key) & noexcept;
|
||||||
|
simdjson_really_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept;
|
||||||
|
simdjson_really_inline simdjson_result<value> find_field_unordered(const char *key) & noexcept;
|
||||||
|
|
||||||
|
simdjson_really_inline simdjson_result<json_type> type() noexcept;
|
||||||
|
simdjson_really_inline simdjson_result<bool> is_scalar() noexcept;
|
||||||
|
|
||||||
|
simdjson_really_inline simdjson_result<const char *> current_location() noexcept;
|
||||||
|
simdjson_really_inline int32_t current_depth() const noexcept;
|
||||||
|
simdjson_really_inline bool is_negative() noexcept;
|
||||||
|
simdjson_really_inline simdjson_result<bool> is_integer() noexcept;
|
||||||
|
simdjson_really_inline simdjson_result<number_type> get_number_type() noexcept;
|
||||||
|
simdjson_really_inline simdjson_result<number> get_number() noexcept;
|
||||||
|
simdjson_really_inline simdjson_result<std::string_view> raw_json_token() noexcept;
|
||||||
|
simdjson_really_inline simdjson_result<value> at_pointer(std::string_view json_pointer) noexcept;
|
||||||
|
private:
|
||||||
|
document *doc{nullptr};
|
||||||
|
};
|
||||||
} // namespace ondemand
|
} // namespace ondemand
|
||||||
} // namespace SIMDJSON_IMPLEMENTATION
|
} // namespace SIMDJSON_IMPLEMENTATION
|
||||||
} // namespace simdjson
|
} // namespace simdjson
|
||||||
@@ -408,9 +655,11 @@ public:
|
|||||||
simdjson_really_inline simdjson_result<uint64_t> get_uint64() noexcept;
|
simdjson_really_inline simdjson_result<uint64_t> get_uint64() noexcept;
|
||||||
simdjson_really_inline simdjson_result<int64_t> get_int64() noexcept;
|
simdjson_really_inline simdjson_result<int64_t> get_int64() noexcept;
|
||||||
simdjson_really_inline simdjson_result<double> get_double() noexcept;
|
simdjson_really_inline simdjson_result<double> get_double() noexcept;
|
||||||
|
simdjson_really_inline simdjson_result<double> get_double_from_string() noexcept;
|
||||||
simdjson_really_inline simdjson_result<std::string_view> get_string() noexcept;
|
simdjson_really_inline simdjson_result<std::string_view> get_string() noexcept;
|
||||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string> get_raw_json_string() noexcept;
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string> get_raw_json_string() noexcept;
|
||||||
simdjson_really_inline simdjson_result<bool> get_bool() noexcept;
|
simdjson_really_inline simdjson_result<bool> get_bool() noexcept;
|
||||||
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> get_value() noexcept;
|
||||||
simdjson_really_inline bool is_null() noexcept;
|
simdjson_really_inline bool is_null() noexcept;
|
||||||
|
|
||||||
template<typename T> simdjson_really_inline simdjson_result<T> get() & noexcept;
|
template<typename T> simdjson_really_inline simdjson_result<T> get() & noexcept;
|
||||||
@@ -428,8 +677,11 @@ public:
|
|||||||
simdjson_really_inline operator std::string_view() noexcept(false);
|
simdjson_really_inline operator std::string_view() noexcept(false);
|
||||||
simdjson_really_inline operator SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string() noexcept(false);
|
simdjson_really_inline operator SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string() noexcept(false);
|
||||||
simdjson_really_inline operator bool() noexcept(false);
|
simdjson_really_inline operator bool() noexcept(false);
|
||||||
|
simdjson_really_inline operator SIMDJSON_IMPLEMENTATION::ondemand::value() noexcept(false);
|
||||||
#endif
|
#endif
|
||||||
simdjson_really_inline simdjson_result<size_t> count_elements() & noexcept;
|
simdjson_really_inline simdjson_result<size_t> count_elements() & noexcept;
|
||||||
|
simdjson_really_inline simdjson_result<size_t> count_fields() & noexcept;
|
||||||
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> at(size_t index) & noexcept;
|
||||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator> begin() & noexcept;
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator> begin() & noexcept;
|
||||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator> end() & noexcept;
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator> end() & noexcept;
|
||||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field(std::string_view key) & noexcept;
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field(std::string_view key) & noexcept;
|
||||||
@@ -438,13 +690,80 @@ public:
|
|||||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> operator[](const char *key) & noexcept;
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> operator[](const char *key) & noexcept;
|
||||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field_unordered(std::string_view key) & noexcept;
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field_unordered(std::string_view key) & noexcept;
|
||||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field_unordered(const char *key) & noexcept;
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field_unordered(const char *key) & noexcept;
|
||||||
|
|
||||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::json_type> type() noexcept;
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::json_type> type() noexcept;
|
||||||
|
simdjson_really_inline simdjson_result<bool> is_scalar() noexcept;
|
||||||
|
simdjson_really_inline simdjson_result<const char *> current_location() noexcept;
|
||||||
|
simdjson_really_inline int32_t current_depth() const noexcept;
|
||||||
|
simdjson_really_inline bool is_negative() noexcept;
|
||||||
|
simdjson_really_inline simdjson_result<bool> is_integer() noexcept;
|
||||||
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::number_type> get_number_type() noexcept;
|
||||||
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::number> get_number() noexcept;
|
||||||
/** @copydoc simdjson_really_inline std::string_view document::raw_json_token() const noexcept */
|
/** @copydoc simdjson_really_inline std::string_view document::raw_json_token() const noexcept */
|
||||||
simdjson_really_inline simdjson_result<std::string_view> raw_json_token() noexcept;
|
simdjson_really_inline simdjson_result<std::string_view> raw_json_token() noexcept;
|
||||||
|
|
||||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> at_pointer(std::string_view json_pointer) noexcept;
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> at_pointer(std::string_view json_pointer) noexcept;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace simdjson
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
namespace simdjson {
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference> : public SIMDJSON_IMPLEMENTATION::implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::document_reference> {
|
||||||
|
public:
|
||||||
|
simdjson_really_inline simdjson_result(SIMDJSON_IMPLEMENTATION::ondemand::document_reference value, error_code error) noexcept;
|
||||||
|
simdjson_really_inline simdjson_result() noexcept = default;
|
||||||
|
simdjson_really_inline error_code rewind() noexcept;
|
||||||
|
|
||||||
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array> get_array() & noexcept;
|
||||||
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object> get_object() & noexcept;
|
||||||
|
simdjson_really_inline simdjson_result<uint64_t> get_uint64() noexcept;
|
||||||
|
simdjson_really_inline simdjson_result<int64_t> get_int64() noexcept;
|
||||||
|
simdjson_really_inline simdjson_result<double> get_double() noexcept;
|
||||||
|
simdjson_really_inline simdjson_result<std::string_view> get_string() noexcept;
|
||||||
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string> get_raw_json_string() noexcept;
|
||||||
|
simdjson_really_inline simdjson_result<bool> get_bool() noexcept;
|
||||||
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> get_value() noexcept;
|
||||||
|
simdjson_really_inline bool is_null() noexcept;
|
||||||
|
|
||||||
|
#if SIMDJSON_EXCEPTIONS
|
||||||
|
simdjson_really_inline operator SIMDJSON_IMPLEMENTATION::ondemand::array() & noexcept(false);
|
||||||
|
simdjson_really_inline operator SIMDJSON_IMPLEMENTATION::ondemand::object() & noexcept(false);
|
||||||
|
simdjson_really_inline operator uint64_t() noexcept(false);
|
||||||
|
simdjson_really_inline operator int64_t() noexcept(false);
|
||||||
|
simdjson_really_inline operator double() noexcept(false);
|
||||||
|
simdjson_really_inline operator std::string_view() noexcept(false);
|
||||||
|
simdjson_really_inline operator SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string() noexcept(false);
|
||||||
|
simdjson_really_inline operator bool() noexcept(false);
|
||||||
|
simdjson_really_inline operator SIMDJSON_IMPLEMENTATION::ondemand::value() noexcept(false);
|
||||||
|
#endif
|
||||||
|
simdjson_really_inline simdjson_result<size_t> count_elements() & noexcept;
|
||||||
|
simdjson_really_inline simdjson_result<size_t> count_fields() & noexcept;
|
||||||
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> at(size_t index) & noexcept;
|
||||||
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator> begin() & noexcept;
|
||||||
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator> end() & noexcept;
|
||||||
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field(std::string_view key) & noexcept;
|
||||||
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field(const char *key) & noexcept;
|
||||||
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> operator[](std::string_view key) & noexcept;
|
||||||
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> operator[](const char *key) & noexcept;
|
||||||
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field_unordered(std::string_view key) & noexcept;
|
||||||
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field_unordered(const char *key) & noexcept;
|
||||||
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::json_type> type() noexcept;
|
||||||
|
simdjson_really_inline simdjson_result<bool> is_scalar() noexcept;
|
||||||
|
simdjson_really_inline simdjson_result<const char *> current_location() noexcept;
|
||||||
|
simdjson_really_inline int32_t current_depth() const noexcept;
|
||||||
|
simdjson_really_inline bool is_negative() noexcept;
|
||||||
|
simdjson_really_inline simdjson_result<bool> is_integer() noexcept;
|
||||||
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::number_type> get_number_type() noexcept;
|
||||||
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::number> get_number() noexcept;
|
||||||
|
/** @copydoc simdjson_really_inline std::string_view document_reference::raw_json_token() const noexcept */
|
||||||
|
simdjson_really_inline simdjson_result<std::string_view> raw_json_token() noexcept;
|
||||||
|
|
||||||
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> at_pointer(std::string_view json_pointer) noexcept;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace simdjson
|
} // namespace simdjson
|
||||||
@@ -126,6 +126,7 @@ inline size_t document_stream::size_in_bytes() const noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline size_t document_stream::truncated_bytes() const noexcept {
|
inline size_t document_stream::truncated_bytes() const noexcept {
|
||||||
|
if(error == CAPACITY) { return len - batch_start; }
|
||||||
return parser->implementation->structural_indexes[parser->implementation->n_structural_indexes] - parser->implementation->structural_indexes[parser->implementation->n_structural_indexes + 1];
|
return parser->implementation->structural_indexes[parser->implementation->n_structural_indexes] - parser->implementation->structural_indexes[parser->implementation->n_structural_indexes + 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,8 +138,9 @@ simdjson_really_inline document_stream::iterator::iterator(document_stream* _str
|
|||||||
: stream{_stream}, finished{is_end} {
|
: stream{_stream}, finished{is_end} {
|
||||||
}
|
}
|
||||||
|
|
||||||
simdjson_really_inline ondemand::document& document_stream::iterator::operator*() noexcept {
|
simdjson_really_inline simdjson_result<ondemand::document_reference> document_stream::iterator::operator*() noexcept {
|
||||||
return stream->doc;
|
//if(stream->error) { return stream->error; }
|
||||||
|
return simdjson_result<ondemand::document_reference>(stream->doc, stream->error);
|
||||||
}
|
}
|
||||||
|
|
||||||
simdjson_really_inline document_stream::iterator& document_stream::iterator::operator++() noexcept {
|
simdjson_really_inline document_stream::iterator& document_stream::iterator::operator++() noexcept {
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Get the current document (or error).
|
* Get the current document (or error).
|
||||||
*/
|
*/
|
||||||
simdjson_really_inline ondemand::document& operator*() noexcept;
|
simdjson_really_inline simdjson_result<ondemand::document_reference> operator*() noexcept;
|
||||||
/**
|
/**
|
||||||
* Advance to the next document (prefix).
|
* Advance to the next document (prefix).
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -35,7 +35,9 @@ simdjson_really_inline json_iterator::json_iterator(const uint8_t *buf, ondemand
|
|||||||
|
|
||||||
{
|
{
|
||||||
logger::log_headers();
|
logger::log_headers();
|
||||||
|
#if SIMDJSON_CHECK_EOF
|
||||||
assert_more_tokens();
|
assert_more_tokens();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void json_iterator::rewind() noexcept {
|
inline void json_iterator::rewind() noexcept {
|
||||||
@@ -51,17 +53,6 @@ inline void json_iterator::rewind() noexcept {
|
|||||||
SIMDJSON_PUSH_DISABLE_WARNINGS
|
SIMDJSON_PUSH_DISABLE_WARNINGS
|
||||||
SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING
|
SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING
|
||||||
simdjson_warn_unused simdjson_really_inline error_code json_iterator::skip_child(depth_t parent_depth) noexcept {
|
simdjson_warn_unused simdjson_really_inline error_code json_iterator::skip_child(depth_t parent_depth) noexcept {
|
||||||
/***
|
|
||||||
* WARNING:
|
|
||||||
* Inside an object, a string value is a depth of +1 compared to the object. Yet a key
|
|
||||||
* is at the same depth as the object.
|
|
||||||
* But json_iterator cannot easily tell whether we are pointing at a key or a string value.
|
|
||||||
* Instead, it assumes that if you are pointing at a string, then it is a value, not a key.
|
|
||||||
* To be clear...
|
|
||||||
* the following code assumes that we are *not* pointing at a key. If we are then a bug
|
|
||||||
* will follow. Unfortunately, it is not possible for the json_iterator its to make this
|
|
||||||
* check.
|
|
||||||
*/
|
|
||||||
if (depth() <= parent_depth) { return SUCCESS; }
|
if (depth() <= parent_depth) { return SUCCESS; }
|
||||||
switch (*return_current_and_advance()) {
|
switch (*return_current_and_advance()) {
|
||||||
// TODO consider whether matching braces is a requirement: if non-matching braces indicates
|
// TODO consider whether matching braces is a requirement: if non-matching braces indicates
|
||||||
@@ -84,24 +75,23 @@ simdjson_warn_unused simdjson_really_inline error_code json_iterator::skip_child
|
|||||||
logger::log_end_value(*this, "skip");
|
logger::log_end_value(*this, "skip");
|
||||||
_depth--;
|
_depth--;
|
||||||
if (depth() <= parent_depth) { return SUCCESS; }
|
if (depth() <= parent_depth) { return SUCCESS; }
|
||||||
#if __SIMDJSON_CHECK_EOF
|
#if SIMDJSON_CHECK_EOF
|
||||||
// If there are no more tokens, the parent is incomplete.
|
// If there are no more tokens, the parent is incomplete.
|
||||||
if (at_end()) { return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "Missing [ or { at start"); }
|
if (at_end()) { return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "Missing [ or { at start"); }
|
||||||
#endif // __SIMDJSON_CHECK_EOF
|
#endif // SIMDJSON_CHECK_EOF
|
||||||
break;
|
break;
|
||||||
/*case '"':
|
case '"':
|
||||||
if(*peek() == ':') {
|
if(*peek() == ':') {
|
||||||
// we are at a key!!! This is
|
// We are at a key!!!
|
||||||
// only possible if someone searched
|
// This might happen if you just started an object and you skip it immediately.
|
||||||
// for a key in an object and the key
|
// Performance note: it would be nice to get rid of this check as it is somewhat
|
||||||
// was not found but our code then
|
// expensive.
|
||||||
// decided the consume the separating
|
// https://github.com/simdjson/simdjson/issues/1742
|
||||||
// comma before returning.
|
|
||||||
logger::log_value(*this, "key");
|
logger::log_value(*this, "key");
|
||||||
advance(); // eat up the ':'
|
return_current_and_advance(); // eat up the ':'
|
||||||
break; // important!!!
|
break; // important!!!
|
||||||
}
|
}
|
||||||
simdjson_fallthrough;*/
|
simdjson_fallthrough;
|
||||||
// Anything else must be a scalar value
|
// Anything else must be a scalar value
|
||||||
default:
|
default:
|
||||||
// For the first scalar, we will have incremented depth already, so we decrement it here.
|
// For the first scalar, we will have incremented depth already, so we decrement it here.
|
||||||
@@ -151,6 +141,10 @@ simdjson_really_inline token_position json_iterator::root_position() const noexc
|
|||||||
return _root;
|
return _root;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
simdjson_really_inline void json_iterator::assert_at_document_depth() const noexcept {
|
||||||
|
SIMDJSON_ASSUME( _depth == 1 );
|
||||||
|
}
|
||||||
|
|
||||||
simdjson_really_inline void json_iterator::assert_at_root() const noexcept {
|
simdjson_really_inline void json_iterator::assert_at_root() const noexcept {
|
||||||
SIMDJSON_ASSUME( _depth == 1 );
|
SIMDJSON_ASSUME( _depth == 1 );
|
||||||
#ifndef SIMDJSON_CLANG_VISUAL_STUDIO
|
#ifndef SIMDJSON_CLANG_VISUAL_STUDIO
|
||||||
@@ -189,6 +183,20 @@ inline std::string json_iterator::to_string() const noexcept {
|
|||||||
+ std::string(" ]");
|
+ std::string(" ]");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline simdjson_result<const char *> json_iterator::current_location() noexcept {
|
||||||
|
if (!is_alive()) { // Unrecoverable error
|
||||||
|
if (!at_root()) {
|
||||||
|
return reinterpret_cast<const char *>(token.peek(-1));
|
||||||
|
} else {
|
||||||
|
return reinterpret_cast<const char *>(token.peek());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (at_end()) {
|
||||||
|
return OUT_OF_BOUNDS;
|
||||||
|
}
|
||||||
|
return reinterpret_cast<const char *>(token.peek());
|
||||||
|
}
|
||||||
|
|
||||||
simdjson_really_inline bool json_iterator::is_alive() const noexcept {
|
simdjson_really_inline bool json_iterator::is_alive() const noexcept {
|
||||||
return parser;
|
return parser;
|
||||||
}
|
}
|
||||||
@@ -199,23 +207,28 @@ simdjson_really_inline void json_iterator::abandon() noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
simdjson_really_inline const uint8_t *json_iterator::return_current_and_advance() noexcept {
|
simdjson_really_inline const uint8_t *json_iterator::return_current_and_advance() noexcept {
|
||||||
// The following assert_more_tokens is currently disabled because rely on end-of-file buffering.
|
#if SIMDJSON_CHECK_EOF
|
||||||
// assert_more_tokens();
|
assert_more_tokens();
|
||||||
// This is almost surely related to __SIMDJSON_CHECK_EOF but given that __SIMDJSON_CHECK_EOF
|
#endif // SIMDJSON_CHECK_EOF
|
||||||
// is ON by default, we have no choice but to disable it for real with a comment.
|
|
||||||
return token.return_current_and_advance();
|
return token.return_current_and_advance();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
simdjson_really_inline const uint8_t *json_iterator::unsafe_pointer() const noexcept {
|
||||||
|
// deliberately done without safety guard:
|
||||||
|
return token.peek(0);
|
||||||
|
}
|
||||||
|
|
||||||
simdjson_really_inline const uint8_t *json_iterator::peek(int32_t delta) const noexcept {
|
simdjson_really_inline const uint8_t *json_iterator::peek(int32_t delta) const noexcept {
|
||||||
// The following assert_more_tokens is currently disabled because rely on end-of-file buffering.
|
#if SIMDJSON_CHECK_EOF
|
||||||
// assert_more_tokens(delta+1);
|
assert_more_tokens(delta+1);
|
||||||
// This is almost surely related to __SIMDJSON_CHECK_EOF but given that __SIMDJSON_CHECK_EOF
|
#endif // SIMDJSON_CHECK_EOF
|
||||||
// is ON by default, we have no choice but to disable it for real with a comment.
|
|
||||||
return token.peek(delta);
|
return token.peek(delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
simdjson_really_inline uint32_t json_iterator::peek_length(int32_t delta) const noexcept {
|
simdjson_really_inline uint32_t json_iterator::peek_length(int32_t delta) const noexcept {
|
||||||
|
#if SIMDJSON_CHECK_EOF
|
||||||
assert_more_tokens(delta+1);
|
assert_more_tokens(delta+1);
|
||||||
|
#endif // #if SIMDJSON_CHECK_EOF
|
||||||
return token.peek_length(delta);
|
return token.peek_length(delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -223,17 +236,15 @@ simdjson_really_inline const uint8_t *json_iterator::peek(token_position positio
|
|||||||
// todo: currently we require end-of-string buffering, but the following
|
// todo: currently we require end-of-string buffering, but the following
|
||||||
// assert_valid_position should be turned on if/when we lift that condition.
|
// assert_valid_position should be turned on if/when we lift that condition.
|
||||||
// assert_valid_position(position);
|
// assert_valid_position(position);
|
||||||
// This is almost surely related to __SIMDJSON_CHECK_EOF but given that __SIMDJSON_CHECK_EOF
|
// This is almost surely related to SIMDJSON_CHECK_EOF but given that SIMDJSON_CHECK_EOF
|
||||||
// is ON by default, we have no choice but to disable it for real with a comment.
|
// is ON by default, we have no choice but to disable it for real with a comment.
|
||||||
return token.peek(position);
|
return token.peek(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
simdjson_really_inline uint32_t json_iterator::peek_length(token_position position) const noexcept {
|
simdjson_really_inline uint32_t json_iterator::peek_length(token_position position) const noexcept {
|
||||||
// todo: currently we require end-of-string buffering, but the following
|
#if SIMDJSON_CHECK_EOF
|
||||||
// assert_valid_position should be turned on if/when we lift that condition.
|
assert_valid_position(position);
|
||||||
// assert_valid_position(position);
|
#endif // SIMDJSON_CHECK_EOF
|
||||||
// This is almost surely related to __SIMDJSON_CHECK_EOF but given that __SIMDJSON_CHECK_EOF
|
|
||||||
// is ON by default, we have no choice but to disable it for real with a comment.
|
|
||||||
return token.peek_length(position);
|
return token.peek_length(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -88,9 +88,12 @@ public:
|
|||||||
* Get the root value iterator
|
* Get the root value iterator
|
||||||
*/
|
*/
|
||||||
simdjson_really_inline token_position root_position() const noexcept;
|
simdjson_really_inline token_position root_position() const noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Assert if the iterator is not at the start
|
* Assert that we are at the document depth (== 1)
|
||||||
|
*/
|
||||||
|
simdjson_really_inline void assert_at_document_depth() const noexcept;
|
||||||
|
/**
|
||||||
|
* Assert that we are at the root of the document
|
||||||
*/
|
*/
|
||||||
simdjson_really_inline void assert_at_root() const noexcept;
|
simdjson_really_inline void assert_at_root() const noexcept;
|
||||||
|
|
||||||
@@ -145,12 +148,21 @@ public:
|
|||||||
* @param delta The relative position of the token to retrieve. e.g. 0 = next token, -1 = prev token.
|
* @param delta The relative position of the token to retrieve. e.g. 0 = next token, -1 = prev token.
|
||||||
*/
|
*/
|
||||||
simdjson_really_inline uint32_t peek_length(int32_t delta=0) const noexcept;
|
simdjson_really_inline uint32_t peek_length(int32_t delta=0) const noexcept;
|
||||||
|
/**
|
||||||
|
* Get a pointer to the current location in the input buffer.
|
||||||
|
*
|
||||||
|
* This is not null-terminated; it is a view into the JSON.
|
||||||
|
*
|
||||||
|
* You may be pointing outside of the input buffer: it is not generally
|
||||||
|
* safe to dereference this pointer.
|
||||||
|
*/
|
||||||
|
simdjson_really_inline const uint8_t *unsafe_pointer() const noexcept;
|
||||||
/**
|
/**
|
||||||
* Get the JSON text for a given token.
|
* Get the JSON text for a given token.
|
||||||
*
|
*
|
||||||
* This is not null-terminated; it is a view into the JSON.
|
* This is not null-terminated; it is a view into the JSON.
|
||||||
*
|
*
|
||||||
* @param index The position of the token to retrieve.
|
* @param position The position of the token to retrieve.
|
||||||
*
|
*
|
||||||
* TODO consider a string_view, assuming the length will get stripped out by the optimizer when
|
* TODO consider a string_view, assuming the length will get stripped out by the optimizer when
|
||||||
* it isn't used ...
|
* it isn't used ...
|
||||||
@@ -161,7 +173,7 @@ public:
|
|||||||
*
|
*
|
||||||
* The length will include any whitespace at the end of the token.
|
* The length will include any whitespace at the end of the token.
|
||||||
*
|
*
|
||||||
* @param index The position of the token to retrieve.
|
* @param position The position of the token to retrieve.
|
||||||
*/
|
*/
|
||||||
simdjson_really_inline uint32_t peek_length(token_position position) const noexcept;
|
simdjson_really_inline uint32_t peek_length(token_position position) const noexcept;
|
||||||
/**
|
/**
|
||||||
@@ -204,7 +216,7 @@ public:
|
|||||||
simdjson_really_inline uint8_t *&string_buf_loc() noexcept;
|
simdjson_really_inline uint8_t *&string_buf_loc() noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Report an error, preventing further iteration.
|
* Report an unrecoverable error, preventing further iteration.
|
||||||
*
|
*
|
||||||
* @param error The error to report. Must not be SUCCESS, UNINITIALIZED, INCORRECT_TYPE, or NO_SUCH_FIELD.
|
* @param error The error to report. Must not be SUCCESS, UNINITIALIZED, INCORRECT_TYPE, or NO_SUCH_FIELD.
|
||||||
* @param message An error message to report with the error.
|
* @param message An error message to report with the error.
|
||||||
@@ -228,6 +240,12 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
/* Useful for debugging and logging purposes. */
|
/* Useful for debugging and logging purposes. */
|
||||||
inline std::string to_string() const noexcept;
|
inline std::string to_string() const noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current location in the document if in bounds.
|
||||||
|
*/
|
||||||
|
inline simdjson_result<const char *> current_location() noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates this json iterator so that it is back at the beginning of the document,
|
* Updates this json iterator so that it is back at the beginning of the document,
|
||||||
* as if it had just been created.
|
* as if it had just been created.
|
||||||
|
|||||||
@@ -15,12 +15,93 @@ inline std::ostream& operator<<(std::ostream& out, json_type type) noexcept {
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline std::ostream& operator<<(std::ostream& out, number_type type) noexcept {
|
||||||
|
switch (type) {
|
||||||
|
case number_type::signed_integer: out << "integer in [-9223372036854775808,9223372036854775808)"; break;
|
||||||
|
case number_type::unsigned_integer: out << "unsigned integer in [9223372036854775808,18446744073709551616)"; break;
|
||||||
|
case number_type::floating_point_number: out << "floating-point number (binary64)"; break;
|
||||||
|
default: SIMDJSON_UNREACHABLE();
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
#if SIMDJSON_EXCEPTIONS
|
#if SIMDJSON_EXCEPTIONS
|
||||||
inline std::ostream& operator<<(std::ostream& out, simdjson_result<json_type> &type) noexcept(false) {
|
inline std::ostream& operator<<(std::ostream& out, simdjson_result<json_type> &type) noexcept(false) {
|
||||||
return out << type.value();
|
return out << type.value();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
simdjson_really_inline number_type number::get_number_type() const noexcept {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
simdjson_really_inline bool number::is_uint64() const noexcept {
|
||||||
|
return get_number_type() == number_type::unsigned_integer;
|
||||||
|
}
|
||||||
|
|
||||||
|
simdjson_really_inline uint64_t number::get_uint64() const noexcept {
|
||||||
|
return payload.unsigned_integer;
|
||||||
|
}
|
||||||
|
|
||||||
|
simdjson_really_inline number::operator uint64_t() const noexcept {
|
||||||
|
return get_uint64();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
simdjson_really_inline bool number::is_int64() const noexcept {
|
||||||
|
return get_number_type() == number_type::signed_integer;
|
||||||
|
}
|
||||||
|
|
||||||
|
simdjson_really_inline int64_t number::get_int64() const noexcept {
|
||||||
|
return payload.signed_integer;
|
||||||
|
}
|
||||||
|
|
||||||
|
simdjson_really_inline number::operator int64_t() const noexcept {
|
||||||
|
return get_int64();
|
||||||
|
}
|
||||||
|
|
||||||
|
simdjson_really_inline bool number::is_double() const noexcept {
|
||||||
|
return get_number_type() == number_type::floating_point_number;
|
||||||
|
}
|
||||||
|
|
||||||
|
simdjson_really_inline double number::get_double() const noexcept {
|
||||||
|
return payload.floating_point_number;
|
||||||
|
}
|
||||||
|
|
||||||
|
simdjson_really_inline number::operator double() const noexcept {
|
||||||
|
return get_double();
|
||||||
|
}
|
||||||
|
|
||||||
|
simdjson_really_inline double number::as_double() const noexcept {
|
||||||
|
if(is_double()) {
|
||||||
|
return payload.floating_point_number;
|
||||||
|
}
|
||||||
|
if(is_int64()) {
|
||||||
|
return double(payload.signed_integer);
|
||||||
|
}
|
||||||
|
return double(payload.unsigned_integer);
|
||||||
|
}
|
||||||
|
|
||||||
|
simdjson_really_inline void number::append_s64(int64_t value) noexcept {
|
||||||
|
payload.signed_integer = value;
|
||||||
|
type = number_type::signed_integer;
|
||||||
|
}
|
||||||
|
|
||||||
|
simdjson_really_inline void number::append_u64(uint64_t value) noexcept {
|
||||||
|
payload.unsigned_integer = value;
|
||||||
|
type = number_type::unsigned_integer;
|
||||||
|
}
|
||||||
|
|
||||||
|
simdjson_really_inline void number::append_double(double value) noexcept {
|
||||||
|
payload.floating_point_number = value;
|
||||||
|
type = number_type::floating_point_number;
|
||||||
|
}
|
||||||
|
|
||||||
|
simdjson_really_inline void number::skip_double() noexcept {
|
||||||
|
type = number_type::floating_point_number;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ondemand
|
} // namespace ondemand
|
||||||
} // namespace SIMDJSON_IMPLEMENTATION
|
} // namespace SIMDJSON_IMPLEMENTATION
|
||||||
} // namespace simdjson
|
} // namespace simdjson
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
namespace simdjson {
|
namespace simdjson {
|
||||||
namespace SIMDJSON_IMPLEMENTATION {
|
namespace SIMDJSON_IMPLEMENTATION {
|
||||||
namespace ondemand {
|
namespace ondemand {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The type of a JSON value.
|
* The type of a JSON value.
|
||||||
*/
|
*/
|
||||||
@@ -15,6 +14,105 @@ enum class json_type {
|
|||||||
null ///< A JSON null (null)
|
null ///< A JSON null (null)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class value_iterator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A type representing a JSON number.
|
||||||
|
* The design of the struct is deliberately straight-forward. All
|
||||||
|
* functions return standard values with no error check.
|
||||||
|
*/
|
||||||
|
struct number {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* return the automatically determined type of
|
||||||
|
* the number: number_type::floating_point_number,
|
||||||
|
* number_type::signed_integer or number_type::unsigned_integer.
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
* };
|
||||||
|
*/
|
||||||
|
simdjson_really_inline number_type get_number_type() const noexcept;
|
||||||
|
/**
|
||||||
|
* return true if the automatically determined type of
|
||||||
|
* the number is number_type::unsigned_integer.
|
||||||
|
*/
|
||||||
|
simdjson_really_inline bool is_uint64() const noexcept;
|
||||||
|
/**
|
||||||
|
* return the value as a uint64_t, only valid if is_uint64() is true.
|
||||||
|
*/
|
||||||
|
simdjson_really_inline uint64_t get_uint64() const noexcept;
|
||||||
|
simdjson_really_inline operator uint64_t() const noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* return true if the automatically determined type of
|
||||||
|
* the number is number_type::signed_integer.
|
||||||
|
*/
|
||||||
|
simdjson_really_inline bool is_int64() const noexcept;
|
||||||
|
/**
|
||||||
|
* return the value as a int64_t, only valid if is_int64() is true.
|
||||||
|
*/
|
||||||
|
simdjson_really_inline int64_t get_int64() const noexcept;
|
||||||
|
simdjson_really_inline operator int64_t() const noexcept;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* return true if the automatically determined type of
|
||||||
|
* the number is number_type::floating_point_number.
|
||||||
|
*/
|
||||||
|
simdjson_really_inline bool is_double() const noexcept;
|
||||||
|
/**
|
||||||
|
* return the value as a double, only valid if is_double() is true.
|
||||||
|
*/
|
||||||
|
simdjson_really_inline double get_double() const noexcept;
|
||||||
|
simdjson_really_inline operator double() const noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert the number to a double. Though it always succeed, the conversion
|
||||||
|
* may be lossy if the number cannot be represented exactly.
|
||||||
|
*/
|
||||||
|
simdjson_really_inline double as_double() const noexcept;
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/**
|
||||||
|
* The next block of declaration is designed so that we can call the number parsing
|
||||||
|
* functions on a number type. They are protected and should never be used outside
|
||||||
|
* of the core simdjson library.
|
||||||
|
*/
|
||||||
|
friend class value_iterator;
|
||||||
|
template<typename W>
|
||||||
|
friend error_code numberparsing::write_float(const uint8_t *const src, bool negative, uint64_t i, const uint8_t * start_digits, size_t digit_count, int64_t exponent, W &writer);
|
||||||
|
template<typename W>
|
||||||
|
friend error_code numberparsing::parse_number(const uint8_t *const src, W &writer);
|
||||||
|
template<typename W>
|
||||||
|
friend error_code numberparsing::slow_float_parsing(simdjson_unused const uint8_t * src, W writer);
|
||||||
|
/** Store a signed 64-bit value to the number. */
|
||||||
|
simdjson_really_inline void append_s64(int64_t value) noexcept;
|
||||||
|
/** Store an unsigned 64-bit value to the number. */
|
||||||
|
simdjson_really_inline void append_u64(uint64_t value) noexcept;
|
||||||
|
/** Store a double value to the number. */
|
||||||
|
simdjson_really_inline void append_double(double value) noexcept;
|
||||||
|
/** Specifies that the value is a double, but leave it undefined. */
|
||||||
|
simdjson_really_inline void skip_double() noexcept;
|
||||||
|
/**
|
||||||
|
* End of friend declarations.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Our attributes are a union type (size = 64 bits)
|
||||||
|
* followed by a type indicator.
|
||||||
|
*/
|
||||||
|
union {
|
||||||
|
double floating_point_number;
|
||||||
|
int64_t signed_integer;
|
||||||
|
uint64_t unsigned_integer;
|
||||||
|
} payload{0};
|
||||||
|
number_type type{number_type::signed_integer};
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write the JSON type to the output stream
|
* Write the JSON type to the output stream
|
||||||
*
|
*
|
||||||
@@ -22,6 +120,7 @@ enum class json_type {
|
|||||||
* @param type The json_type.
|
* @param type The json_type.
|
||||||
*/
|
*/
|
||||||
inline std::ostream& operator<<(std::ostream& out, json_type type) noexcept;
|
inline std::ostream& operator<<(std::ostream& out, json_type type) noexcept;
|
||||||
|
inline std::ostream& operator<<(std::ostream& out, number_type type) noexcept;
|
||||||
|
|
||||||
#if SIMDJSON_EXCEPTIONS
|
#if SIMDJSON_EXCEPTIONS
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ inline void log_headers() noexcept {
|
|||||||
printf("# skip says 'this is a structural or value I am skipping'\n");
|
printf("# skip says 'this is a structural or value I am skipping'\n");
|
||||||
printf("# +/-skip says 'this is a start/end array or object I am skipping'\n");
|
printf("# +/-skip says 'this is a start/end array or object I am skipping'\n");
|
||||||
printf("#\n");
|
printf("#\n");
|
||||||
printf("# The identation of the terms (array, string,...) indicates the depth,\n");
|
printf("# The indentation of the terms (array, string,...) indicates the depth,\n");
|
||||||
printf("# in addition to the depth being displayed.\n");
|
printf("# in addition to the depth being displayed.\n");
|
||||||
printf("#\n");
|
printf("#\n");
|
||||||
printf("# Every token in the document has a single depth determined by the tokens before it,\n");
|
printf("# Every token in the document has a single depth determined by the tokens before it,\n");
|
||||||
|
|||||||
@@ -139,6 +139,29 @@ inline simdjson_result<value> object::at_pointer(std::string_view json_pointer)
|
|||||||
return child;
|
return child;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
simdjson_really_inline simdjson_result<size_t> object::count_fields() & noexcept {
|
||||||
|
size_t count{0};
|
||||||
|
// Important: we do not consume any of the values.
|
||||||
|
for(simdjson_unused auto v : *this) { count++; }
|
||||||
|
// The above loop will always succeed, but we want to report errors.
|
||||||
|
if(iter.error()) { return iter.error(); }
|
||||||
|
// We need to move back at the start because we expect users to iterate through
|
||||||
|
// the object after counting the number of elements.
|
||||||
|
iter.reset_object();
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
simdjson_really_inline simdjson_result<bool> object::is_empty() & noexcept {
|
||||||
|
bool is_not_empty;
|
||||||
|
auto error = iter.reset_object().get(is_not_empty);
|
||||||
|
if(error) { return error; }
|
||||||
|
return !is_not_empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
simdjson_really_inline simdjson_result<bool> object::reset() & noexcept {
|
||||||
|
return iter.reset_object();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ondemand
|
} // namespace ondemand
|
||||||
} // namespace SIMDJSON_IMPLEMENTATION
|
} // namespace SIMDJSON_IMPLEMENTATION
|
||||||
} // namespace simdjson
|
} // namespace simdjson
|
||||||
@@ -188,4 +211,19 @@ simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>
|
|||||||
return first.at_pointer(json_pointer);
|
return first.at_pointer(json_pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline simdjson_result<bool> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object>::reset() noexcept {
|
||||||
|
if (error()) { return error(); }
|
||||||
|
return first.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline simdjson_result<bool> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object>::is_empty() noexcept {
|
||||||
|
if (error()) { return error(); }
|
||||||
|
return first.is_empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
simdjson_really_inline simdjson_result<size_t> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object>::count_fields() & noexcept {
|
||||||
|
if (error()) { return error(); }
|
||||||
|
return first.count_fields();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace simdjson
|
} // namespace simdjson
|
||||||
|
|||||||
@@ -37,6 +37,17 @@ public:
|
|||||||
* **Raw Keys:** The lookup will be done against the *raw* key, and will not unescape keys.
|
* **Raw Keys:** The lookup will be done against the *raw* key, and will not unescape keys.
|
||||||
* e.g. `object["a"]` will match `{ "a": 1 }`, but will *not* match `{ "\u0061": 1 }`.
|
* e.g. `object["a"]` will match `{ "a": 1 }`, but will *not* match `{ "\u0061": 1 }`.
|
||||||
*
|
*
|
||||||
|
* You must consume the fields on an object one at a time. A request for a new key
|
||||||
|
* invalidates previous field values: it makes them unsafe. E.g., the array
|
||||||
|
* given by content["bids"].get_array() should not be accessed after you have called
|
||||||
|
* content["asks"].get_array(). You can detect such mistakes by first compiling and running
|
||||||
|
* the code in Debug mode (or with the macro `SIMDJSON_DEVELOPMENT_CHECKS` set to 1): an
|
||||||
|
* OUT_OF_ORDER_ITERATION error is generated.
|
||||||
|
*
|
||||||
|
* You are expected to access keys only once. You should access the value corresponding to a
|
||||||
|
* key a single time. Doing object["mykey"].to_string() and then again object["mykey"].to_string()
|
||||||
|
* is an error.
|
||||||
|
*
|
||||||
* @param key The key to look up.
|
* @param key The key to look up.
|
||||||
* @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
|
* @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
|
||||||
*/
|
*/
|
||||||
@@ -63,6 +74,16 @@ public:
|
|||||||
* If you have multiple fields with a matching key ({"x": 1, "x": 1}) be mindful
|
* If you have multiple fields with a matching key ({"x": 1, "x": 1}) be mindful
|
||||||
* that only one field is returned.
|
* that only one field is returned.
|
||||||
*
|
*
|
||||||
|
* You must consume the fields on an object one at a time. A request for a new key
|
||||||
|
* invalidates previous field values: it makes them unsafe. E.g., the array
|
||||||
|
* given by content["bids"].get_array() should not be accessed after you have called
|
||||||
|
* content["asks"].get_array(). You can detect such mistakes by first compiling and running
|
||||||
|
* the code in Debug mode (or with the macro `SIMDJSON_DEVELOPMENT_CHECKS` set to 1): an
|
||||||
|
* OUT_OF_ORDER_ITERATION error is generated.
|
||||||
|
*
|
||||||
|
* You are expected to access keys only once. You should access the value corresponding to a key
|
||||||
|
* a single time. Doing object["mykey"].to_string() and then again object["mykey"].to_string() is an error.
|
||||||
|
*
|
||||||
* @param key The key to look up.
|
* @param key The key to look up.
|
||||||
* @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
|
* @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
|
||||||
*/
|
*/
|
||||||
@@ -97,7 +118,7 @@ public:
|
|||||||
* instance: there is no rewind and no invalidation.
|
* instance: there is no rewind and no invalidation.
|
||||||
*
|
*
|
||||||
* You may call at_pointer more than once on an object, but each time the pointer is advanced
|
* You may call at_pointer more than once on an object, but each time the pointer is advanced
|
||||||
* to be within the value matched by the key indicated by the JSON pointer query. Thus any preceeding
|
* to be within the value matched by the key indicated by the JSON pointer query. Thus any preceding
|
||||||
* key (as well as the current key) can no longer be used with following JSON pointer calls.
|
* key (as well as the current key) can no longer be used with following JSON pointer calls.
|
||||||
*
|
*
|
||||||
* Also note that at_pointer() relies on find_field() which implies that we do not unescape keys when matching.
|
* Also note that at_pointer() relies on find_field() which implies that we do not unescape keys when matching.
|
||||||
@@ -110,9 +131,44 @@ public:
|
|||||||
*/
|
*/
|
||||||
inline simdjson_result<value> at_pointer(std::string_view json_pointer) noexcept;
|
inline simdjson_result<value> at_pointer(std::string_view json_pointer) noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the iterator so that we are pointing back at the
|
||||||
|
* beginning of the object. You should still consume values only once even if you
|
||||||
|
* can iterate through the object more than once. If you unescape a string within
|
||||||
|
* the object more than once, you have unsafe code. Note that rewinding an object
|
||||||
|
* means that you may need to reparse it anew: it is not a free operation.
|
||||||
|
*
|
||||||
|
* @returns true if the object contains some elements (not empty)
|
||||||
|
*/
|
||||||
|
inline simdjson_result<bool> reset() & noexcept;
|
||||||
|
/**
|
||||||
|
* This method scans the beginning of the object and checks whether the
|
||||||
|
* object is empty.
|
||||||
|
* The runtime complexity is constant time. After
|
||||||
|
* calling this function, if successful, the object is 'rewinded' at its
|
||||||
|
* beginning as if it had never been accessed. If the JSON is malformed (e.g.,
|
||||||
|
* there is a missing comma), then an error is returned and it is no longer
|
||||||
|
* safe to continue.
|
||||||
|
*/
|
||||||
|
inline simdjson_result<bool> is_empty() & noexcept;
|
||||||
|
/**
|
||||||
|
* This method scans the object and counts the number of key-value pairs.
|
||||||
|
* The count_fields method should always be called before you have begun
|
||||||
|
* iterating through the object: it is expected that you are pointing at
|
||||||
|
* the beginning of the object.
|
||||||
|
* The runtime complexity is linear in the size of the object. After
|
||||||
|
* calling this function, if successful, the object is 'rewinded' at its
|
||||||
|
* beginning as if it had never been accessed. If the JSON is malformed (e.g.,
|
||||||
|
* there is a missing comma), then an error is returned and it is no longer
|
||||||
|
* safe to continue.
|
||||||
|
*
|
||||||
|
* To check that an object is empty, it is more performant to use
|
||||||
|
* the is_empty() method.
|
||||||
|
*/
|
||||||
|
simdjson_really_inline simdjson_result<size_t> count_fields() & noexcept;
|
||||||
/**
|
/**
|
||||||
* Consumes the object and returns a string_view instance corresponding to the
|
* Consumes the object and returns a string_view instance corresponding to the
|
||||||
* object as represented in JSON. It points inside the original byte array containg
|
* object as represented in JSON. It points inside the original byte array containing
|
||||||
* the JSON document.
|
* the JSON document.
|
||||||
*/
|
*/
|
||||||
simdjson_really_inline simdjson_result<std::string_view> raw_json() noexcept;
|
simdjson_really_inline simdjson_result<std::string_view> raw_json() noexcept;
|
||||||
@@ -159,6 +215,10 @@ public:
|
|||||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> operator[](std::string_view key) & noexcept;
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> operator[](std::string_view key) & noexcept;
|
||||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> operator[](std::string_view key) && noexcept;
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> operator[](std::string_view key) && noexcept;
|
||||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> at_pointer(std::string_view json_pointer) noexcept;
|
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> at_pointer(std::string_view json_pointer) noexcept;
|
||||||
|
inline simdjson_result<bool> reset() noexcept;
|
||||||
|
inline simdjson_result<bool> is_empty() noexcept;
|
||||||
|
inline simdjson_result<size_t> count_fields() & noexcept;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace simdjson
|
} // namespace simdjson
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ simdjson_warn_unused simdjson_really_inline error_code parser::allocate(size_t n
|
|||||||
SIMDJSON_TRY( implementation->set_capacity(new_capacity) );
|
SIMDJSON_TRY( implementation->set_capacity(new_capacity) );
|
||||||
SIMDJSON_TRY( implementation->set_max_depth(new_max_depth) );
|
SIMDJSON_TRY( implementation->set_max_depth(new_max_depth) );
|
||||||
} else {
|
} else {
|
||||||
SIMDJSON_TRY( simdjson::active_implementation->create_dom_parser_implementation(new_capacity, new_max_depth, implementation) );
|
SIMDJSON_TRY( simdjson::get_active_implementation()->create_dom_parser_implementation(new_capacity, new_max_depth, implementation) );
|
||||||
}
|
}
|
||||||
_capacity = new_capacity;
|
_capacity = new_capacity;
|
||||||
_max_depth = new_max_depth;
|
_max_depth = new_max_depth;
|
||||||
|
|||||||
@@ -54,6 +54,11 @@ public:
|
|||||||
* ondemand::parser parser;
|
* ondemand::parser parser;
|
||||||
* document doc = parser.iterate(json);
|
* document doc = parser.iterate(json);
|
||||||
*
|
*
|
||||||
|
* It is expected that the content is a valid UTF-8 file, containing a valid JSON document.
|
||||||
|
* Otherwise the iterate method may return an error. In particular, the whole input should be
|
||||||
|
* valid: we do not attempt to tolerate incorrect content either before or after a JSON
|
||||||
|
* document.
|
||||||
|
*
|
||||||
* ### IMPORTANT: Validate what you use
|
* ### IMPORTANT: Validate what you use
|
||||||
*
|
*
|
||||||
* Calling iterate on an invalid JSON document may not immediately trigger an error. The call to
|
* Calling iterate on an invalid JSON document may not immediately trigger an error. The call to
|
||||||
@@ -123,14 +128,15 @@ public:
|
|||||||
* iteration to ensure intermediate buffers can be accessed. Any document must be destroyed before
|
* iteration to ensure intermediate buffers can be accessed. Any document must be destroyed before
|
||||||
* you call parse() again or destroy the parser.
|
* you call parse() again or destroy the parser.
|
||||||
*
|
*
|
||||||
|
* The ondemand::document instance holds the iterator. The document must remain in scope
|
||||||
|
* while you are accessing instances of ondemand::value, ondemand::object, ondemand::array.
|
||||||
|
*
|
||||||
* ### REQUIRED: Buffer Padding
|
* ### REQUIRED: Buffer Padding
|
||||||
*
|
*
|
||||||
* The buffer must have at least SIMDJSON_PADDING extra allocated bytes. It does not matter what
|
* The buffer must have at least SIMDJSON_PADDING extra allocated bytes. It does not matter what
|
||||||
* those bytes are initialized to, as long as they are allocated.
|
* those bytes are initialized to, as long as they are allocated.
|
||||||
*
|
*
|
||||||
* @param json The JSON to parse.
|
* @param json The JSON to parse.
|
||||||
* @param len The length of the JSON.
|
|
||||||
* @param allocated The number of bytes allocated in the JSON (must be at least len+SIMDJSON_PADDING).
|
|
||||||
*
|
*
|
||||||
* @return The iterator, or an error:
|
* @return The iterator, or an error:
|
||||||
* - INSUFFICIENT_PADDING if the input has less than SIMDJSON_PADDING extra bytes.
|
* - INSUFFICIENT_PADDING if the input has less than SIMDJSON_PADDING extra bytes.
|
||||||
@@ -143,6 +149,69 @@ public:
|
|||||||
*/
|
*/
|
||||||
simdjson_warn_unused simdjson_result<json_iterator> iterate_raw(padded_string_view json) & noexcept;
|
simdjson_warn_unused simdjson_result<json_iterator> iterate_raw(padded_string_view json) & noexcept;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse a buffer containing many JSON documents.
|
||||||
|
*
|
||||||
|
* auto json = R"({ "foo": 1 } { "foo": 2 } { "foo": 3 } )"_padded;
|
||||||
|
* ondemand::parser parser;
|
||||||
|
* ondemand::document_stream docs = parser.iterate_many(json);
|
||||||
|
* for (auto & doc : docs) {
|
||||||
|
* std::cout << doc["foo"] << std::endl;
|
||||||
|
* }
|
||||||
|
* // Prints 1 2 3
|
||||||
|
*
|
||||||
|
* No copy of the input buffer is made.
|
||||||
|
*
|
||||||
|
* The function is lazy: it may be that no more than one JSON document at a time is parsed.
|
||||||
|
*
|
||||||
|
* The caller is responsabile to ensure that the input string data remains unchanged and is
|
||||||
|
* not deleted during the loop.
|
||||||
|
*
|
||||||
|
* ### Format
|
||||||
|
*
|
||||||
|
* The buffer must contain a series of one or more JSON documents, concatenated into a single
|
||||||
|
* buffer, separated by ASCII whitespace. It effectively parses until it has a fully valid document,
|
||||||
|
* then starts parsing the next document at that point. (It does this with more parallelism and
|
||||||
|
* lookahead than you might think, though.)
|
||||||
|
*
|
||||||
|
* documents that consist of an object or array may omit the whitespace between them, concatenating
|
||||||
|
* with no separator. Documents that consist of a single primitive (i.e. documents that are not
|
||||||
|
* arrays or objects) MUST be separated with ASCII whitespace.
|
||||||
|
*
|
||||||
|
* The characters inside a JSON document, and between JSON documents, must be valid Unicode (UTF-8).
|
||||||
|
*
|
||||||
|
* The documents must not exceed batch_size bytes (by default 1MB) or they will fail to parse.
|
||||||
|
* Setting batch_size to excessively large or excessively small values may impact negatively the
|
||||||
|
* performance.
|
||||||
|
*
|
||||||
|
* ### REQUIRED: Buffer Padding
|
||||||
|
*
|
||||||
|
* The buffer must have at least SIMDJSON_PADDING extra allocated bytes. It does not matter what
|
||||||
|
* those bytes are initialized to, as long as they are allocated.
|
||||||
|
*
|
||||||
|
* ### Threads
|
||||||
|
*
|
||||||
|
* When compiled with SIMDJSON_THREADS_ENABLED, this method will use a single thread under the
|
||||||
|
* hood to do some lookahead.
|
||||||
|
*
|
||||||
|
* ### Parser Capacity
|
||||||
|
*
|
||||||
|
* If the parser's current capacity is less than batch_size, it will allocate enough capacity
|
||||||
|
* to handle it (up to max_capacity).
|
||||||
|
*
|
||||||
|
* @param buf The concatenated JSON to parse.
|
||||||
|
* @param len The length of the concatenated JSON.
|
||||||
|
* @param batch_size The batch size to use. MUST be larger than the largest document. The sweet
|
||||||
|
* spot is cache-related: small enough to fit in cache, yet big enough to
|
||||||
|
* parse as many documents as possible in one tight loop.
|
||||||
|
* Defaults to 10MB, which has been a reasonable sweet spot in our tests.
|
||||||
|
* @return The stream, or an error. An empty input will yield 0 documents rather than an EMPTY error. Errors:
|
||||||
|
* - MEMALLOC if the parser does not have enough capacity and memory allocation fails
|
||||||
|
* - CAPACITY if the parser does not have enough capacity and batch_size > max_capacity.
|
||||||
|
* - other json errors if parsing fails. You should not rely on these errors to always the same for the
|
||||||
|
* same document: they may vary under runtime dispatch (so they may vary depending on your system and hardware).
|
||||||
|
*/
|
||||||
inline simdjson_result<document_stream> iterate_many(const uint8_t *buf, size_t len, size_t batch_size = DEFAULT_BATCH_SIZE) noexcept;
|
inline simdjson_result<document_stream> iterate_many(const uint8_t *buf, size_t len, size_t batch_size = DEFAULT_BATCH_SIZE) noexcept;
|
||||||
/** @overload parse_many(const uint8_t *buf, size_t len, size_t batch_size) */
|
/** @overload parse_many(const uint8_t *buf, size_t len, size_t batch_size) */
|
||||||
inline simdjson_result<document_stream> iterate_many(const char *buf, size_t len, size_t batch_size = DEFAULT_BATCH_SIZE) noexcept;
|
inline simdjson_result<document_stream> iterate_many(const char *buf, size_t len, size_t batch_size = DEFAULT_BATCH_SIZE) noexcept;
|
||||||
|
|||||||
@@ -20,6 +20,13 @@ inline simdjson_result<std::string_view> to_json_string(SIMDJSON_IMPLEMENTATION:
|
|||||||
return trim(v);
|
return trim(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline simdjson_result<std::string_view> to_json_string(SIMDJSON_IMPLEMENTATION::ondemand::document_reference& x) noexcept {
|
||||||
|
std::string_view v;
|
||||||
|
auto error = x.raw_json().get(v);
|
||||||
|
if(error) {return error; }
|
||||||
|
return trim(v);
|
||||||
|
}
|
||||||
|
|
||||||
inline simdjson_result<std::string_view> to_json_string(SIMDJSON_IMPLEMENTATION::ondemand::value& x) noexcept {
|
inline simdjson_result<std::string_view> to_json_string(SIMDJSON_IMPLEMENTATION::ondemand::value& x) noexcept {
|
||||||
/**
|
/**
|
||||||
* If we somehow receive a value that has already been consumed,
|
* If we somehow receive a value that has already been consumed,
|
||||||
@@ -66,30 +73,33 @@ inline simdjson_result<std::string_view> to_json_string(SIMDJSON_IMPLEMENTATION:
|
|||||||
return trim(v);
|
return trim(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if SIMDJSON_EXCEPTIONS
|
|
||||||
|
|
||||||
inline simdjson_result<std::string_view> to_json_string(simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document> x) {
|
inline simdjson_result<std::string_view> to_json_string(simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document> x) {
|
||||||
if (x.error()) { return x.error(); }
|
if (x.error()) { return x.error(); }
|
||||||
return to_json_string(x.value());
|
return to_json_string(x.value_unsafe());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline simdjson_result<std::string_view> to_json_string(simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference> x) {
|
||||||
|
if (x.error()) { return x.error(); }
|
||||||
|
return to_json_string(x.value_unsafe());
|
||||||
}
|
}
|
||||||
|
|
||||||
inline simdjson_result<std::string_view> to_json_string(simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> x) {
|
inline simdjson_result<std::string_view> to_json_string(simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> x) {
|
||||||
if (x.error()) { return x.error(); }
|
if (x.error()) { return x.error(); }
|
||||||
return to_json_string(x.value());
|
return to_json_string(x.value_unsafe());
|
||||||
}
|
}
|
||||||
|
|
||||||
inline simdjson_result<std::string_view> to_json_string(simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object> x) {
|
inline simdjson_result<std::string_view> to_json_string(simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object> x) {
|
||||||
if (x.error()) { return x.error(); }
|
if (x.error()) { return x.error(); }
|
||||||
return to_json_string(x.value());
|
return to_json_string(x.value_unsafe());
|
||||||
}
|
}
|
||||||
|
|
||||||
inline simdjson_result<std::string_view> to_json_string(simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array> x) {
|
inline simdjson_result<std::string_view> to_json_string(simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array> x) {
|
||||||
if (x.error()) { return x.error(); }
|
if (x.error()) { return x.error(); }
|
||||||
return to_json_string(x.value());
|
return to_json_string(x.value_unsafe());
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
} // namespace simdjson
|
} // namespace simdjson
|
||||||
|
|
||||||
|
namespace simdjson { namespace SIMDJSON_IMPLEMENTATION { namespace ondemand {
|
||||||
|
|
||||||
#if SIMDJSON_EXCEPTIONS
|
#if SIMDJSON_EXCEPTIONS
|
||||||
inline std::ostream& operator<<(std::ostream& out, simdjson::SIMDJSON_IMPLEMENTATION::ondemand::value x) {
|
inline std::ostream& operator<<(std::ostream& out, simdjson::SIMDJSON_IMPLEMENTATION::ondemand::value x) {
|
||||||
@@ -153,7 +163,20 @@ inline std::ostream& operator<<(std::ostream& out, simdjson::SIMDJSON_IMPLEMENTA
|
|||||||
throw simdjson::simdjson_error(error);
|
throw simdjson::simdjson_error(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::SIMDJSON_IMPLEMENTATION::ondemand::document> x) {
|
inline std::ostream& operator<<(std::ostream& out, simdjson::SIMDJSON_IMPLEMENTATION::ondemand::document_reference& value) {
|
||||||
|
std::string_view v;
|
||||||
|
auto error = simdjson::to_json_string(value).get(v);
|
||||||
|
if(error == simdjson::SUCCESS) {
|
||||||
|
return (out << v);
|
||||||
|
} else {
|
||||||
|
throw simdjson::simdjson_error(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::SIMDJSON_IMPLEMENTATION::ondemand::document>&& x) {
|
||||||
|
if (x.error()) { throw simdjson::simdjson_error(x.error()); }
|
||||||
|
return (out << x.value());
|
||||||
|
}
|
||||||
|
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::SIMDJSON_IMPLEMENTATION::ondemand::document_reference>&& x) {
|
||||||
if (x.error()) { throw simdjson::simdjson_error(x.error()); }
|
if (x.error()) { throw simdjson::simdjson_error(x.error()); }
|
||||||
return (out << x.value());
|
return (out << x.value());
|
||||||
}
|
}
|
||||||
@@ -194,3 +217,4 @@ inline std::ostream& operator<<(std::ostream& out, simdjson::SIMDJSON_IMPLEMENTA
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
}}} // namespace simdjson::SIMDJSON_IMPLEMENTATION::ondemand
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user