Merge pull request #1342 from simdjson/jkeiser/iter-safety
Safety: assert in debug mode when on demand values are used out of order
This commit is contained in:
commit
f785f76d98
|
@ -19,7 +19,7 @@ environment:
|
||||||
- job_name: VS2017 (Static, No Threads)
|
- job_name: VS2017 (Static, No Threads)
|
||||||
image: Visual Studio 2017
|
image: Visual Studio 2017
|
||||||
CMAKE_ARGS: -A %Platform% -DSIMDJSON_BUILD_STATIC=ON -DSIMDJSON_ENABLE_THREADS=OFF
|
CMAKE_ARGS: -A %Platform% -DSIMDJSON_BUILD_STATIC=ON -DSIMDJSON_ENABLE_THREADS=OFF
|
||||||
CTEST_ARGS: -E checkperf
|
CTEST_ARGS: -LE explicitonly
|
||||||
- job_name: VS2019 (Win32)
|
- job_name: VS2019 (Win32)
|
||||||
platform: Win32
|
platform: Win32
|
||||||
CMAKE_ARGS: -A %Platform% -DSIMDJSON_BUILD_STATIC=OFF -DSIMDJSON_ENABLE_THREADS=ON # This should be the default. Testing anyway.
|
CMAKE_ARGS: -A %Platform% -DSIMDJSON_BUILD_STATIC=OFF -DSIMDJSON_ENABLE_THREADS=ON # This should be the default. Testing anyway.
|
||||||
|
@ -31,7 +31,7 @@ environment:
|
||||||
- job_name: VS2015
|
- job_name: VS2015
|
||||||
image: Visual Studio 2015
|
image: Visual Studio 2015
|
||||||
CMAKE_ARGS: -A %Platform% -DSIMDJSON_BUILD_STATIC=ON -DSIMDJSON_ENABLE_THREADS=OFF
|
CMAKE_ARGS: -A %Platform% -DSIMDJSON_BUILD_STATIC=ON -DSIMDJSON_ENABLE_THREADS=OFF
|
||||||
CTEST_ARGS: -E checkperf
|
CTEST_ARGS: -LE explicitonly
|
||||||
|
|
||||||
build_script:
|
build_script:
|
||||||
- mkdir build
|
- mkdir build
|
||||||
|
|
|
@ -103,7 +103,14 @@ commands:
|
||||||
cd build &&
|
cd build &&
|
||||||
tools/json2json -h &&
|
tools/json2json -h &&
|
||||||
ctest $CTEST_FLAGS -L acceptance &&
|
ctest $CTEST_FLAGS -L acceptance &&
|
||||||
ctest $CTEST_FLAGS -LE acceptance -E checkperf
|
ctest $CTEST_FLAGS -LE acceptance -LE explicitonly
|
||||||
|
|
||||||
|
cmake_assert_test:
|
||||||
|
steps:
|
||||||
|
- run: |
|
||||||
|
cd build &&
|
||||||
|
tools/json2json -h &&
|
||||||
|
ctest $CTEST_FLAGS -L assert
|
||||||
|
|
||||||
cmake_test_all:
|
cmake_test_all:
|
||||||
steps:
|
steps:
|
||||||
|
@ -112,9 +119,9 @@ commands:
|
||||||
cd build &&
|
cd build &&
|
||||||
tools/json2json -h &&
|
tools/json2json -h &&
|
||||||
ctest $CTEST_FLAGS -DSIMDJSON_IMPLEMENTATION="haswell;westmere;fallback" -L acceptance -LE per_implementation &&
|
ctest $CTEST_FLAGS -DSIMDJSON_IMPLEMENTATION="haswell;westmere;fallback" -L acceptance -LE per_implementation &&
|
||||||
SIMDJSON_FORCE_IMPLEMENTATION=haswell ctest $CTEST_FLAGS -L per_implementation -E checkperf &&
|
SIMDJSON_FORCE_IMPLEMENTATION=haswell ctest $CTEST_FLAGS -L per_implementation -LE explicitonly &&
|
||||||
SIMDJSON_FORCE_IMPLEMENTATION=westmere ctest $CTEST_FLAGS -L per_implementation -E checkperf &&
|
SIMDJSON_FORCE_IMPLEMENTATION=westmere ctest $CTEST_FLAGS -L per_implementation -LE explicitonly &&
|
||||||
SIMDJSON_FORCE_IMPLEMENTATION=fallback ctest $CTEST_FLAGS -L per_implementation -E checkperf &&
|
SIMDJSON_FORCE_IMPLEMENTATION=fallback ctest $CTEST_FLAGS -L per_implementation -LE explicitonly &&
|
||||||
ctest $CTEST_FLAGS -LE "acceptance|per_implementation" # Everything we haven't run yet, run now.
|
ctest $CTEST_FLAGS -LE "acceptance|per_implementation" # Everything we haven't run yet, run now.
|
||||||
|
|
||||||
|
|
||||||
|
@ -144,6 +151,16 @@ jobs:
|
||||||
executor: gcc10
|
executor: gcc10
|
||||||
environment: { CMAKE_FLAGS: -DSIMDJSON_JUST_LIBRARY=ON }
|
environment: { CMAKE_FLAGS: -DSIMDJSON_JUST_LIBRARY=ON }
|
||||||
steps: [ cmake_build, cmake_install_test, cmake_installed_test_cxx20 ]
|
steps: [ cmake_build, cmake_install_test, cmake_installed_test_cxx20 ]
|
||||||
|
assert-gcc10:
|
||||||
|
description: Build the library with asserts on, install it and run tests
|
||||||
|
executor: gcc10
|
||||||
|
environment: { CMAKE_FLAGS: -DSIMDJSON_GOOGLE_BENCHMARKS=OFF -DCMAKE_CXX_FLAGS_RELEASE=-O3 }
|
||||||
|
steps: [ cmake_test, cmake_assert_test ]
|
||||||
|
assert-clang10:
|
||||||
|
description: Build just the library, install it and do a basic test
|
||||||
|
executor: clang10
|
||||||
|
environment: { CMAKE_FLAGS: -DSIMDJSON_GOOGLE_BENCHMARKS=OFF -DCMAKE_CXX_FLAGS_RELEASE=-O3 }
|
||||||
|
steps: [ cmake_test, cmake_assert_test ]
|
||||||
gcc10-perftest:
|
gcc10-perftest:
|
||||||
description: Build and run performance tests on GCC 10 and AVX 2 with a cmake static build, this test performance regression
|
description: Build and run performance tests on GCC 10 and AVX 2 with a cmake static build, this test performance regression
|
||||||
executor: gcc10
|
executor: gcc10
|
||||||
|
@ -174,22 +191,22 @@ 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: -DSIMDJSON_BUILD_STATIC=OFF -DSIMDJSON_SANITIZE=ON, BUILD_FLAGS: "", CTEST_FLAGS: --output-on-failure -E checkperf }
|
environment: { CMAKE_FLAGS: -DSIMDJSON_BUILD_STATIC=OFF -DSIMDJSON_SANITIZE=ON, BUILD_FLAGS: "", 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: -DSIMDJSON_BUILD_STATIC=OFF -DSIMDJSON_SANITIZE=ON, CTEST_FLAGS: --output-on-failure -E checkperf }
|
environment: { CMAKE_FLAGS: -DSIMDJSON_BUILD_STATIC=OFF -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
|
||||||
executor: gcc10
|
executor: gcc10
|
||||||
environment: { CMAKE_FLAGS: -DSIMDJSON_BUILD_STATIC=OFF -DSIMDJSON_SANITIZE_THREADS=ON, BUILD_FLAGS: "", CTEST_FLAGS: --output-on-failure -E checkperf }
|
environment: { CMAKE_FLAGS: -DSIMDJSON_BUILD_STATIC=OFF -DSIMDJSON_SANITIZE_THREADS=ON, BUILD_FLAGS: "", CTEST_FLAGS: --output-on-failure -LE explicitonly }
|
||||||
steps: [ cmake_test ]
|
steps: [ cmake_test ]
|
||||||
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: -DSIMDJSON_BUILD_STATIC=OFF -DSIMDJSON_SANITIZE_THREADS=ON, CTEST_FLAGS: --output-on-failure -E checkperf }
|
environment: { CMAKE_FLAGS: -DSIMDJSON_BUILD_STATIC=OFF -DSIMDJSON_SANITIZE_THREADS=ON, CTEST_FLAGS: --output-on-failure -LE explicitonly }
|
||||||
steps: [ cmake_test ]
|
steps: [ cmake_test ]
|
||||||
# dynamic
|
# dynamic
|
||||||
dynamic-gcc10:
|
dynamic-gcc10:
|
||||||
|
@ -245,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: -DSIMDJSON_BUILD_STATIC=OFF -DSIMDJSON_SANITIZE=ON, BUILD_FLAGS: "", CTEST_FLAGS: --output-on-failure -E checkperf }
|
environment: { CXXFLAGS: -march=haswell, CMAKE_FLAGS: -DSIMDJSON_BUILD_STATIC=OFF -DSIMDJSON_SANITIZE=ON, BUILD_FLAGS: "", 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: -DSIMDJSON_BUILD_STATIC=OFF -DSIMDJSON_SANITIZE=ON, CTEST_FLAGS: --output-on-failure -E checkperf }
|
environment: { CXXFLAGS: -march=haswell, CMAKE_FLAGS: -DSIMDJSON_BUILD_STATIC=OFF -DSIMDJSON_SANITIZE=ON, CTEST_FLAGS: --output-on-failure -LE explicitonly }
|
||||||
steps: [ cmake_test ]
|
steps: [ cmake_test ]
|
||||||
|
|
||||||
workflows:
|
workflows:
|
||||||
|
@ -292,4 +309,8 @@ workflows:
|
||||||
# testing "just the library"
|
# testing "just the library"
|
||||||
- justlib-gcc10
|
- justlib-gcc10
|
||||||
|
|
||||||
|
# testing asserts
|
||||||
|
- assert-gcc10
|
||||||
|
- assert-clang10
|
||||||
|
|
||||||
# TODO add windows: https://circleci.com/docs/2.0/configuration-reference/#windows
|
# TODO add windows: https://circleci.com/docs/2.0/configuration-reference/#windows
|
||||||
|
|
|
@ -23,4 +23,4 @@ task:
|
||||||
- make
|
- make
|
||||||
test_script:
|
test_script:
|
||||||
- cd build
|
- cd build
|
||||||
- ctest --output-on-failure -E checkperf
|
- ctest --output-on-failure -LE explicitonly
|
||||||
|
|
38
.drone.yml
38
.drone.yml
|
@ -9,7 +9,7 @@ steps:
|
||||||
CXX: g++
|
CXX: g++
|
||||||
BUILD_FLAGS: -- -j
|
BUILD_FLAGS: -- -j
|
||||||
CMAKE_FLAGS: -DSIMDJSON_BUILD_STATIC=ON
|
CMAKE_FLAGS: -DSIMDJSON_BUILD_STATIC=ON
|
||||||
CTEST_FLAGS: -j4 --output-on-failure -E checkperf
|
CTEST_FLAGS: -j4 --output-on-failure -LE explicitonly
|
||||||
commands:
|
commands:
|
||||||
- scripts/addcmakeppa.sh "$(env -i sh -c '. /etc/os-release; echo $VERSION_CODENAME')"
|
- scripts/addcmakeppa.sh "$(env -i sh -c '. /etc/os-release; echo $VERSION_CODENAME')"
|
||||||
- apt-get install -y g++ cmake gcc git
|
- apt-get install -y g++ cmake gcc git
|
||||||
|
@ -30,7 +30,7 @@ steps:
|
||||||
CXX: clang++-6.0
|
CXX: clang++-6.0
|
||||||
BUILD_FLAGS: -- -j
|
BUILD_FLAGS: -- -j
|
||||||
CMAKE_FLAGS: -DSIMDJSON_BUILD_STATIC=ON
|
CMAKE_FLAGS: -DSIMDJSON_BUILD_STATIC=ON
|
||||||
CTEST_FLAGS: -j4 --output-on-failure -E checkperf
|
CTEST_FLAGS: -j4 --output-on-failure -LE explicitonly
|
||||||
commands:
|
commands:
|
||||||
- scripts/addcmakeppa.sh "$(env -i sh -c '. /etc/os-release; echo $VERSION_CODENAME')"
|
- scripts/addcmakeppa.sh "$(env -i sh -c '. /etc/os-release; echo $VERSION_CODENAME')"
|
||||||
- apt-get install -y clang++-6.0 cmake git
|
- apt-get install -y clang++-6.0 cmake git
|
||||||
|
@ -51,7 +51,7 @@ steps:
|
||||||
CXX: g++
|
CXX: g++
|
||||||
BUILD_FLAGS: -- -j
|
BUILD_FLAGS: -- -j
|
||||||
CMAKE_FLAGS: -DSIMDJSON_BUILD_STATIC=ON -DSIMDJSON_IMPLEMENTATION=haswell;westmere;fallback
|
CMAKE_FLAGS: -DSIMDJSON_BUILD_STATIC=ON -DSIMDJSON_IMPLEMENTATION=haswell;westmere;fallback
|
||||||
CTEST_FLAGS: -j4 --output-on-failure -E checkperf
|
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
|
||||||
- apt-get update -qq
|
- apt-get update -qq
|
||||||
|
@ -78,7 +78,7 @@ steps:
|
||||||
CXX: clang++-6.0
|
CXX: clang++-6.0
|
||||||
BUILD_FLAGS: -- -j
|
BUILD_FLAGS: -- -j
|
||||||
CMAKE_FLAGS: -DSIMDJSON_BUILD_STATIC=ON -DSIMDJSON_IMPLEMENTATION=haswell;westmere;fallback
|
CMAKE_FLAGS: -DSIMDJSON_BUILD_STATIC=ON -DSIMDJSON_IMPLEMENTATION=haswell;westmere;fallback
|
||||||
CTEST_FLAGS: -j4 --output-on-failure -E checkperf
|
CTEST_FLAGS: -j4 --output-on-failure -LE explicitonly
|
||||||
commands:
|
commands:
|
||||||
- mkdir build
|
- mkdir build
|
||||||
- cd build
|
- cd build
|
||||||
|
@ -101,7 +101,7 @@ steps:
|
||||||
CXX: g++
|
CXX: g++
|
||||||
BUILD_FLAGS: -- -j
|
BUILD_FLAGS: -- -j
|
||||||
CMAKE_FLAGS: -DSIMDJSON_BUILD_STATIC=OFF
|
CMAKE_FLAGS: -DSIMDJSON_BUILD_STATIC=OFF
|
||||||
CTEST_FLAGS: -j4 --output-on-failure -E checkperf
|
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
|
||||||
- apt-get update -qq
|
- apt-get update -qq
|
||||||
|
@ -124,7 +124,7 @@ steps:
|
||||||
CXX: clang++-9
|
CXX: clang++-9
|
||||||
CMAKE_FLAGS: -DSIMDJSON_BUILD_STATIC=OFF
|
CMAKE_FLAGS: -DSIMDJSON_BUILD_STATIC=OFF
|
||||||
BUILD_FLAGS: -- -j
|
BUILD_FLAGS: -- -j
|
||||||
CTEST_FLAGS: -j4 --output-on-failure -E checkperf
|
CTEST_FLAGS: -j4 --output-on-failure -LE explicitonly
|
||||||
commands:
|
commands:
|
||||||
- mkdir build
|
- mkdir build
|
||||||
- cd build
|
- cd build
|
||||||
|
@ -143,7 +143,7 @@ steps:
|
||||||
CXX: g++
|
CXX: g++
|
||||||
BUILD_FLAGS: -- -j
|
BUILD_FLAGS: -- -j
|
||||||
CMAKE_FLAGS: -DSIMDJSON_BUILD_STATIC=ON -DSIMDJSON_IMPLEMENTATION=haswell;westmere;fallback
|
CMAKE_FLAGS: -DSIMDJSON_BUILD_STATIC=ON -DSIMDJSON_IMPLEMENTATION=haswell;westmere;fallback
|
||||||
CTEST_FLAGS: -j4 --output-on-failure -E checkperf
|
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
|
||||||
- apt-get update -qq
|
- apt-get update -qq
|
||||||
|
@ -170,7 +170,7 @@ steps:
|
||||||
CXX: clang++-9
|
CXX: clang++-9
|
||||||
CMAKE_FLAGS: -DSIMDJSON_SANITIZE=ON -DSIMDJSON_IMPLEMENTATION=haswell;westmere;fallback
|
CMAKE_FLAGS: -DSIMDJSON_SANITIZE=ON -DSIMDJSON_IMPLEMENTATION=haswell;westmere;fallback
|
||||||
BUILD_FLAGS: -- -j
|
BUILD_FLAGS: -- -j
|
||||||
CTEST_FLAGS: -j4 --output-on-failure -E checkperf
|
CTEST_FLAGS: -j4 --output-on-failure -LE explicitonly
|
||||||
commands:
|
commands:
|
||||||
- mkdir build
|
- mkdir build
|
||||||
- cd build
|
- cd build
|
||||||
|
@ -194,7 +194,7 @@ steps:
|
||||||
CXX: clang++-11
|
CXX: clang++-11
|
||||||
CMAKE_FLAGS: -GNinja
|
CMAKE_FLAGS: -GNinja
|
||||||
BUILD_FLAGS:
|
BUILD_FLAGS:
|
||||||
CTEST_FLAGS: -j4 --output-on-failure -E checkperf
|
CTEST_FLAGS: -j4 --output-on-failure -LE explicitonly
|
||||||
CXXFLAGS: -std=c++20 -stdlib=libc++
|
CXXFLAGS: -std=c++20 -stdlib=libc++
|
||||||
commands:
|
commands:
|
||||||
- mkdir build
|
- mkdir build
|
||||||
|
@ -214,7 +214,7 @@ steps:
|
||||||
CXX: g++
|
CXX: g++
|
||||||
BUILD_FLAGS: -- -j
|
BUILD_FLAGS: -- -j
|
||||||
CMAKE_FLAGS: -DSIMDJSON_BUILD_STATIC=ON -DSIMDJSON_IMPLEMENTATION=arm64;fallback
|
CMAKE_FLAGS: -DSIMDJSON_BUILD_STATIC=ON -DSIMDJSON_IMPLEMENTATION=arm64;fallback
|
||||||
CTEST_FLAGS: -j4 --output-on-failure -E checkperf
|
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
|
||||||
- apt-get update -qq
|
- apt-get update -qq
|
||||||
|
@ -239,7 +239,7 @@ steps:
|
||||||
CXX: clang++-6.0
|
CXX: clang++-6.0
|
||||||
CMAKE_FLAGS: -DSIMDJSON_BUILD_STATIC=OFF
|
CMAKE_FLAGS: -DSIMDJSON_BUILD_STATIC=OFF
|
||||||
BUILD_FLAGS: -- -j
|
BUILD_FLAGS: -- -j
|
||||||
CTEST_FLAGS: -j4 --output-on-failure -E checkperf
|
CTEST_FLAGS: -j4 --output-on-failure -LE explicitonly
|
||||||
commands:
|
commands:
|
||||||
- apt-get -qq update
|
- apt-get -qq update
|
||||||
- apt-get -t buster-backports install -y cmake
|
- apt-get -t buster-backports install -y cmake
|
||||||
|
@ -261,7 +261,7 @@ steps:
|
||||||
CXX: g++
|
CXX: g++
|
||||||
BUILD_FLAGS: -- -j
|
BUILD_FLAGS: -- -j
|
||||||
CMAKE_FLAGS: -DSIMDJSON_BUILD_STATIC=OFF
|
CMAKE_FLAGS: -DSIMDJSON_BUILD_STATIC=OFF
|
||||||
CTEST_FLAGS: -j4 --output-on-failure -E checkperf
|
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
|
||||||
- apt-get update -qq
|
- apt-get update -qq
|
||||||
|
@ -283,7 +283,7 @@ steps:
|
||||||
CXX: clang++-6.0
|
CXX: clang++-6.0
|
||||||
CMAKE_FLAGS: -DSIMDJSON_BUILD_STATIC=OFF
|
CMAKE_FLAGS: -DSIMDJSON_BUILD_STATIC=OFF
|
||||||
BUILD_FLAGS: -- -j
|
BUILD_FLAGS: -- -j
|
||||||
CTEST_FLAGS: -j4 --output-on-failure -E checkperf
|
CTEST_FLAGS: -j4 --output-on-failure -LE explicitonly
|
||||||
commands:
|
commands:
|
||||||
- apt-get -qq update
|
- apt-get -qq update
|
||||||
- apt-get -t buster-backports install -y cmake
|
- apt-get -t buster-backports install -y cmake
|
||||||
|
@ -303,7 +303,7 @@ steps:
|
||||||
environment:
|
environment:
|
||||||
BUILD_FLAGS: -- -j
|
BUILD_FLAGS: -- -j
|
||||||
CMAKE_FLAGS: -DSIMDJSON_BUILD_STATIC=ON -DSIMDJSON_IMPLEMENTATION=arm64;fallback
|
CMAKE_FLAGS: -DSIMDJSON_BUILD_STATIC=ON -DSIMDJSON_IMPLEMENTATION=arm64;fallback
|
||||||
CTEST_FLAGS: -j4 --output-on-failure -E checkperf
|
CTEST_FLAGS: -j4 --output-on-failure -LE explicitonly
|
||||||
CC: gcc
|
CC: gcc
|
||||||
CXX: g++
|
CXX: g++
|
||||||
commands:
|
commands:
|
||||||
|
@ -331,7 +331,7 @@ steps:
|
||||||
CXX: clang++-6.0
|
CXX: clang++-6.0
|
||||||
CMAKE_FLAGS: -DSIMDJSON_SANITIZE=ON -DSIMDJSON_IMPLEMENTATION=arm64;fallback
|
CMAKE_FLAGS: -DSIMDJSON_SANITIZE=ON -DSIMDJSON_IMPLEMENTATION=arm64;fallback
|
||||||
BUILD_FLAGS: -- -j
|
BUILD_FLAGS: -- -j
|
||||||
CTEST_FLAGS: -j4 --output-on-failure -E checkperf
|
CTEST_FLAGS: -j4 --output-on-failure -LE explicitonly
|
||||||
commands:
|
commands:
|
||||||
- apt-get -qq update
|
- apt-get -qq update
|
||||||
- apt-get -t buster-backports install -y cmake
|
- apt-get -t buster-backports install -y cmake
|
||||||
|
@ -357,7 +357,7 @@ steps:
|
||||||
CXX: clang++-9
|
CXX: clang++-9
|
||||||
BUILD_FLAGS: -- -j 4
|
BUILD_FLAGS: -- -j 4
|
||||||
CMAKE_FLAGS: -GNinja -DSIMDJSON_BUILD_STATIC=ON
|
CMAKE_FLAGS: -GNinja -DSIMDJSON_BUILD_STATIC=ON
|
||||||
CTEST_FLAGS: -j4 --output-on-failure -E checkperf
|
CTEST_FLAGS: -j4 --output-on-failure -LE explicitonly
|
||||||
CXXFLAGS: -stdlib=libc++
|
CXXFLAGS: -stdlib=libc++
|
||||||
commands:
|
commands:
|
||||||
- mkdir build
|
- mkdir build
|
||||||
|
@ -378,7 +378,7 @@ steps:
|
||||||
CXX: clang++-9
|
CXX: clang++-9
|
||||||
BUILD_FLAGS: -- -j
|
BUILD_FLAGS: -- -j
|
||||||
CMAKE_FLAGS: -DSIMDJSON_BUILD_STATIC=ON
|
CMAKE_FLAGS: -DSIMDJSON_BUILD_STATIC=ON
|
||||||
CTEST_FLAGS: -j4 --output-on-failure -E checkperf
|
CTEST_FLAGS: -j4 --output-on-failure -LE explicitonly
|
||||||
CXXFLAGS: -stdlib=libc++
|
CXXFLAGS: -stdlib=libc++
|
||||||
commands:
|
commands:
|
||||||
- mkdir build
|
- mkdir build
|
||||||
|
@ -399,7 +399,7 @@ steps:
|
||||||
CXX: clang++-7
|
CXX: clang++-7
|
||||||
BUILD_FLAGS: -- -j
|
BUILD_FLAGS: -- -j
|
||||||
CMAKE_FLAGS: -DSIMDJSON_BUILD_STATIC=ON
|
CMAKE_FLAGS: -DSIMDJSON_BUILD_STATIC=ON
|
||||||
CTEST_FLAGS: -j4 --output-on-failure -E checkperf
|
CTEST_FLAGS: -j4 --output-on-failure -LE explicitonly
|
||||||
CXXFLAGS: -stdlib=libc++
|
CXXFLAGS: -stdlib=libc++
|
||||||
commands:
|
commands:
|
||||||
- mkdir build
|
- mkdir build
|
||||||
|
@ -419,7 +419,7 @@ steps:
|
||||||
CXX: g++
|
CXX: g++
|
||||||
BUILD_FLAGS: -- -j
|
BUILD_FLAGS: -- -j
|
||||||
CMAKE_FLAGS: -DSIMDJSON_EXCEPTIONS=OFF
|
CMAKE_FLAGS: -DSIMDJSON_EXCEPTIONS=OFF
|
||||||
CTEST_FLAGS: -j4 --output-on-failure -E checkperf
|
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
|
||||||
- apt-get update -qq
|
- apt-get update -qq
|
||||||
|
|
|
@ -34,4 +34,4 @@ jobs:
|
||||||
./alpine.sh cmake --build build_for_alpine
|
./alpine.sh cmake --build build_for_alpine
|
||||||
- name: test
|
- name: test
|
||||||
run: |
|
run: |
|
||||||
./alpine.sh bash -c "cd build_for_alpine && ctest -E checkperf"
|
./alpine.sh bash -c "cd build_for_alpine && ctest -LE explicitonly"
|
||||||
|
|
|
@ -51,4 +51,4 @@ jobs:
|
||||||
cd build
|
cd build
|
||||||
cmake -DCMAKE_BUILD_TYPE=${{ matrix.type }} -DSIMDJSON_BUILD_STATIC=ON -DSIMDJSON_DO_NOT_USE_THREADS_NO_MATTER_WHAT=ON ..
|
cmake -DCMAKE_BUILD_TYPE=${{ matrix.type }} -DSIMDJSON_BUILD_STATIC=ON -DSIMDJSON_DO_NOT_USE_THREADS_NO_MATTER_WHAT=ON ..
|
||||||
cmake --build . --verbose
|
cmake --build . --verbose
|
||||||
ctest -j4 --output-on-failure -E checkperf
|
ctest -j4 --output-on-failure -LE explicitonly
|
||||||
|
|
|
@ -23,6 +23,6 @@ jobs:
|
||||||
cd build &&
|
cd build &&
|
||||||
cmake -DSIMDJSON_GOOGLE_BENCHMARKS=ON -DSIMDJSON_BUILD_STATIC=ON -DCMAKE_INSTALL_PREFIX:PATH=destination .. &&
|
cmake -DSIMDJSON_GOOGLE_BENCHMARKS=ON -DSIMDJSON_BUILD_STATIC=ON -DCMAKE_INSTALL_PREFIX:PATH=destination .. &&
|
||||||
cmake --build . &&
|
cmake --build . &&
|
||||||
ctest -j --output-on-failure -E checkperf &&
|
ctest -j --output-on-failure -LE explicitonly &&
|
||||||
make install &&
|
make install &&
|
||||||
echo -e '#include <simdjson.h>\nint main(int argc,char**argv) {simdjson::dom::parser parser;simdjson::dom::element tweets = parser.load(argv[1]); }' > tmp.cpp && c++ -Idestination/include -Ldestination/lib -std=c++17 -Wl,-rpath,destination/lib -o linkandrun tmp.cpp -lsimdjson && ./linkandrun jsonexamples/twitter.json
|
echo -e '#include <simdjson.h>\nint main(int argc,char**argv) {simdjson::dom::parser parser;simdjson::dom::element tweets = parser.load(argv[1]); }' > tmp.cpp && c++ -Idestination/include -Ldestination/lib -std=c++17 -Wl,-rpath,destination/lib -o linkandrun tmp.cpp -lsimdjson && ./linkandrun jsonexamples/twitter.json
|
||||||
|
|
|
@ -23,6 +23,6 @@ jobs:
|
||||||
cd build &&
|
cd build &&
|
||||||
cmake -DSIMDJSON_GOOGLE_BENCHMARKS=ON -DSIMDJSON_BUILD_STATIC=ON -DCMAKE_INSTALL_PREFIX:PATH=destination .. &&
|
cmake -DSIMDJSON_GOOGLE_BENCHMARKS=ON -DSIMDJSON_BUILD_STATIC=ON -DCMAKE_INSTALL_PREFIX:PATH=destination .. &&
|
||||||
cmake --build . &&
|
cmake --build . &&
|
||||||
ctest -j --output-on-failure -E checkperf &&
|
ctest -j --output-on-failure -LE explicitonly &&
|
||||||
make install &&
|
make install &&
|
||||||
echo -e '#include <simdjson.h>\nint main(int argc,char**argv) {simdjson::dom::parser parser;simdjson::dom::element tweets = parser.load(argv[1]); }' > tmp.cpp && c++ -Idestination/include -Ldestination/lib -std=c++17 -Wl,-rpath,destination/lib -o linkandrun tmp.cpp -lsimdjson && ./linkandrun jsonexamples/twitter.json
|
echo -e '#include <simdjson.h>\nint main(int argc,char**argv) {simdjson::dom::parser parser;simdjson::dom::element tweets = parser.load(argv[1]); }' > tmp.cpp && c++ -Idestination/include -Ldestination/lib -std=c++17 -Wl,-rpath,destination/lib -o linkandrun tmp.cpp -lsimdjson && ./linkandrun jsonexamples/twitter.json
|
||||||
|
|
|
@ -31,6 +31,6 @@ jobs:
|
||||||
buildWithCMakeArgs: --config Release
|
buildWithCMakeArgs: --config Release
|
||||||
|
|
||||||
- name: 'Run CTest'
|
- name: 'Run CTest'
|
||||||
run: ctest -C Release -E checkperf --output-on-failure
|
run: ctest -C Release -LE explicitonly --output-on-failure
|
||||||
working-directory: "${{ github.workspace }}/../../_temp/windows"
|
working-directory: "${{ github.workspace }}/../../_temp/windows"
|
||||||
|
|
||||||
|
|
|
@ -31,5 +31,5 @@ jobs:
|
||||||
buildWithCMakeArgs: --config Release
|
buildWithCMakeArgs: --config Release
|
||||||
|
|
||||||
- name: 'Run CTest'
|
- name: 'Run CTest'
|
||||||
run: ctest -C Release -E checkperf --output-on-failure
|
run: ctest -C Release -LE explicitonly --output-on-failure
|
||||||
working-directory: "${{ github.workspace }}/../../_temp/windows"
|
working-directory: "${{ github.workspace }}/../../_temp/windows"
|
||||||
|
|
|
@ -31,6 +31,6 @@ jobs:
|
||||||
buildWithCMakeArgs: --config Release
|
buildWithCMakeArgs: --config Release
|
||||||
|
|
||||||
- name: 'Run CTest'
|
- name: 'Run CTest'
|
||||||
run: ctest -C Release -E checkperf --output-on-failure
|
run: ctest -C Release -LE explicitonly --output-on-failure
|
||||||
working-directory: "${{ github.workspace }}/../../_temp/windows"
|
working-directory: "${{ github.workspace }}/../../_temp/windows"
|
||||||
|
|
||||||
|
|
|
@ -176,7 +176,7 @@ install:
|
||||||
- if [[ "${STATIC}" == "on" ]]; then
|
- if [[ "${STATIC}" == "on" ]]; then
|
||||||
export CMAKE_FLAGS="${CMAKE_FLAGS} -DSIMDJSON_BUILD_STATIC=ON";
|
export CMAKE_FLAGS="${CMAKE_FLAGS} -DSIMDJSON_BUILD_STATIC=ON";
|
||||||
fi
|
fi
|
||||||
- export CTEST_FLAGS="-j4 --output-on-failure -E checkperf"
|
- export CTEST_FLAGS="-j4 --output-on-failure -LE explicitonly"
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- mkdir build
|
- mkdir build
|
||||||
|
|
|
@ -41,7 +41,7 @@
|
||||||
#
|
#
|
||||||
# Next you can test it as follows:
|
# Next you can test it as follows:
|
||||||
#
|
#
|
||||||
# docker run -it -v $(pwd):/project:Z simdjson sh -c "cd dockerbuild && ctest . --output-on-failure -E checkperf"
|
# docker run -it -v $(pwd):/project:Z simdjson sh -c "cd dockerbuild && ctest . --output-on-failure -LE explicitonly"
|
||||||
#
|
#
|
||||||
# The run the complete tests requires you to have built all of simdjson.
|
# The run the complete tests requires you to have built all of simdjson.
|
||||||
#
|
#
|
||||||
|
|
|
@ -89,7 +89,7 @@ if (Git_FOUND AND (GIT_VERSION_STRING VERSION_GREATER "2.1.4") AND (NOT CMAKE_G
|
||||||
# COMMAND ECHO $<TARGET_FILE:perfdiff> \"$<TARGET_FILE:parse> -t ${SIMDJSON_CHECKPERF_ARGS}\" \"${CHECKPERF_PARSE} -t ${SIMDJSON_CHECKPERF_ARGS}\" }
|
# COMMAND ECHO $<TARGET_FILE:perfdiff> \"$<TARGET_FILE:parse> -t ${SIMDJSON_CHECKPERF_ARGS}\" \"${CHECKPERF_PARSE} -t ${SIMDJSON_CHECKPERF_ARGS}\" }
|
||||||
COMMAND $<TARGET_FILE:perfdiff> $<TARGET_FILE:parse> ${CHECKPERF_PARSE} -H -t ${SIMDJSON_CHECKPERF_ARGS}
|
COMMAND $<TARGET_FILE:perfdiff> $<TARGET_FILE:parse> ${CHECKPERF_PARSE} -H -t ${SIMDJSON_CHECKPERF_ARGS}
|
||||||
)
|
)
|
||||||
set_property(TEST checkperf APPEND PROPERTY LABELS per_implementation)
|
set_property(TEST checkperf APPEND PROPERTY LABELS per_implementation explicitonly)
|
||||||
set_property(TEST checkperf APPEND PROPERTY DEPENDS parse perfdiff ${SIMDJSON_USER_CMAKECACHE})
|
set_property(TEST checkperf APPEND PROPERTY DEPENDS parse perfdiff ${SIMDJSON_USER_CMAKECACHE})
|
||||||
set_property(TEST checkperf PROPERTY RUN_SERIAL TRUE)
|
set_property(TEST checkperf PROPERTY RUN_SERIAL TRUE)
|
||||||
else()
|
else()
|
||||||
|
|
|
@ -82,14 +82,14 @@ endif()
|
||||||
if(SIMDJSON_VISUAL_STUDIO_BUILD_WITH_DEBUG_INFO_FOR_PROFILING)
|
if(SIMDJSON_VISUAL_STUDIO_BUILD_WITH_DEBUG_INFO_FOR_PROFILING)
|
||||||
target_link_options(simdjson-flags INTERFACE /DEBUG )
|
target_link_options(simdjson-flags INTERFACE /DEBUG )
|
||||||
target_compile_options(simdjson-flags INTERFACE /Zi)
|
target_compile_options(simdjson-flags INTERFACE /Zi)
|
||||||
endif()
|
endif(SIMDJSON_VISUAL_STUDIO_BUILD_WITH_DEBUG_INFO_FOR_PROFILING)
|
||||||
else()
|
else(MSVC)
|
||||||
if(NOT WIN32)
|
if(NOT WIN32)
|
||||||
target_compile_options(simdjson-internal-flags INTERFACE -fPIC)
|
target_compile_options(simdjson-internal-flags INTERFACE -fPIC)
|
||||||
endif()
|
endif()
|
||||||
target_compile_options(simdjson-internal-flags INTERFACE -Werror -Wall -Wextra -Weffc++)
|
target_compile_options(simdjson-internal-flags INTERFACE -Werror -Wall -Wextra -Weffc++)
|
||||||
target_compile_options(simdjson-internal-flags INTERFACE -Wsign-compare -Wshadow -Wwrite-strings -Wpointer-arith -Winit-self -Wconversion -Wno-sign-conversion)
|
target_compile_options(simdjson-internal-flags INTERFACE -Wsign-compare -Wshadow -Wwrite-strings -Wpointer-arith -Winit-self -Wconversion -Wno-sign-conversion)
|
||||||
endif()
|
endif(MSVC)
|
||||||
|
|
||||||
#
|
#
|
||||||
# Optional flags
|
# Optional flags
|
||||||
|
@ -232,5 +232,9 @@ if(${CMAKE_C_COMPILER_ID} MATCHES "Intel") # icc / icpc
|
||||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -static-intel")
|
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -static-intel")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
include (CheckSymbolExists)
|
||||||
|
CHECK_SYMBOL_EXISTS(fork unistd.h HAVE_POSIX_FORK)
|
||||||
|
CHECK_SYMBOL_EXISTS(wait sys/wait.h HAVE_POSIX_WAIT)
|
||||||
|
|
||||||
install(TARGETS simdjson-flags EXPORT simdjson-config)
|
install(TARGETS simdjson-flags EXPORT simdjson-config)
|
||||||
install(TARGETS simdjson-internal-flags EXPORT simdjson-config)
|
install(TARGETS simdjson-internal-flags EXPORT simdjson-config)
|
||||||
|
|
|
@ -5,13 +5,6 @@ namespace SIMDJSON_IMPLEMENTATION {
|
||||||
// internal::implementation_simdjson_result_base<T> inline implementation
|
// internal::implementation_simdjson_result_base<T> inline implementation
|
||||||
//
|
//
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new empty result with error = UNINITIALIZED.
|
|
||||||
*/
|
|
||||||
template<typename T>
|
|
||||||
simdjson_really_inline implementation_simdjson_result_base<T>::~implementation_simdjson_result_base() noexcept {
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
simdjson_really_inline void implementation_simdjson_result_base<T>::tie(T &value, error_code &error) && noexcept {
|
simdjson_really_inline void implementation_simdjson_result_base<T>::tie(T &value, error_code &error) && noexcept {
|
||||||
// on the clang compiler that comes with current macOS (Apple clang version 11.0.0),
|
// on the clang compiler that comes with current macOS (Apple clang version 11.0.0),
|
||||||
|
@ -70,9 +63,6 @@ simdjson_really_inline implementation_simdjson_result_base<T>::implementation_si
|
||||||
template<typename T>
|
template<typename T>
|
||||||
simdjson_really_inline implementation_simdjson_result_base<T>::implementation_simdjson_result_base(T &&value) noexcept
|
simdjson_really_inline implementation_simdjson_result_base<T>::implementation_simdjson_result_base(T &&value) noexcept
|
||||||
: implementation_simdjson_result_base(std::forward<T>(value), SUCCESS) {}
|
: implementation_simdjson_result_base(std::forward<T>(value), SUCCESS) {}
|
||||||
template<typename T>
|
|
||||||
simdjson_really_inline implementation_simdjson_result_base<T>::implementation_simdjson_result_base() noexcept
|
|
||||||
: implementation_simdjson_result_base(T{}, UNINITIALIZED) {}
|
|
||||||
|
|
||||||
} // namespace SIMDJSON_IMPLEMENTATION
|
} // namespace SIMDJSON_IMPLEMENTATION
|
||||||
} // namespace simdjson
|
} // namespace simdjson
|
|
@ -30,7 +30,7 @@ struct implementation_simdjson_result_base {
|
||||||
/**
|
/**
|
||||||
* Create a new empty result with error = UNINITIALIZED.
|
* Create a new empty result with error = UNINITIALIZED.
|
||||||
*/
|
*/
|
||||||
simdjson_really_inline implementation_simdjson_result_base() noexcept;
|
simdjson_really_inline implementation_simdjson_result_base() noexcept = default;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new error result.
|
* Create a new error result.
|
||||||
|
@ -47,21 +47,6 @@ struct implementation_simdjson_result_base {
|
||||||
*/
|
*/
|
||||||
simdjson_really_inline implementation_simdjson_result_base(T &&value, error_code error) noexcept;
|
simdjson_really_inline implementation_simdjson_result_base(T &&value, error_code error) noexcept;
|
||||||
|
|
||||||
/**
|
|
||||||
* Move a result.
|
|
||||||
*/
|
|
||||||
simdjson_really_inline implementation_simdjson_result_base(implementation_simdjson_result_base<T> &&value) noexcept = default;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copy a result.
|
|
||||||
*/
|
|
||||||
simdjson_really_inline implementation_simdjson_result_base(const implementation_simdjson_result_base<T> &value) = default;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new empty result with error = UNINITIALIZED.
|
|
||||||
*/
|
|
||||||
simdjson_really_inline ~implementation_simdjson_result_base() noexcept;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Move the value and the error to the provided variables.
|
* Move the value and the error to the provided variables.
|
||||||
*
|
*
|
||||||
|
@ -114,8 +99,8 @@ struct implementation_simdjson_result_base {
|
||||||
|
|
||||||
#endif // SIMDJSON_EXCEPTIONS
|
#endif // SIMDJSON_EXCEPTIONS
|
||||||
|
|
||||||
T first;
|
T first{};
|
||||||
error_code second;
|
error_code second{UNINITIALIZED};
|
||||||
}; // struct implementation_simdjson_result_base
|
}; // struct implementation_simdjson_result_base
|
||||||
|
|
||||||
} // namespace SIMDJSON_IMPLEMENTATION
|
} // namespace SIMDJSON_IMPLEMENTATION
|
||||||
|
|
|
@ -8,9 +8,6 @@ simdjson_really_inline document::document(ondemand::json_iterator &&_iter) noexc
|
||||||
logger::log_start_value(iter, "document");
|
logger::log_start_value(iter, "document");
|
||||||
}
|
}
|
||||||
|
|
||||||
simdjson_really_inline void document::assert_at_start() const noexcept {
|
|
||||||
iter.assert_at_start();
|
|
||||||
}
|
|
||||||
simdjson_really_inline document document::start(json_iterator &&iter) noexcept {
|
simdjson_really_inline document document::start(json_iterator &&iter) noexcept {
|
||||||
return document(std::forward<json_iterator>(iter));
|
return document(std::forward<json_iterator>(iter));
|
||||||
}
|
}
|
||||||
|
@ -19,8 +16,11 @@ simdjson_really_inline value document::as_value() noexcept {
|
||||||
return as_value_iterator();
|
return as_value_iterator();
|
||||||
}
|
}
|
||||||
simdjson_really_inline value_iterator document::as_value_iterator() noexcept {
|
simdjson_really_inline value_iterator document::as_value_iterator() noexcept {
|
||||||
assert_at_start();
|
iter.assert_at_root();
|
||||||
return value_iterator(&iter, 1);
|
return value_iterator(&iter, 1, iter.root_checkpoint());
|
||||||
|
}
|
||||||
|
simdjson_really_inline value_iterator document::as_non_root_value_iterator() noexcept {
|
||||||
|
return value_iterator(&iter, 1, iter.root_checkpoint());
|
||||||
}
|
}
|
||||||
|
|
||||||
simdjson_really_inline simdjson_result<array> document::get_array() & noexcept {
|
simdjson_really_inline simdjson_result<array> document::get_array() & noexcept {
|
||||||
|
@ -30,15 +30,12 @@ simdjson_really_inline simdjson_result<object> document::get_object() & noexcept
|
||||||
return as_value().get_object();
|
return as_value().get_object();
|
||||||
}
|
}
|
||||||
simdjson_really_inline simdjson_result<uint64_t> document::get_uint64() noexcept {
|
simdjson_really_inline simdjson_result<uint64_t> document::get_uint64() noexcept {
|
||||||
assert_at_start();
|
|
||||||
return as_value_iterator().require_root_uint64();
|
return as_value_iterator().require_root_uint64();
|
||||||
}
|
}
|
||||||
simdjson_really_inline simdjson_result<int64_t> document::get_int64() noexcept {
|
simdjson_really_inline simdjson_result<int64_t> document::get_int64() noexcept {
|
||||||
assert_at_start();
|
|
||||||
return as_value_iterator().require_root_int64();
|
return as_value_iterator().require_root_int64();
|
||||||
}
|
}
|
||||||
simdjson_really_inline simdjson_result<double> document::get_double() noexcept {
|
simdjson_really_inline simdjson_result<double> document::get_double() noexcept {
|
||||||
assert_at_start();
|
|
||||||
return as_value_iterator().require_root_double();
|
return as_value_iterator().require_root_double();
|
||||||
}
|
}
|
||||||
simdjson_really_inline simdjson_result<std::string_view> document::get_string() & noexcept {
|
simdjson_really_inline simdjson_result<std::string_view> document::get_string() & noexcept {
|
||||||
|
@ -48,11 +45,9 @@ simdjson_really_inline simdjson_result<raw_json_string> document::get_raw_json_s
|
||||||
return as_value().get_raw_json_string();
|
return as_value().get_raw_json_string();
|
||||||
}
|
}
|
||||||
simdjson_really_inline simdjson_result<bool> document::get_bool() noexcept {
|
simdjson_really_inline simdjson_result<bool> document::get_bool() noexcept {
|
||||||
assert_at_start();
|
|
||||||
return as_value_iterator().require_root_bool();
|
return as_value_iterator().require_root_bool();
|
||||||
}
|
}
|
||||||
simdjson_really_inline bool document::is_null() noexcept {
|
simdjson_really_inline bool document::is_null() noexcept {
|
||||||
assert_at_start();
|
|
||||||
return as_value_iterator().is_root_null();
|
return as_value_iterator().is_root_null();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,10 +90,20 @@ simdjson_really_inline simdjson_result<array_iterator> document::end() & noexcep
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
simdjson_really_inline simdjson_result<value> document::operator[](std::string_view key) & noexcept {
|
simdjson_really_inline simdjson_result<value> document::operator[](std::string_view key) & noexcept {
|
||||||
|
if (iter.at_root()) {
|
||||||
return get_object()[key];
|
return get_object()[key];
|
||||||
|
} else {
|
||||||
|
// If we're not at the root, this is not the first key we've grabbed
|
||||||
|
return object::resume(as_non_root_value_iterator())[key];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
simdjson_really_inline simdjson_result<value> document::operator[](const char *key) & noexcept {
|
simdjson_really_inline simdjson_result<value> document::operator[](const char *key) & noexcept {
|
||||||
|
if (iter.at_root()) {
|
||||||
return get_object()[key];
|
return get_object()[key];
|
||||||
|
} else {
|
||||||
|
// If we're not at the root, this is not the first key we've grabbed
|
||||||
|
return object::resume(as_non_root_value_iterator())[key];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ondemand
|
} // namespace ondemand
|
||||||
|
|
|
@ -20,17 +20,16 @@ class array_iterator;
|
||||||
*/
|
*/
|
||||||
class document {
|
class document {
|
||||||
public:
|
public:
|
||||||
simdjson_really_inline document(document &&other) noexcept = default;
|
|
||||||
simdjson_really_inline document &operator=(document &&other) noexcept = default;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new invalid document.
|
* Create a new invalid document.
|
||||||
*
|
*
|
||||||
* 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) = delete;
|
simdjson_really_inline document(const document &other) noexcept = delete;
|
||||||
simdjson_really_inline document &operator=(const document &other) = delete;
|
simdjson_really_inline document(document &&other) noexcept = default;
|
||||||
|
simdjson_really_inline document &operator=(const document &other) noexcept = delete;
|
||||||
|
simdjson_really_inline document &operator=(document &&other) noexcept = default;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cast this JSON value to an array.
|
* Cast this JSON value to an array.
|
||||||
|
@ -230,10 +229,9 @@ protected:
|
||||||
|
|
||||||
simdjson_really_inline value as_value() noexcept;
|
simdjson_really_inline value as_value() noexcept;
|
||||||
simdjson_really_inline value_iterator as_value_iterator() noexcept;
|
simdjson_really_inline value_iterator as_value_iterator() noexcept;
|
||||||
|
simdjson_really_inline value_iterator as_non_root_value_iterator() noexcept;
|
||||||
static simdjson_really_inline document start(ondemand::json_iterator &&iter) noexcept;
|
static simdjson_really_inline document start(ondemand::json_iterator &&iter) noexcept;
|
||||||
|
|
||||||
simdjson_really_inline void assert_at_start() const noexcept;
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Fields
|
// Fields
|
||||||
//
|
//
|
||||||
|
@ -261,10 +259,7 @@ struct simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document> : public SIM
|
||||||
public:
|
public:
|
||||||
simdjson_really_inline simdjson_result(SIMDJSON_IMPLEMENTATION::ondemand::document &&value) noexcept; ///< @private
|
simdjson_really_inline simdjson_result(SIMDJSON_IMPLEMENTATION::ondemand::document &&value) noexcept; ///< @private
|
||||||
simdjson_really_inline simdjson_result(error_code error) noexcept; ///< @private
|
simdjson_really_inline simdjson_result(error_code error) noexcept; ///< @private
|
||||||
|
|
||||||
simdjson_really_inline simdjson_result() noexcept = default;
|
simdjson_really_inline simdjson_result() noexcept = default;
|
||||||
simdjson_really_inline simdjson_result(simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document> &&a) noexcept = default;
|
|
||||||
simdjson_really_inline ~simdjson_result() noexcept = default; ///< @private
|
|
||||||
|
|
||||||
simdjson_really_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array> get_array() & 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<SIMDJSON_IMPLEMENTATION::ondemand::object> get_object() & noexcept;
|
||||||
|
|
|
@ -90,11 +90,15 @@ simdjson_warn_unused simdjson_really_inline error_code json_iterator::skip_child
|
||||||
return report_error(TAPE_ERROR, "not enough close braces");
|
return report_error(TAPE_ERROR, "not enough close braces");
|
||||||
}
|
}
|
||||||
|
|
||||||
simdjson_really_inline bool json_iterator::at_start() const noexcept {
|
simdjson_really_inline bool json_iterator::at_root() const noexcept {
|
||||||
return token.index == &parser->dom_parser.structural_indexes[0];
|
return token.checkpoint() == root_checkpoint();
|
||||||
}
|
}
|
||||||
|
|
||||||
simdjson_really_inline void json_iterator::assert_at_start() const noexcept {
|
simdjson_really_inline const uint32_t *json_iterator::root_checkpoint() const noexcept {
|
||||||
|
return parser->dom_parser.structural_indexes.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
simdjson_really_inline void json_iterator::assert_at_root() const noexcept {
|
||||||
SIMDJSON_ASSUME( _depth == 1 );
|
SIMDJSON_ASSUME( _depth == 1 );
|
||||||
// Visual Studio Clang treats unique_ptr.get() as "side effecting."
|
// Visual Studio Clang treats unique_ptr.get() as "side effecting."
|
||||||
#ifndef SIMDJSON_CLANG_VISUAL_STUDIO
|
#ifndef SIMDJSON_CLANG_VISUAL_STUDIO
|
||||||
|
|
|
@ -60,12 +60,17 @@ public:
|
||||||
/**
|
/**
|
||||||
* Tell whether the iterator is still at the start
|
* Tell whether the iterator is still at the start
|
||||||
*/
|
*/
|
||||||
simdjson_really_inline bool at_start() const noexcept;
|
simdjson_really_inline bool at_root() const noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the root value iterator
|
||||||
|
*/
|
||||||
|
simdjson_really_inline const uint32_t *root_checkpoint() const noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Assert if the iterator is not at the start
|
* Assert if the iterator is not at the start
|
||||||
*/
|
*/
|
||||||
simdjson_really_inline void assert_at_start() const noexcept;
|
simdjson_really_inline void assert_at_root() const noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tell whether the iterator is at the EOF mark
|
* Tell whether the iterator is at the EOF mark
|
||||||
|
@ -184,8 +189,6 @@ public:
|
||||||
simdjson_really_inline simdjson_result(error_code error) noexcept; ///< @private
|
simdjson_really_inline simdjson_result(error_code error) noexcept; ///< @private
|
||||||
|
|
||||||
simdjson_really_inline simdjson_result() noexcept = default;
|
simdjson_really_inline simdjson_result() noexcept = default;
|
||||||
simdjson_really_inline simdjson_result(simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::json_iterator> &&a) noexcept = default;
|
|
||||||
simdjson_really_inline ~simdjson_result() noexcept = default; ///< @private
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace simdjson
|
} // namespace simdjson
|
||||||
|
|
|
@ -43,18 +43,18 @@ namespace ondemand {
|
||||||
// In this state, iter.depth < depth, at_start == false, and error == SUCCESS.
|
// In this state, iter.depth < depth, at_start == false, and error == SUCCESS.
|
||||||
//
|
//
|
||||||
|
|
||||||
simdjson_warn_unused simdjson_really_inline error_code object::find_field_raw(const std::string_view key) noexcept {
|
|
||||||
return iter.find_field_raw(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
simdjson_really_inline simdjson_result<value> object::operator[](const std::string_view key) & noexcept {
|
simdjson_really_inline simdjson_result<value> object::operator[](const std::string_view key) & noexcept {
|
||||||
SIMDJSON_TRY( find_field_raw(key) );
|
bool has_value;
|
||||||
return value(iter.iter.child());
|
SIMDJSON_TRY( iter.find_field_raw(key).get(has_value) );
|
||||||
|
if (!has_value) { return NO_SUCH_FIELD; }
|
||||||
|
return value(iter.child());
|
||||||
}
|
}
|
||||||
|
|
||||||
simdjson_really_inline simdjson_result<value> object::operator[](const std::string_view key) && noexcept {
|
simdjson_really_inline simdjson_result<value> object::operator[](const std::string_view key) && noexcept {
|
||||||
SIMDJSON_TRY( find_field_raw(key) );
|
bool has_value;
|
||||||
return value(iter.iter.child());
|
SIMDJSON_TRY( iter.find_field_raw(key).get(has_value) );
|
||||||
|
if (!has_value) { return NO_SUCH_FIELD; }
|
||||||
|
return value(iter.child());
|
||||||
}
|
}
|
||||||
|
|
||||||
simdjson_really_inline simdjson_result<object> object::start(value_iterator &iter) noexcept {
|
simdjson_really_inline simdjson_result<object> object::start(value_iterator &iter) noexcept {
|
||||||
|
@ -71,6 +71,9 @@ simdjson_really_inline object object::started(value_iterator &iter) noexcept {
|
||||||
simdjson_unused bool has_value = iter.started_object();
|
simdjson_unused bool has_value = iter.started_object();
|
||||||
return iter;
|
return iter;
|
||||||
}
|
}
|
||||||
|
simdjson_really_inline object object::resume(const value_iterator &iter) noexcept {
|
||||||
|
return iter;
|
||||||
|
}
|
||||||
|
|
||||||
simdjson_really_inline object::object(const value_iterator &_iter) noexcept
|
simdjson_really_inline object::object(const value_iterator &_iter) noexcept
|
||||||
: iter{_iter}
|
: iter{_iter}
|
||||||
|
@ -78,7 +81,8 @@ simdjson_really_inline object::object(const value_iterator &_iter) noexcept
|
||||||
}
|
}
|
||||||
|
|
||||||
simdjson_really_inline object_iterator object::begin() noexcept {
|
simdjson_really_inline object_iterator object::begin() noexcept {
|
||||||
SIMDJSON_ASSUME( iter.at_start || iter.iter._json_iter->_depth < iter.iter._depth );
|
// Expanded version of SIMDJSON_ASSUME( iter.at_field_start() || !iter.is_open() )
|
||||||
|
SIMDJSON_ASSUME( (iter._json_iter->token.index == iter._start_index + 1) || (iter._json_iter->_depth < iter._depth) );
|
||||||
return iter;
|
return iter;
|
||||||
}
|
}
|
||||||
simdjson_really_inline object_iterator object::end() noexcept {
|
simdjson_really_inline object_iterator object::end() noexcept {
|
||||||
|
|
|
@ -49,11 +49,12 @@ protected:
|
||||||
static simdjson_really_inline simdjson_result<object> start(value_iterator &iter) noexcept;
|
static simdjson_really_inline simdjson_result<object> start(value_iterator &iter) noexcept;
|
||||||
static simdjson_really_inline simdjson_result<object> try_start(value_iterator &iter) noexcept;
|
static simdjson_really_inline simdjson_result<object> try_start(value_iterator &iter) noexcept;
|
||||||
static simdjson_really_inline object started(value_iterator &iter) noexcept;
|
static simdjson_really_inline object started(value_iterator &iter) noexcept;
|
||||||
simdjson_really_inline object(const value_iterator &_iter) noexcept;
|
static simdjson_really_inline object resume(const value_iterator &iter) noexcept;
|
||||||
|
simdjson_really_inline object(const value_iterator &iter) noexcept;
|
||||||
|
|
||||||
simdjson_warn_unused simdjson_really_inline error_code find_field_raw(const std::string_view key) noexcept;
|
simdjson_warn_unused simdjson_really_inline error_code find_field_raw(const std::string_view key) noexcept;
|
||||||
|
|
||||||
object_iterator iter{};
|
value_iterator iter{};
|
||||||
|
|
||||||
friend class value;
|
friend class value;
|
||||||
friend class document;
|
friend class document;
|
||||||
|
|
|
@ -7,8 +7,7 @@ namespace ondemand {
|
||||||
//
|
//
|
||||||
|
|
||||||
simdjson_really_inline object_iterator::object_iterator(const value_iterator &_iter) noexcept
|
simdjson_really_inline object_iterator::object_iterator(const value_iterator &_iter) noexcept
|
||||||
: iter{_iter},
|
: iter{_iter}
|
||||||
at_start{true}
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
simdjson_really_inline simdjson_result<field> object_iterator::operator*() noexcept {
|
simdjson_really_inline simdjson_result<field> object_iterator::operator*() noexcept {
|
||||||
|
@ -80,39 +79,6 @@ simdjson_really_inline object_iterator &object_iterator::operator++() noexcept {
|
||||||
// In this state, iter.depth < depth, at_start == false, and error == SUCCESS.
|
// In this state, iter.depth < depth, at_start == false, and error == SUCCESS.
|
||||||
//
|
//
|
||||||
|
|
||||||
simdjson_warn_unused simdjson_really_inline error_code object_iterator::find_field_raw(const std::string_view key) noexcept {
|
|
||||||
if (!iter.is_open()) { return NO_SUCH_FIELD; }
|
|
||||||
|
|
||||||
// Unless this is the first field, we need to advance past the , and check for }
|
|
||||||
error_code error;
|
|
||||||
bool has_value;
|
|
||||||
if (at_start) {
|
|
||||||
at_start = false;
|
|
||||||
has_value = true;
|
|
||||||
} else {
|
|
||||||
if ((error = iter.skip_child() )) { iter.abandon(); return error; }
|
|
||||||
if ((error = iter.has_next_field().get(has_value) )) { iter.abandon(); return error; }
|
|
||||||
}
|
|
||||||
while (has_value) {
|
|
||||||
// Get the key
|
|
||||||
raw_json_string actual_key;
|
|
||||||
if ((error = iter.field_key().get(actual_key) )) { iter.abandon(); return error; };
|
|
||||||
if ((error = iter.field_value() )) { iter.abandon(); return error; }
|
|
||||||
|
|
||||||
// Check if it matches
|
|
||||||
if (actual_key == key) {
|
|
||||||
logger::log_event(iter, "match", key, -2);
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
|
||||||
logger::log_event(iter, "no match", key, -2);
|
|
||||||
SIMDJSON_TRY( iter.skip_child() ); // Skip the value entirely
|
|
||||||
if ((error = iter.has_next_field().get(has_value) )) { iter.abandon(); return error; }
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the loop ended, we're out of fields to look at.
|
|
||||||
return NO_SUCH_FIELD;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace ondemand
|
} // namespace ondemand
|
||||||
} // namespace SIMDJSON_IMPLEMENTATION
|
} // namespace SIMDJSON_IMPLEMENTATION
|
||||||
} // namespace simdjson
|
} // namespace simdjson
|
||||||
|
|
|
@ -29,11 +29,6 @@ public:
|
||||||
// Checks for ']' and ','
|
// Checks for ']' and ','
|
||||||
simdjson_really_inline object_iterator &operator++() noexcept;
|
simdjson_really_inline object_iterator &operator++() noexcept;
|
||||||
|
|
||||||
/**
|
|
||||||
* Find the field with the given key. May be used in place of ++.
|
|
||||||
*/
|
|
||||||
simdjson_warn_unused simdjson_really_inline error_code find_field_raw(const std::string_view key) noexcept;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* The underlying JSON iterator.
|
* The underlying JSON iterator.
|
||||||
|
@ -42,15 +37,6 @@ private:
|
||||||
* is first used, and never changes afterwards.
|
* is first used, and never changes afterwards.
|
||||||
*/
|
*/
|
||||||
value_iterator iter{};
|
value_iterator iter{};
|
||||||
/**
|
|
||||||
* Whether we are at the start.
|
|
||||||
*
|
|
||||||
* PERF NOTE: this should be elided into inline control flow: it is only used for the first []
|
|
||||||
* or * call, and SSA optimizers commonly do first-iteration loop optimization.
|
|
||||||
*
|
|
||||||
* SAFETY: this is not safe; the object_iterator can be copied freely, so the state CAN be lost.
|
|
||||||
*/
|
|
||||||
bool at_start{};
|
|
||||||
|
|
||||||
simdjson_really_inline object_iterator(const value_iterator &iter) noexcept;
|
simdjson_really_inline object_iterator(const value_iterator &iter) noexcept;
|
||||||
friend struct simdjson_result<object_iterator>;
|
friend struct simdjson_result<object_iterator>;
|
||||||
|
|
|
@ -130,10 +130,7 @@ struct simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::parser> : public SIMDJ
|
||||||
public:
|
public:
|
||||||
simdjson_really_inline simdjson_result(SIMDJSON_IMPLEMENTATION::ondemand::parser &&value) noexcept; ///< @private
|
simdjson_really_inline simdjson_result(SIMDJSON_IMPLEMENTATION::ondemand::parser &&value) noexcept; ///< @private
|
||||||
simdjson_really_inline simdjson_result(error_code error) noexcept; ///< @private
|
simdjson_really_inline simdjson_result(error_code error) noexcept; ///< @private
|
||||||
|
|
||||||
simdjson_really_inline simdjson_result() noexcept = default;
|
simdjson_really_inline simdjson_result() noexcept = default;
|
||||||
simdjson_really_inline simdjson_result(simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::parser> &&a) noexcept = default;
|
|
||||||
simdjson_really_inline ~simdjson_result() noexcept = default; ///< @private
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace simdjson
|
} // namespace simdjson
|
||||||
|
|
|
@ -109,9 +109,7 @@ struct simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string> : pub
|
||||||
public:
|
public:
|
||||||
simdjson_really_inline simdjson_result(SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string &&value) noexcept; ///< @private
|
simdjson_really_inline simdjson_result(SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string &&value) noexcept; ///< @private
|
||||||
simdjson_really_inline simdjson_result(error_code error) noexcept; ///< @private
|
simdjson_really_inline simdjson_result(error_code error) noexcept; ///< @private
|
||||||
|
|
||||||
simdjson_really_inline simdjson_result() noexcept = default;
|
simdjson_really_inline simdjson_result() noexcept = default;
|
||||||
simdjson_really_inline simdjson_result(const simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string> &a) noexcept = default;
|
|
||||||
simdjson_really_inline ~simdjson_result() noexcept = default; ///< @private
|
simdjson_really_inline ~simdjson_result() noexcept = default; ///< @private
|
||||||
|
|
||||||
simdjson_really_inline simdjson_result<const char *> raw() const noexcept;
|
simdjson_really_inline simdjson_result<const char *> raw() const noexcept;
|
||||||
|
|
|
@ -39,6 +39,10 @@ simdjson_really_inline bool token_iterator::operator<=(const token_iterator &oth
|
||||||
return index <= other.index;
|
return index <= other.index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
simdjson_really_inline const uint32_t *token_iterator::checkpoint() const noexcept {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ondemand
|
} // namespace ondemand
|
||||||
} // namespace SIMDJSON_IMPLEMENTATION
|
} // namespace SIMDJSON_IMPLEMENTATION
|
||||||
} // namespace simdjson
|
} // namespace simdjson
|
||||||
|
|
|
@ -49,6 +49,11 @@ public:
|
||||||
*/
|
*/
|
||||||
simdjson_really_inline const uint8_t *advance() noexcept;
|
simdjson_really_inline const uint8_t *advance() noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save the current index to be restored later.
|
||||||
|
*/
|
||||||
|
simdjson_really_inline const uint32_t *checkpoint() const noexcept;
|
||||||
|
|
||||||
// NOTE: we don't support a full C++ iterator interface, because we expect people to make
|
// NOTE: we don't support a full C++ iterator interface, because we expect people to make
|
||||||
// different calls to advance the iterator based on *their own* state.
|
// different calls to advance the iterator based on *their own* state.
|
||||||
|
|
||||||
|
@ -77,6 +82,8 @@ protected:
|
||||||
const uint32_t *index{};
|
const uint32_t *index{};
|
||||||
|
|
||||||
friend class json_iterator;
|
friend class json_iterator;
|
||||||
|
friend class value_iterator;
|
||||||
|
friend class object;
|
||||||
friend simdjson_really_inline void logger::log_line(const json_iterator &iter, const char *title_prefix, const char *title, std::string_view detail, int delta, int depth_delta) noexcept;
|
friend simdjson_really_inline void logger::log_line(const json_iterator &iter, const char *title_prefix, const char *title, std::string_view detail, int delta, int depth_delta) noexcept;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -91,9 +98,7 @@ struct simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::token_iterator> : publ
|
||||||
public:
|
public:
|
||||||
simdjson_really_inline simdjson_result(SIMDJSON_IMPLEMENTATION::ondemand::token_iterator &&value) noexcept; ///< @private
|
simdjson_really_inline simdjson_result(SIMDJSON_IMPLEMENTATION::ondemand::token_iterator &&value) noexcept; ///< @private
|
||||||
simdjson_really_inline simdjson_result(error_code error) noexcept; ///< @private
|
simdjson_really_inline simdjson_result(error_code error) noexcept; ///< @private
|
||||||
|
|
||||||
simdjson_really_inline simdjson_result() noexcept = default;
|
simdjson_really_inline simdjson_result() noexcept = default;
|
||||||
simdjson_really_inline simdjson_result(simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::token_iterator> &&a) noexcept = default;
|
|
||||||
simdjson_really_inline ~simdjson_result() noexcept = default; ///< @private
|
simdjson_really_inline ~simdjson_result() noexcept = default; ///< @private
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -2,20 +2,21 @@ namespace simdjson {
|
||||||
namespace SIMDJSON_IMPLEMENTATION {
|
namespace SIMDJSON_IMPLEMENTATION {
|
||||||
namespace ondemand {
|
namespace ondemand {
|
||||||
|
|
||||||
simdjson_really_inline value_iterator::value_iterator(json_iterator *json_iter, depth_t depth) noexcept
|
simdjson_really_inline value_iterator::value_iterator(json_iterator *json_iter, depth_t depth, const uint32_t *start_index) noexcept
|
||||||
: _json_iter{json_iter},
|
: _json_iter{json_iter},
|
||||||
_depth{depth}
|
_depth{depth},
|
||||||
|
_start_index{start_index}
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator::start_object() noexcept {
|
simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator::start_object() noexcept {
|
||||||
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth > 0 );
|
assert_at_start();
|
||||||
|
|
||||||
if (*_json_iter->advance() != '{') { logger::log_error(*_json_iter, "Not an object"); return INCORRECT_TYPE; }
|
if (*_json_iter->advance() != '{') { logger::log_error(*_json_iter, "Not an object"); return INCORRECT_TYPE; }
|
||||||
return started_object();
|
return started_object();
|
||||||
}
|
}
|
||||||
simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator::try_start_object() noexcept {
|
simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator::try_start_object() noexcept {
|
||||||
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth > 0 );
|
assert_at_start();
|
||||||
|
|
||||||
if (*_json_iter->peek() != '{') { logger::log_error(*_json_iter, "Not an object"); return INCORRECT_TYPE; }
|
if (*_json_iter->peek() != '{') { logger::log_error(*_json_iter, "Not an object"); return INCORRECT_TYPE; }
|
||||||
_json_iter->advance();
|
_json_iter->advance();
|
||||||
|
@ -23,8 +24,6 @@ simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator
|
||||||
}
|
}
|
||||||
|
|
||||||
simdjson_warn_unused simdjson_really_inline bool value_iterator::started_object() noexcept {
|
simdjson_warn_unused simdjson_really_inline bool value_iterator::started_object() noexcept {
|
||||||
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth > 0 );
|
|
||||||
|
|
||||||
if (*_json_iter->peek() == '}') {
|
if (*_json_iter->peek() == '}') {
|
||||||
logger::log_value(*_json_iter, "empty object");
|
logger::log_value(*_json_iter, "empty object");
|
||||||
_json_iter->advance();
|
_json_iter->advance();
|
||||||
|
@ -37,7 +36,7 @@ simdjson_warn_unused simdjson_really_inline bool value_iterator::started_object(
|
||||||
}
|
}
|
||||||
|
|
||||||
simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator::has_next_field() noexcept {
|
simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator::has_next_field() noexcept {
|
||||||
SIMDJSON_ASSUME( _json_iter->_depth == _depth );
|
assert_at_next();
|
||||||
|
|
||||||
switch (*_json_iter->advance()) {
|
switch (*_json_iter->advance()) {
|
||||||
case '}':
|
case '}':
|
||||||
|
@ -52,36 +51,43 @@ simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator::find_field_raw(const char *key) noexcept {
|
/**
|
||||||
// We assume we are sitting at a key: at "key": <value>
|
* Find the field with the given key. May be used in place of ++.
|
||||||
SIMDJSON_ASSUME( _json_iter->_depth == _depth+1 );
|
*/
|
||||||
|
simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator::find_field_raw(const std::string_view key) noexcept {
|
||||||
|
if (!is_open()) { return false; }
|
||||||
|
|
||||||
bool has_next;
|
// Unless this is the first field, we need to advance past the , and check for }
|
||||||
do {
|
error_code error;
|
||||||
|
bool has_value;
|
||||||
|
if (at_first_field()) {
|
||||||
|
has_value = true;
|
||||||
|
} else {
|
||||||
|
if ((error = skip_child() )) { abandon(); return error; }
|
||||||
|
if ((error = has_next_field().get(has_value) )) { abandon(); return error; }
|
||||||
|
}
|
||||||
|
while (has_value) {
|
||||||
// Get the key
|
// Get the key
|
||||||
raw_json_string actual_key;
|
raw_json_string actual_key;
|
||||||
SIMDJSON_TRY( require_raw_json_string().get(actual_key) );
|
if ((error = field_key().get(actual_key) )) { abandon(); return error; };
|
||||||
if (*_json_iter->advance() != ':') { return _json_iter->report_error(TAPE_ERROR, "Missing colon in object field"); }
|
if ((error = field_value() )) { abandon(); return error; }
|
||||||
|
|
||||||
// Check if the key matches, and return if so
|
// Check if it matches
|
||||||
if (actual_key == key) {
|
if (actual_key == key) {
|
||||||
logger::log_event(*_json_iter, "match", key);
|
logger::log_event(*this, "match", key, -2);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
logger::log_event(*this, "no match", key, -2);
|
||||||
|
SIMDJSON_TRY( skip_child() ); // Skip the value entirely
|
||||||
|
if ((error = has_next_field().get(has_value) )) { abandon(); return error; }
|
||||||
|
}
|
||||||
|
|
||||||
// Skip the value so we can look at the next key
|
// If the loop ended, we're out of fields to look at.
|
||||||
logger::log_event(*_json_iter, "non-match", key);
|
|
||||||
SIMDJSON_TRY( skip_child() );
|
|
||||||
|
|
||||||
// Check whether the next token is , or }
|
|
||||||
SIMDJSON_TRY( has_next_field().get(has_next) );
|
|
||||||
} while (has_next);
|
|
||||||
logger::log_event(*_json_iter, "no matches", key);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
simdjson_warn_unused simdjson_really_inline simdjson_result<raw_json_string> value_iterator::field_key() noexcept {
|
simdjson_warn_unused simdjson_really_inline simdjson_result<raw_json_string> value_iterator::field_key() noexcept {
|
||||||
SIMDJSON_ASSUME( _json_iter->_depth == _depth+1 );
|
assert_at_child();
|
||||||
|
|
||||||
const uint8_t *key = _json_iter->advance();
|
const uint8_t *key = _json_iter->advance();
|
||||||
if (*(key++) != '"') { return _json_iter->report_error(TAPE_ERROR, "Object key is not a string"); }
|
if (*(key++) != '"') { return _json_iter->report_error(TAPE_ERROR, "Object key is not a string"); }
|
||||||
|
@ -89,21 +95,21 @@ simdjson_warn_unused simdjson_really_inline simdjson_result<raw_json_string> val
|
||||||
}
|
}
|
||||||
|
|
||||||
simdjson_warn_unused simdjson_really_inline error_code value_iterator::field_value() noexcept {
|
simdjson_warn_unused simdjson_really_inline error_code value_iterator::field_value() noexcept {
|
||||||
SIMDJSON_ASSUME( _json_iter->_depth == _depth+1 );
|
assert_at_child();
|
||||||
|
|
||||||
if (*_json_iter->advance() != ':') { return _json_iter->report_error(TAPE_ERROR, "Missing colon in object field"); }
|
if (*_json_iter->advance() != ':') { return _json_iter->report_error(TAPE_ERROR, "Missing colon in object field"); }
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator::start_array() noexcept {
|
simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator::start_array() noexcept {
|
||||||
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth > 0);
|
assert_at_start();
|
||||||
|
|
||||||
if (*_json_iter->advance() != '[') { logger::log_error(*_json_iter, "Not an array"); return INCORRECT_TYPE; }
|
if (*_json_iter->advance() != '[') { logger::log_error(*_json_iter, "Not an array"); return INCORRECT_TYPE; }
|
||||||
return started_array();
|
return started_array();
|
||||||
}
|
}
|
||||||
|
|
||||||
simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator::try_start_array() noexcept {
|
simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator::try_start_array() noexcept {
|
||||||
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth > 0);
|
assert_at_start();
|
||||||
|
|
||||||
if (*_json_iter->peek() != '[') { logger::log_error(*_json_iter, "Not an array"); return INCORRECT_TYPE; }
|
if (*_json_iter->peek() != '[') { logger::log_error(*_json_iter, "Not an array"); return INCORRECT_TYPE; }
|
||||||
_json_iter->advance();
|
_json_iter->advance();
|
||||||
|
@ -111,8 +117,6 @@ simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator
|
||||||
}
|
}
|
||||||
|
|
||||||
simdjson_warn_unused simdjson_really_inline bool value_iterator::started_array() noexcept {
|
simdjson_warn_unused simdjson_really_inline bool value_iterator::started_array() noexcept {
|
||||||
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth > 0 );
|
|
||||||
|
|
||||||
if (*_json_iter->peek() == ']') {
|
if (*_json_iter->peek() == ']') {
|
||||||
logger::log_value(*_json_iter, "empty array");
|
logger::log_value(*_json_iter, "empty array");
|
||||||
_json_iter->advance();
|
_json_iter->advance();
|
||||||
|
@ -125,7 +129,7 @@ simdjson_warn_unused simdjson_really_inline bool value_iterator::started_array()
|
||||||
}
|
}
|
||||||
|
|
||||||
simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator::has_next_element() noexcept {
|
simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator::has_next_element() noexcept {
|
||||||
SIMDJSON_ASSUME( _json_iter->_depth == _depth );
|
assert_at_next();
|
||||||
|
|
||||||
switch (*_json_iter->advance()) {
|
switch (*_json_iter->advance()) {
|
||||||
case ']':
|
case ']':
|
||||||
|
@ -147,7 +151,7 @@ simdjson_warn_unused simdjson_really_inline simdjson_result<std::string_view> va
|
||||||
return require_raw_json_string().unescape(_json_iter->string_buf_loc());
|
return require_raw_json_string().unescape(_json_iter->string_buf_loc());
|
||||||
}
|
}
|
||||||
simdjson_warn_unused simdjson_really_inline simdjson_result<raw_json_string> value_iterator::try_get_raw_json_string() noexcept {
|
simdjson_warn_unused simdjson_really_inline simdjson_result<raw_json_string> value_iterator::try_get_raw_json_string() noexcept {
|
||||||
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth > 0 );
|
assert_at_start();
|
||||||
|
|
||||||
logger::log_value(*_json_iter, "string", "", 0);
|
logger::log_value(*_json_iter, "string", "", 0);
|
||||||
auto json = _json_iter->peek();
|
auto json = _json_iter->peek();
|
||||||
|
@ -157,7 +161,7 @@ simdjson_warn_unused simdjson_really_inline simdjson_result<raw_json_string> val
|
||||||
return raw_json_string(json+1);
|
return raw_json_string(json+1);
|
||||||
}
|
}
|
||||||
simdjson_warn_unused simdjson_really_inline simdjson_result<raw_json_string> value_iterator::require_raw_json_string() noexcept {
|
simdjson_warn_unused simdjson_really_inline simdjson_result<raw_json_string> value_iterator::require_raw_json_string() noexcept {
|
||||||
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth > 0 );
|
assert_at_start();
|
||||||
|
|
||||||
logger::log_value(*_json_iter, "string", "", 0);
|
logger::log_value(*_json_iter, "string", "", 0);
|
||||||
auto json = _json_iter->advance();
|
auto json = _json_iter->advance();
|
||||||
|
@ -166,7 +170,7 @@ simdjson_warn_unused simdjson_really_inline simdjson_result<raw_json_string> val
|
||||||
return raw_json_string(json+1);
|
return raw_json_string(json+1);
|
||||||
}
|
}
|
||||||
simdjson_warn_unused simdjson_really_inline simdjson_result<uint64_t> value_iterator::try_get_uint64() noexcept {
|
simdjson_warn_unused simdjson_really_inline simdjson_result<uint64_t> value_iterator::try_get_uint64() noexcept {
|
||||||
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth > 1 );
|
assert_at_non_root_start();
|
||||||
|
|
||||||
logger::log_value(*_json_iter, "uint64", "", 0);
|
logger::log_value(*_json_iter, "uint64", "", 0);
|
||||||
uint64_t result;
|
uint64_t result;
|
||||||
|
@ -176,14 +180,14 @@ simdjson_warn_unused simdjson_really_inline simdjson_result<uint64_t> value_iter
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
simdjson_warn_unused simdjson_really_inline simdjson_result<uint64_t> value_iterator::require_uint64() noexcept {
|
simdjson_warn_unused simdjson_really_inline simdjson_result<uint64_t> value_iterator::require_uint64() noexcept {
|
||||||
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth > 1 );
|
assert_at_non_root_start();
|
||||||
|
|
||||||
logger::log_value(*_json_iter, "uint64", "", 0);
|
logger::log_value(*_json_iter, "uint64", "", 0);
|
||||||
_json_iter->ascend_to(depth()-1);
|
_json_iter->ascend_to(depth()-1);
|
||||||
return numberparsing::parse_unsigned(_json_iter->advance());
|
return numberparsing::parse_unsigned(_json_iter->advance());
|
||||||
}
|
}
|
||||||
simdjson_warn_unused simdjson_really_inline simdjson_result<int64_t> value_iterator::try_get_int64() noexcept {
|
simdjson_warn_unused simdjson_really_inline simdjson_result<int64_t> value_iterator::try_get_int64() noexcept {
|
||||||
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth > 1 );
|
assert_at_non_root_start();
|
||||||
|
|
||||||
logger::log_value(*_json_iter, "int64", "", 0);
|
logger::log_value(*_json_iter, "int64", "", 0);
|
||||||
int64_t result;
|
int64_t result;
|
||||||
|
@ -193,14 +197,14 @@ simdjson_warn_unused simdjson_really_inline simdjson_result<int64_t> value_itera
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
simdjson_warn_unused simdjson_really_inline simdjson_result<int64_t> value_iterator::require_int64() noexcept {
|
simdjson_warn_unused simdjson_really_inline simdjson_result<int64_t> value_iterator::require_int64() noexcept {
|
||||||
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth > 1 );
|
assert_at_non_root_start();
|
||||||
|
|
||||||
logger::log_value(*_json_iter, "int64", "", 0);
|
logger::log_value(*_json_iter, "int64", "", 0);
|
||||||
_json_iter->ascend_to(depth()-1);
|
_json_iter->ascend_to(depth()-1);
|
||||||
return numberparsing::parse_integer(_json_iter->advance());
|
return numberparsing::parse_integer(_json_iter->advance());
|
||||||
}
|
}
|
||||||
simdjson_warn_unused simdjson_really_inline simdjson_result<double> value_iterator::try_get_double() noexcept {
|
simdjson_warn_unused simdjson_really_inline simdjson_result<double> value_iterator::try_get_double() noexcept {
|
||||||
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth > 1 );
|
assert_at_non_root_start();
|
||||||
|
|
||||||
logger::log_value(*_json_iter, "double", "", 0);
|
logger::log_value(*_json_iter, "double", "", 0);
|
||||||
double result;
|
double result;
|
||||||
|
@ -210,7 +214,7 @@ simdjson_warn_unused simdjson_really_inline simdjson_result<double> value_iterat
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
simdjson_warn_unused simdjson_really_inline simdjson_result<double> value_iterator::require_double() noexcept {
|
simdjson_warn_unused simdjson_really_inline simdjson_result<double> value_iterator::require_double() noexcept {
|
||||||
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth > 1 );
|
assert_at_non_root_start();
|
||||||
|
|
||||||
logger::log_value(*_json_iter, "double", "", 0);
|
logger::log_value(*_json_iter, "double", "", 0);
|
||||||
_json_iter->ascend_to(depth()-1);
|
_json_iter->ascend_to(depth()-1);
|
||||||
|
@ -225,7 +229,7 @@ simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator
|
||||||
return simdjson_result<bool>(!not_true);
|
return simdjson_result<bool>(!not_true);
|
||||||
}
|
}
|
||||||
simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator::try_get_bool() noexcept {
|
simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator::try_get_bool() noexcept {
|
||||||
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth > 1 );
|
assert_at_non_root_start();
|
||||||
|
|
||||||
bool result;
|
bool result;
|
||||||
SIMDJSON_TRY( parse_bool(_json_iter->peek()).get(result) );
|
SIMDJSON_TRY( parse_bool(_json_iter->peek()).get(result) );
|
||||||
|
@ -234,7 +238,7 @@ simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator::require_bool() noexcept {
|
simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator::require_bool() noexcept {
|
||||||
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth > 1 );
|
assert_at_non_root_start();
|
||||||
|
|
||||||
_json_iter->ascend_to(depth()-1);
|
_json_iter->ascend_to(depth()-1);
|
||||||
return parse_bool(_json_iter->advance());
|
return parse_bool(_json_iter->advance());
|
||||||
|
@ -247,7 +251,7 @@ simdjson_really_inline bool value_iterator::is_null(const uint8_t *json) const n
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
simdjson_really_inline bool value_iterator::is_null() noexcept {
|
simdjson_really_inline bool value_iterator::is_null() noexcept {
|
||||||
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth > 1 );
|
assert_at_non_root_start();
|
||||||
|
|
||||||
if (is_null(_json_iter->peek())) {
|
if (is_null(_json_iter->peek())) {
|
||||||
_json_iter->advance();
|
_json_iter->advance();
|
||||||
|
@ -257,7 +261,7 @@ simdjson_really_inline bool value_iterator::is_null() noexcept {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
simdjson_really_inline bool value_iterator::require_null() noexcept {
|
simdjson_really_inline bool value_iterator::require_null() noexcept {
|
||||||
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth > 1 );
|
assert_at_non_root_start();
|
||||||
|
|
||||||
_json_iter->ascend_to(depth()-1);
|
_json_iter->ascend_to(depth()-1);
|
||||||
return is_null(_json_iter->advance());
|
return is_null(_json_iter->advance());
|
||||||
|
@ -266,8 +270,6 @@ simdjson_really_inline bool value_iterator::require_null() noexcept {
|
||||||
constexpr const uint32_t MAX_INT_LENGTH = 1024;
|
constexpr const uint32_t MAX_INT_LENGTH = 1024;
|
||||||
|
|
||||||
simdjson_warn_unused simdjson_really_inline simdjson_result<uint64_t> value_iterator::parse_root_uint64(const uint8_t *json, uint32_t max_len) const noexcept {
|
simdjson_warn_unused simdjson_really_inline simdjson_result<uint64_t> value_iterator::parse_root_uint64(const uint8_t *json, uint32_t max_len) const noexcept {
|
||||||
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth == 1 );
|
|
||||||
|
|
||||||
uint8_t tmpbuf[20+1]; // <20 digits> is the longest possible unsigned integer
|
uint8_t tmpbuf[20+1]; // <20 digits> is the longest possible unsigned integer
|
||||||
if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf)) { logger::log_error(*_json_iter, "Root number more than 20 characters"); return NUMBER_ERROR; }
|
if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf)) { logger::log_error(*_json_iter, "Root number more than 20 characters"); return NUMBER_ERROR; }
|
||||||
logger::log_value(*_json_iter, "uint64", "", 0);
|
logger::log_value(*_json_iter, "uint64", "", 0);
|
||||||
|
@ -276,7 +278,7 @@ simdjson_warn_unused simdjson_really_inline simdjson_result<uint64_t> value_iter
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
simdjson_warn_unused simdjson_really_inline simdjson_result<uint64_t> value_iterator::try_get_root_uint64() noexcept {
|
simdjson_warn_unused simdjson_really_inline simdjson_result<uint64_t> value_iterator::try_get_root_uint64() noexcept {
|
||||||
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth == 1 );
|
assert_at_root();
|
||||||
|
|
||||||
uint64_t result;
|
uint64_t result;
|
||||||
SIMDJSON_TRY( parse_root_uint64(_json_iter->peek(), _json_iter->peek_length()).get(result) );
|
SIMDJSON_TRY( parse_root_uint64(_json_iter->peek(), _json_iter->peek_length()).get(result) );
|
||||||
|
@ -284,14 +286,12 @@ simdjson_warn_unused simdjson_really_inline simdjson_result<uint64_t> value_iter
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
simdjson_warn_unused simdjson_really_inline simdjson_result<uint64_t> value_iterator::require_root_uint64() noexcept {
|
simdjson_warn_unused simdjson_really_inline simdjson_result<uint64_t> value_iterator::require_root_uint64() noexcept {
|
||||||
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth == 1 );
|
assert_at_root();
|
||||||
|
|
||||||
auto max_len = _json_iter->peek_length();
|
auto max_len = _json_iter->peek_length();
|
||||||
return parse_root_uint64(_json_iter->advance(), max_len);
|
return parse_root_uint64(_json_iter->advance(), max_len);
|
||||||
}
|
}
|
||||||
simdjson_warn_unused simdjson_really_inline simdjson_result<int64_t> value_iterator::parse_root_int64(const uint8_t *json, uint32_t max_len) const noexcept {
|
simdjson_warn_unused simdjson_really_inline simdjson_result<int64_t> value_iterator::parse_root_int64(const uint8_t *json, uint32_t max_len) const noexcept {
|
||||||
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth == 1 );
|
|
||||||
|
|
||||||
uint8_t tmpbuf[20+1]; // -<19 digits> is the longest possible integer
|
uint8_t tmpbuf[20+1]; // -<19 digits> is the longest possible integer
|
||||||
if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf)) { logger::log_error(*_json_iter, "Root number more than 20 characters"); return NUMBER_ERROR; }
|
if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf)) { logger::log_error(*_json_iter, "Root number more than 20 characters"); return NUMBER_ERROR; }
|
||||||
logger::log_value(*_json_iter, "int64", "", 0);
|
logger::log_value(*_json_iter, "int64", "", 0);
|
||||||
|
@ -300,7 +300,7 @@ simdjson_warn_unused simdjson_really_inline simdjson_result<int64_t> value_itera
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
simdjson_warn_unused simdjson_really_inline simdjson_result<int64_t> value_iterator::try_get_root_int64() noexcept {
|
simdjson_warn_unused simdjson_really_inline simdjson_result<int64_t> value_iterator::try_get_root_int64() noexcept {
|
||||||
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth == 1 );
|
assert_at_root();
|
||||||
|
|
||||||
int64_t result;
|
int64_t result;
|
||||||
SIMDJSON_TRY( parse_root_int64(_json_iter->peek(), _json_iter->peek_length()).get(result) );
|
SIMDJSON_TRY( parse_root_int64(_json_iter->peek(), _json_iter->peek_length()).get(result) );
|
||||||
|
@ -308,14 +308,12 @@ simdjson_warn_unused simdjson_really_inline simdjson_result<int64_t> value_itera
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
simdjson_warn_unused simdjson_really_inline simdjson_result<int64_t> value_iterator::require_root_int64() noexcept {
|
simdjson_warn_unused simdjson_really_inline simdjson_result<int64_t> value_iterator::require_root_int64() noexcept {
|
||||||
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth == 1 );
|
assert_at_root();
|
||||||
|
|
||||||
auto max_len = _json_iter->peek_length();
|
auto max_len = _json_iter->peek_length();
|
||||||
return parse_root_int64(_json_iter->advance(), max_len);
|
return parse_root_int64(_json_iter->advance(), max_len);
|
||||||
}
|
}
|
||||||
simdjson_warn_unused simdjson_really_inline simdjson_result<double> value_iterator::parse_root_double(const uint8_t *json, uint32_t max_len) const noexcept {
|
simdjson_warn_unused simdjson_really_inline simdjson_result<double> value_iterator::parse_root_double(const uint8_t *json, uint32_t max_len) const noexcept {
|
||||||
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth == 1 );
|
|
||||||
|
|
||||||
// Per https://www.exploringbinary.com/maximum-number-of-decimal-digits-in-binary-floating-point-numbers/, 1074 is the maximum number of significant fractional digits. Add 8 more digits for the biggest number: -0.<fraction>e-308.
|
// Per https://www.exploringbinary.com/maximum-number-of-decimal-digits-in-binary-floating-point-numbers/, 1074 is the maximum number of significant fractional digits. Add 8 more digits for the biggest number: -0.<fraction>e-308.
|
||||||
uint8_t tmpbuf[1074+8+1];
|
uint8_t tmpbuf[1074+8+1];
|
||||||
if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf)) { logger::log_error(*_json_iter, "Root number more than 1082 characters"); return NUMBER_ERROR; }
|
if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf)) { logger::log_error(*_json_iter, "Root number more than 1082 characters"); return NUMBER_ERROR; }
|
||||||
|
@ -325,7 +323,7 @@ simdjson_warn_unused simdjson_really_inline simdjson_result<double> value_iterat
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
simdjson_warn_unused simdjson_really_inline simdjson_result<double> value_iterator::try_get_root_double() noexcept {
|
simdjson_warn_unused simdjson_really_inline simdjson_result<double> value_iterator::try_get_root_double() noexcept {
|
||||||
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth == 1 );
|
assert_at_root();
|
||||||
|
|
||||||
double result;
|
double result;
|
||||||
SIMDJSON_TRY( parse_root_double(_json_iter->peek(), _json_iter->peek_length()).get(result) );
|
SIMDJSON_TRY( parse_root_double(_json_iter->peek(), _json_iter->peek_length()).get(result) );
|
||||||
|
@ -333,20 +331,18 @@ simdjson_warn_unused simdjson_really_inline simdjson_result<double> value_iterat
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
simdjson_warn_unused simdjson_really_inline simdjson_result<double> value_iterator::require_root_double() noexcept {
|
simdjson_warn_unused simdjson_really_inline simdjson_result<double> value_iterator::require_root_double() noexcept {
|
||||||
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth == 1 );
|
assert_at_root();
|
||||||
|
|
||||||
auto max_len = _json_iter->peek_length();
|
auto max_len = _json_iter->peek_length();
|
||||||
return parse_root_double(_json_iter->advance(), max_len);
|
return parse_root_double(_json_iter->advance(), max_len);
|
||||||
}
|
}
|
||||||
simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator::parse_root_bool(const uint8_t *json, uint32_t max_len) const noexcept {
|
simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator::parse_root_bool(const uint8_t *json, uint32_t max_len) const noexcept {
|
||||||
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth == 1 );
|
|
||||||
|
|
||||||
uint8_t tmpbuf[5+1];
|
uint8_t tmpbuf[5+1];
|
||||||
if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf)) { logger::log_error(*_json_iter, "Not a boolean"); return INCORRECT_TYPE; }
|
if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf)) { logger::log_error(*_json_iter, "Not a boolean"); return INCORRECT_TYPE; }
|
||||||
return parse_bool(tmpbuf);
|
return parse_bool(tmpbuf);
|
||||||
}
|
}
|
||||||
simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator::try_get_root_bool() noexcept {
|
simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator::try_get_root_bool() noexcept {
|
||||||
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth == 1 );
|
assert_at_root();
|
||||||
|
|
||||||
bool result;
|
bool result;
|
||||||
SIMDJSON_TRY( parse_root_bool(_json_iter->peek(), _json_iter->peek_length()).get(result) );
|
SIMDJSON_TRY( parse_root_bool(_json_iter->peek(), _json_iter->peek_length()).get(result) );
|
||||||
|
@ -354,44 +350,50 @@ simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator::require_root_bool() noexcept {
|
simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator::require_root_bool() noexcept {
|
||||||
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth == 1 );
|
assert_at_root();
|
||||||
|
|
||||||
auto max_len = _json_iter->peek_length();
|
auto max_len = _json_iter->peek_length();
|
||||||
return parse_root_bool(_json_iter->advance(), max_len);
|
return parse_root_bool(_json_iter->advance(), max_len);
|
||||||
}
|
}
|
||||||
simdjson_really_inline bool value_iterator::is_root_null(const uint8_t *json, uint32_t max_len) const noexcept {
|
simdjson_really_inline bool value_iterator::is_root_null(const uint8_t *json, uint32_t max_len) const noexcept {
|
||||||
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth == 1 );
|
|
||||||
|
|
||||||
uint8_t tmpbuf[4+1];
|
uint8_t tmpbuf[4+1];
|
||||||
if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf)) { return false; }
|
if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf)) { return false; }
|
||||||
return is_null(tmpbuf);
|
return is_null(tmpbuf);
|
||||||
}
|
}
|
||||||
simdjson_really_inline bool value_iterator::is_root_null() noexcept {
|
simdjson_really_inline bool value_iterator::is_root_null() noexcept {
|
||||||
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth == 1 );
|
assert_at_root();
|
||||||
|
|
||||||
if (!is_root_null(_json_iter->peek(), _json_iter->peek_length())) { return false; }
|
if (!is_root_null(_json_iter->peek(), _json_iter->peek_length())) { return false; }
|
||||||
_json_iter->advance();
|
_json_iter->advance();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
simdjson_really_inline bool value_iterator::require_root_null() noexcept {
|
simdjson_really_inline bool value_iterator::require_root_null() noexcept {
|
||||||
SIMDJSON_ASSUME( _json_iter->_depth == _depth && _depth == 1 );
|
assert_at_root();
|
||||||
|
|
||||||
auto max_len = _json_iter->peek_length();
|
auto max_len = _json_iter->peek_length();
|
||||||
return is_root_null(_json_iter->advance(), max_len);
|
return is_root_null(_json_iter->advance(), max_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
simdjson_warn_unused simdjson_really_inline error_code value_iterator::skip_child() noexcept {
|
simdjson_warn_unused simdjson_really_inline error_code value_iterator::skip_child() noexcept {
|
||||||
|
SIMDJSON_ASSUME( _json_iter->token.index > _start_index );
|
||||||
|
SIMDJSON_ASSUME( _json_iter->_depth >= _depth );
|
||||||
|
|
||||||
return _json_iter->skip_child(depth());
|
return _json_iter->skip_child(depth());
|
||||||
}
|
}
|
||||||
simdjson_really_inline value_iterator value_iterator::child() const noexcept {
|
simdjson_really_inline value_iterator value_iterator::child() const noexcept {
|
||||||
SIMDJSON_ASSUME( _json_iter->_depth == _depth+1 );
|
assert_at_child();
|
||||||
return { _json_iter, depth()+1 };
|
return { _json_iter, depth()+1, _json_iter->token.checkpoint() };
|
||||||
}
|
}
|
||||||
|
|
||||||
simdjson_really_inline bool value_iterator::is_open() const noexcept {
|
simdjson_really_inline bool value_iterator::is_open() const noexcept {
|
||||||
return _json_iter->depth() >= depth();
|
return _json_iter->depth() >= depth();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
simdjson_really_inline bool value_iterator::at_first_field() const noexcept {
|
||||||
|
SIMDJSON_ASSUME( _json_iter->token.index > _start_index );
|
||||||
|
return _json_iter->token.index == _start_index + 1;
|
||||||
|
}
|
||||||
|
|
||||||
simdjson_really_inline void value_iterator::abandon() noexcept {
|
simdjson_really_inline void value_iterator::abandon() noexcept {
|
||||||
_json_iter->abandon();
|
_json_iter->abandon();
|
||||||
}
|
}
|
||||||
|
@ -413,6 +415,35 @@ simdjson_warn_unused simdjson_really_inline json_iterator &value_iterator::json_
|
||||||
return *_json_iter;
|
return *_json_iter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
simdjson_really_inline void value_iterator::assert_at_start() const noexcept {
|
||||||
|
SIMDJSON_ASSUME( _json_iter->token.index == _start_index );
|
||||||
|
SIMDJSON_ASSUME( _json_iter->_depth == _depth );
|
||||||
|
SIMDJSON_ASSUME( _depth > 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
simdjson_really_inline void value_iterator::assert_at_next() const noexcept {
|
||||||
|
SIMDJSON_ASSUME( _json_iter->token.index > _start_index );
|
||||||
|
SIMDJSON_ASSUME( _json_iter->_depth == _depth );
|
||||||
|
SIMDJSON_ASSUME( _depth > 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
simdjson_really_inline void value_iterator::assert_at_child() const noexcept {
|
||||||
|
SIMDJSON_ASSUME( _json_iter->token.index > _start_index );
|
||||||
|
SIMDJSON_ASSUME( _json_iter->_depth == _depth + 1 );
|
||||||
|
SIMDJSON_ASSUME( _depth > 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
simdjson_really_inline void value_iterator::assert_at_root() const noexcept {
|
||||||
|
assert_at_start();
|
||||||
|
SIMDJSON_ASSUME( _depth == 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
simdjson_really_inline void value_iterator::assert_at_non_root_start() const noexcept {
|
||||||
|
assert_at_start();
|
||||||
|
SIMDJSON_ASSUME( _depth > 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} // namespace ondemand
|
} // namespace ondemand
|
||||||
} // namespace SIMDJSON_IMPLEMENTATION
|
} // namespace SIMDJSON_IMPLEMENTATION
|
||||||
} // namespace simdjson
|
} // namespace simdjson
|
||||||
|
|
|
@ -23,6 +23,12 @@ protected:
|
||||||
json_iterator *_json_iter{};
|
json_iterator *_json_iter{};
|
||||||
/** The depth of this value */
|
/** The depth of this value */
|
||||||
depth_t _depth{};
|
depth_t _depth{};
|
||||||
|
/**
|
||||||
|
* The starting token index for this value
|
||||||
|
*
|
||||||
|
* PERF NOTE: this is a safety check; we expect this to be elided in release builds.
|
||||||
|
*/
|
||||||
|
const uint32_t *_start_index{};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
simdjson_really_inline value_iterator() noexcept = default;
|
simdjson_really_inline value_iterator() noexcept = default;
|
||||||
|
@ -49,6 +55,11 @@ public:
|
||||||
*/
|
*/
|
||||||
simdjson_really_inline bool is_open() const noexcept;
|
simdjson_really_inline bool is_open() const noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tell whether the value is at an object's first field (just after the {).
|
||||||
|
*/
|
||||||
|
simdjson_really_inline bool at_first_field() const noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abandon all iteration.
|
* Abandon all iteration.
|
||||||
*/
|
*/
|
||||||
|
@ -152,7 +163,7 @@ public:
|
||||||
* unescape it. This works well for typical ASCII and UTF-8 keys (almost all of them), but may
|
* unescape it. This works well for typical ASCII and UTF-8 keys (almost all of them), but may
|
||||||
* fail to match some keys with escapes (\u, \n, etc.).
|
* fail to match some keys with escapes (\u, \n, etc.).
|
||||||
*/
|
*/
|
||||||
simdjson_warn_unused simdjson_really_inline simdjson_result<bool> find_field_raw(const char *key) noexcept;
|
simdjson_warn_unused simdjson_really_inline simdjson_result<bool> find_field_raw(const std::string_view key) noexcept;
|
||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
|
@ -246,7 +257,7 @@ public:
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
simdjson_really_inline value_iterator(json_iterator *json_iter, depth_t depth) noexcept;
|
simdjson_really_inline value_iterator(json_iterator *json_iter, depth_t depth, const uint32_t *start_index) noexcept;
|
||||||
simdjson_really_inline bool is_null(const uint8_t *json) const noexcept;
|
simdjson_really_inline bool is_null(const uint8_t *json) const noexcept;
|
||||||
simdjson_really_inline simdjson_result<bool> parse_bool(const uint8_t *json) const noexcept;
|
simdjson_really_inline simdjson_result<bool> parse_bool(const uint8_t *json) const noexcept;
|
||||||
simdjson_really_inline bool is_root_null(const uint8_t *json, uint32_t max_len) const noexcept;
|
simdjson_really_inline bool is_root_null(const uint8_t *json, uint32_t max_len) const noexcept;
|
||||||
|
@ -255,6 +266,12 @@ protected:
|
||||||
simdjson_really_inline simdjson_result<int64_t> parse_root_int64(const uint8_t *json, uint32_t max_len) const noexcept;
|
simdjson_really_inline simdjson_result<int64_t> parse_root_int64(const uint8_t *json, uint32_t max_len) const noexcept;
|
||||||
simdjson_really_inline simdjson_result<double> parse_root_double(const uint8_t *json, uint32_t max_len) const noexcept;
|
simdjson_really_inline simdjson_result<double> parse_root_double(const uint8_t *json, uint32_t max_len) const noexcept;
|
||||||
|
|
||||||
|
simdjson_really_inline void assert_at_start() const noexcept;
|
||||||
|
simdjson_really_inline void assert_at_root() const noexcept;
|
||||||
|
simdjson_really_inline void assert_at_child() const noexcept;
|
||||||
|
simdjson_really_inline void assert_at_next() const noexcept;
|
||||||
|
simdjson_really_inline void assert_at_non_root_start() const noexcept;
|
||||||
|
|
||||||
friend class document;
|
friend class document;
|
||||||
friend class object;
|
friend class object;
|
||||||
friend class array;
|
friend class array;
|
||||||
|
|
|
@ -2,4 +2,6 @@
|
||||||
link_libraries(simdjson)
|
link_libraries(simdjson)
|
||||||
include_directories(..)
|
include_directories(..)
|
||||||
add_cpp_test(ondemand_basictests LABELS acceptance per_implementation)
|
add_cpp_test(ondemand_basictests LABELS acceptance per_implementation)
|
||||||
|
if(HAVE_POSIX_FORK AND HAVE_POSIX_WAIT) # assert tests use fork and wait, which aren't on MSVC
|
||||||
|
add_cpp_test(ondemand_assert_out_of_order_values LABELS per_implementation explicitonly assert)
|
||||||
|
endif()
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include "simdjson.h"
|
||||||
|
|
||||||
|
using namespace simdjson;
|
||||||
|
using namespace simdjson::builtin;
|
||||||
|
|
||||||
|
// This ensures the compiler can't rearrange them into the proper order (which causes it to work!)
|
||||||
|
simdjson_never_inline int check_point(simdjson_result<ondemand::value> xval, simdjson_result<ondemand::value> yval) {
|
||||||
|
// Verify the expected release behavior
|
||||||
|
error_code error;
|
||||||
|
uint64_t x = 0;
|
||||||
|
if ((error = xval.get(x))) { std::cerr << "error getting x: " << error << std::endl; }
|
||||||
|
else if (x != 2) { std::cerr << "expected x to (wrongly) be 2, was " << x << std::endl; }
|
||||||
|
uint64_t y = 0;
|
||||||
|
if ((error = yval.get(y))) { std::cerr << "error getting y: " << error << std::endl; }
|
||||||
|
else if (y != 3) { std::cerr << "expected y to (wrongly) be 3, was " << y << std::endl; }
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int test_check_point() {
|
||||||
|
auto json = R"(
|
||||||
|
{
|
||||||
|
"x": 1,
|
||||||
|
"y": 2 3
|
||||||
|
)"_padded;
|
||||||
|
ondemand::parser parser;
|
||||||
|
auto doc = parser.iterate(json);
|
||||||
|
return check_point(doc["x"], doc["y"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fork_failed_with_assert() {
|
||||||
|
int status = 0;
|
||||||
|
wait(&status);
|
||||||
|
return WIFSIGNALED(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
|
||||||
|
// To verify that the program asserts (which sends a signal), we fork a new process and use wait()
|
||||||
|
// to check the resulting error code. If it's a signal error code, we consider the
|
||||||
|
// test to have passed.
|
||||||
|
// From https://stackoverflow.com/a/33694733
|
||||||
|
|
||||||
|
pid_t pid = fork();
|
||||||
|
if (pid == -1) { std::cerr << "fork failed" << std::endl; return 1; }
|
||||||
|
if (pid) {
|
||||||
|
// Parent - wait child and interpret its result
|
||||||
|
return fork_failed_with_assert() ? 0 : 1;
|
||||||
|
} else {
|
||||||
|
test_check_point();
|
||||||
|
}
|
||||||
|
}
|
|
@ -887,6 +887,116 @@ namespace dom_api_tests {
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
SUBTEST("simdjson_result<ondemand::document>", test_ondemand_doc(json, [&](auto doc_result) {
|
||||||
|
ASSERT_SUCCESS( doc_result["scalar_ignore"] );
|
||||||
|
std::cout << " - After ignoring empty scalar ..." << std::endl;
|
||||||
|
|
||||||
|
ASSERT_SUCCESS( doc_result["empty_array_ignore"] );
|
||||||
|
std::cout << " - After ignoring empty array ..." << std::endl;
|
||||||
|
|
||||||
|
ASSERT_SUCCESS( doc_result["empty_object_ignore"] );
|
||||||
|
std::cout << " - After ignoring empty doc_result ..." << std::endl;
|
||||||
|
|
||||||
|
// Break after using first value in child object
|
||||||
|
{
|
||||||
|
auto value = doc_result["object_break"];
|
||||||
|
for (auto [ child_field, error ] : value.get_object()) {
|
||||||
|
ASSERT_SUCCESS(error);
|
||||||
|
ASSERT_EQUAL(child_field.key(), "x");
|
||||||
|
uint64_t x;
|
||||||
|
ASSERT_SUCCESS( child_field.value().get(x) );
|
||||||
|
ASSERT_EQUAL(x, 3);
|
||||||
|
break; // Break after the first value
|
||||||
|
}
|
||||||
|
std::cout << " - After using first value in child object ..." << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Break without using first value in child object
|
||||||
|
{
|
||||||
|
auto value = doc_result["object_break_unused"];
|
||||||
|
for (auto [ child_field, error ] : value.get_object()) {
|
||||||
|
ASSERT_SUCCESS(error);
|
||||||
|
ASSERT_EQUAL(child_field.key(), "x");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
std::cout << " - After reaching (but not using) first value in child object ..." << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only look up one field in child object
|
||||||
|
{
|
||||||
|
auto value = doc_result["object_index"];
|
||||||
|
|
||||||
|
uint64_t x;
|
||||||
|
ASSERT_SUCCESS( value["x"].get(x) );
|
||||||
|
ASSERT_EQUAL( x, 5 );
|
||||||
|
std::cout << " - After looking up one field in child object ..." << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only look up one field in child object, but don't use it
|
||||||
|
{
|
||||||
|
auto value = doc_result["object_index_unused"];
|
||||||
|
|
||||||
|
ASSERT_SUCCESS( value["x"] );
|
||||||
|
std::cout << " - After looking up (but not using) one field in child object ..." << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Break after first value in child array
|
||||||
|
{
|
||||||
|
auto value = doc_result["array_break"];
|
||||||
|
|
||||||
|
for (auto child_value : value) {
|
||||||
|
uint64_t x;
|
||||||
|
ASSERT_SUCCESS( child_value.get(x) );
|
||||||
|
ASSERT_EQUAL( x, 7 );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
std::cout << " - After using first value in child array ..." << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Break without using first value in child array
|
||||||
|
{
|
||||||
|
auto value = doc_result["array_break_unused"];
|
||||||
|
|
||||||
|
for (auto child_value : value) {
|
||||||
|
ASSERT_SUCCESS(child_value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
std::cout << " - After reaching (but not using) first value in child array ..." << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Break out of multiple child loops
|
||||||
|
{
|
||||||
|
auto value = doc_result["quadruple_nested_break"];
|
||||||
|
for (auto child1 : value.get_object()) {
|
||||||
|
for (auto child2 : child1.value().get_array()) {
|
||||||
|
for (auto child3 : child2.get_object()) {
|
||||||
|
for (auto child4 : child3.value().get_array()) {
|
||||||
|
uint64_t x;
|
||||||
|
ASSERT_SUCCESS( child4.get(x) );
|
||||||
|
ASSERT_EQUAL( x, 9 );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
std::cout << " - After breaking out of quadruply-nested arrays and objects ..." << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test the actual value
|
||||||
|
{
|
||||||
|
auto value = doc_result["actual_value"];
|
||||||
|
uint64_t actual_value;
|
||||||
|
ASSERT_SUCCESS( value.get(actual_value) );
|
||||||
|
ASSERT_EQUAL( actual_value, 10 );
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1061,17 +1171,35 @@ namespace dom_api_tests {
|
||||||
return true;
|
return true;
|
||||||
}));
|
}));
|
||||||
SUBTEST("simdjson_result<ondemand::object>", test_ondemand_doc(json, [&](auto doc_result) {
|
SUBTEST("simdjson_result<ondemand::object>", test_ondemand_doc(json, [&](auto doc_result) {
|
||||||
ASSERT_EQUAL( doc_result.get_object()["a"].get_uint64().first, 1 );
|
simdjson_result<ondemand::object> object;
|
||||||
|
object = doc_result.get_object();
|
||||||
|
|
||||||
|
ASSERT_EQUAL( object["a"].get_uint64().first, 1 );
|
||||||
|
ASSERT_EQUAL( object["b"].get_uint64().first, 2 );
|
||||||
|
ASSERT_EQUAL( object["c/d"].get_uint64().first, 3 );
|
||||||
|
|
||||||
|
ASSERT_ERROR( object["a"], NO_SUCH_FIELD );
|
||||||
|
ASSERT_ERROR( object["d"], NO_SUCH_FIELD );
|
||||||
return true;
|
return true;
|
||||||
}));
|
}));
|
||||||
SUBTEST("ondemand::document", test_ondemand_doc(json, [&](auto doc_result) {
|
SUBTEST("ondemand::document", test_ondemand_doc(json, [&](auto doc_result) {
|
||||||
ondemand::document doc;
|
ondemand::document doc;
|
||||||
ASSERT_SUCCESS( std::move(doc_result).get(doc) );
|
ASSERT_SUCCESS( std::move(doc_result).get(doc) );
|
||||||
ASSERT_EQUAL( doc["a"].get_uint64().first, 1 );
|
ASSERT_EQUAL( doc["a"].get_uint64().first, 1 );
|
||||||
|
ASSERT_EQUAL( doc["b"].get_uint64().first, 2 );
|
||||||
|
ASSERT_EQUAL( doc["c/d"].get_uint64().first, 3 );
|
||||||
|
|
||||||
|
ASSERT_ERROR( doc["a"], NO_SUCH_FIELD );
|
||||||
|
ASSERT_ERROR( doc["d"], NO_SUCH_FIELD );
|
||||||
return true;
|
return true;
|
||||||
}));
|
}));
|
||||||
SUBTEST("simdjson_result<ondemand::document>", test_ondemand_doc(json, [&](auto doc_result) {
|
SUBTEST("simdjson_result<ondemand::document>", test_ondemand_doc(json, [&](auto doc_result) {
|
||||||
ASSERT_EQUAL( doc_result["a"].get_uint64().first, 1 );
|
ASSERT_EQUAL( doc_result["a"].get_uint64().first, 1 );
|
||||||
|
ASSERT_EQUAL( doc_result["b"].get_uint64().first, 2 );
|
||||||
|
ASSERT_EQUAL( doc_result["c/d"].get_uint64().first, 3 );
|
||||||
|
|
||||||
|
ASSERT_ERROR( doc_result["a"], NO_SUCH_FIELD );
|
||||||
|
ASSERT_ERROR( doc_result["d"], NO_SUCH_FIELD );
|
||||||
return true;
|
return true;
|
||||||
}));
|
}));
|
||||||
TEST_SUCCEED();
|
TEST_SUCCEED();
|
||||||
|
|
Loading…
Reference in New Issue