Compare commits

..

79 Commits

Author SHA1 Message Date
Daniel Lemire 5541e78402 version bump 2023-12-01 13:56:12 -05:00
Daniel Lemire 9a9ed0e2da Fix Visual Studio 64-bit ARM regression (#2091)
* fix for ARM64 kernel under Visual Studio (bug introduced in release 3.6.1)

* revert comment

* updating amal.
2023-12-01 13:55:28 -05:00
Daniel Lemire bca8d3e277 version bump. 2023-11-30 18:13:02 -05:00
Daniel Lemire 97196fa969 Fixing warnings issued by clang (Node issue 50930) (#2090)
* Fixing warnings issued by clang (Node issue 50930)

* removing space

---------

Co-authored-by: Daniel Lemire <dlemire@lemire.me>
2023-11-30 18:06:50 -05:00
John Keiser 23fab307ca Merge pull request #2088 from luhenry/upstream-riscv64
Make simdjson riscv64 aware
2023-11-30 11:06:43 -08:00
Daniel Lemire 0a14e05ec7 Update README.md 2023-11-30 13:42:00 -05:00
Daniel Lemire b88f831dbd Update basics.md 2023-11-30 11:52:24 -05:00
Daniel Lemire 71a73c2c47 Update basics.md 2023-11-30 11:51:35 -05:00
Daniel Lemire 07603aa7f7 fix space 2023-11-29 18:57:37 -05:00
Ludovic Henry b8a6b889c7 review: Revert changes in include/simdjson/implementation_detection.h 2023-11-29 22:09:25 +00:00
Ludovic Henry 7898234bb3 Make simdjson riscv64 aware 2023-11-29 19:28:14 +00:00
Daniel Lemire f52533538a Update basics.md 2023-11-28 23:49:40 -05:00
Daniel Lemire 3bb2f0a186 Return a better error when a user tries to cast a document that has already been accessed to a value (#2085)
* Fix.

* adding a test, cleaning some comments, adding documentation

* Correcting the JSON input.

* adding another test
2023-11-26 14:13:05 -05:00
Daniel Lemire d6551bf278 Update README.md 2023-11-22 11:36:33 -05:00
Daniel Lemire 0173eaaad7 Macro-based workaround for Visual Studio ARM (#2082) 2023-11-20 09:58:50 -05:00
Daniel Lemire 5459dbd6c6 typos. 2023-11-13 21:48:21 -05:00
Saint 9c45f1f292 Added link to Nim bindings (#2081) 2023-11-11 04:06:32 -05:00
int mian 665cbba159 fix typo (#2080) 2023-11-06 07:34:12 -05:00
Daniel Lemire a26f664907 removing space 2023-10-30 12:56:26 -04:00
Daniel Lemire 17cb457ffd version bump 2023-10-30 12:52:49 -04:00
Daniel Lemire 8b2af0473a skip UTF-8 BOM if present. (#2079) 2023-10-30 12:51:02 -04:00
Daniel Lemire f1bfa43385 Update ubuntu20-sani.yml 2023-10-27 20:58:54 -04:00
Daniel Lemire 29fbbee852 version bump 2023-10-27 20:57:30 -04:00
Daniel Lemire baa7d961ce Allowing users to write directly to std::optional<std::string> (#2078)
* Allowing users to write directly to std::optional<std::string>

* better fallback

* do not force the cast to std::string

* missing header

* removing abort
2023-10-27 20:56:12 -04:00
Yagiz Nizipli 6412b27c7e Merge pull request #2077 from simdjson/raw_json_on_values 2023-10-27 19:11:01 -04:00
Daniel Lemire 503da5ec83 raw_json() on values 2023-10-27 16:22:22 -04:00
Daniel Lemire 9dd6e9c959 version bump 2023-10-25 19:35:51 -04:00
Daniel Lemire 6db330c1a2 Automating string reallocation when it is possible (#2076)
* Automating string reallocation

* Typo
2023-10-25 19:34:52 -04:00
Daniel Lemire 993ac4b87c Adding the ability to write directly to an std::string. It is mostly syntaxic sugar (#2075) 2023-10-25 19:32:12 -04:00
Daniel Lemire 35e87896f0 minor tweak 2023-10-25 10:50:27 -04:00
Daniel Lemire f7e281cadc removing noisy warning 2023-10-20 15:45:40 -04:00
Daniel Lemire 13405afd4b This provides verbose static_assert messages (#2074)
* This provides verbose static_assert messages

* minor fix
2023-10-20 15:42:18 -04:00
Daniel Lemire 24b44309fb Removing commented code 2023-10-15 14:56:32 -04:00
Momtchil Momtchev e11ad58aad add a total order for elements (#2072) 2023-10-09 15:41:57 -04:00
Daniel Lemire 1875ed6550 Version bump. 2023-09-20 10:13:47 -04:00
Daniel Lemire 80d26298a0 Redesigning visit_primitive so that it is optimized for strings and (#2060)
numbers.

Co-authored-by: Daniel Lemire <dlemire@lemire.me>
2023-09-20 10:09:56 -04:00
Antoine Prouvost 25b5015c09 Add simdjson_static lib (#2068)
* Add simdjson_static lib

* Make simdjson_static a separate optional export file
2023-09-20 10:09:27 -04:00
Antoine Prouvost 26f8c566c7 Fix issue template bold text (#2067) 2023-09-19 11:15:54 -04:00
Daniel Lemire ff77ac801e Additional documentation based on issue 2063 (#2065)
* Additional documentation based on issue 2063

* Update basics.md
2023-09-11 10:01:35 -04:00
Daniel Lemire e0699994ef Testing macOS shared library support (#2062) 2023-09-09 12:48:42 -04:00
Daniel Lemire 68ba9a1b2a Adding a few spaces (minor formatting) (#2059) 2023-08-30 20:23:58 -04:00
Daniel Lemire 6fed6bd29b Update README.md 2023-08-30 19:26:34 -04:00
Piotr Rżysko cc24bb4114 Removed number parsing fallback (#2056) 2023-08-29 18:28:21 -04:00
John Keiser 14ec0ca8f4 Merge pull request #2052 from simdjson/jkeiser/structural_indexer_step
Write out 4 structural indexes at a time instead of 8
2023-08-29 15:24:54 -07:00
John Keiser 8dabd02c3a Default to step = 4 2023-08-29 15:48:52 -04:00
Daniel Lemire c9692005fd This allows us to pass SIMDJSON_STRUCTURAL_INDEXER_STEP as a command-line option. (#2055) 2023-08-25 13:47:20 -04:00
Daniel Lemire 2e0a9397c9 Merge branch 'master' into jkeiser/structural_indexer_step 2023-08-25 11:34:13 -04:00
Daniel Lemire f7922075c3 Adding support for Apple event counters (#2054) 2023-08-25 11:33:24 -04:00
Daniel Lemire b2e20e04c9 Standard compatibility fixes (#2053)
* Standard compatibility fixes

* missing commit

* Should work.

* Fix.

* Fix.

* Should work now.

---------

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

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

* Fixed typo

* Simplifying.
2023-07-20 14:11:33 -04:00
John Keiser 4f4e81668e Change all include paths to <> instead of "" to avoid relative path includes 2023-07-20 10:48:25 -07:00
John Keiser bb54946b78 Disallow including headers from implementation files 2023-07-20 10:01:22 -07:00
John Keiser 4dec6ed5a7 Merge pull request #2036 from simdjson/jkeiser/more-header-fixes
A few more header fixes
2023-07-18 10:26:40 -07:00
John Keiser 1dfd48195d Merge pull request #2035 from simdjson/jkeiser/sanitizer-ci
Run sanitizers in parallel
2023-07-17 23:37:34 -07:00
John Keiser 23afc6b695 Merge branch 'master' into jkeiser/sanitizer-ci 2023-07-17 16:09:20 -07:00
John Keiser 80bc9e5051 Run sanitizers in parallel 2023-07-17 12:57:50 -07:00
309 changed files with 13728 additions and 53863 deletions
+22 -1
View File
@@ -1,5 +1,8 @@
CompileFlags:
CompilationDatabase: build
Add:
- -Werror -Wall -Wextra -Weffc++ -Wsign-compare -Wshadow -Wwrite-strings -Wpointer-arith -Winit-self -Wconversion -Wno-sign-conversion
- -Wundefined-inline
Diagnostics:
Suppress:
- misc-unused-alias-decls
@@ -16,10 +19,28 @@ If:
CompileFlags:
Add:
- -Wno-unneeded-internal-declaration
- -Wno-undefined-inline # TODO fix and remove these violations
- -Wno-undefined-internal # TODO fix and remove these violations
- -Wno-unused-function
- -Wno-unused-const-variable
Diagnostics:
Suppress:
- pp_including_mainfile_in_preamble
---
# Amalgamated files that require or partly define an implementation
If:
PathMatch:
- .*/(arm64|fallback|haswell|icelake|ppc64|westmere)/begin.h
- .*/generic/.*
Diagnostics:
Suppress:
- pragma_attribute_no_pop_eof
---
# clang has a bad time detecting the push/pop together in src/ for some reason
If:
PathMatch:
- include/simdjson/.*/end.h
- src/(arm64|fallback|haswell|icelake|ppc64|westmere).cpp
Diagnostics:
Suppress:
- pragma_attribute_no_pop_eof
- pragma_attribute_stack_mismatch
+1 -1
View File
@@ -49,7 +49,7 @@ It is fine to report bugs against our main branch, but if that is what you are d
- Version [e.g. 22]
- Optimization setting (e.g., -O3)
We support up-to-date 64-bit ARM and x64 FreeBSD, macOS, Windows and Linux systems. Please ensure that your configuration is supported before labelling the issue as a bug. In particular, we do not support legacy 32-bit systems.
We support up-to-date 64-bit ARM and x64 FreeBSD, macOS, Windows and Linux systems. Please ensure that your configuration is supported before labelling the issue as a bug.
**Indicate whether you are willing or able to provide a bug fix as a pull request**
+1 -1
View File
@@ -31,7 +31,7 @@ A clear and concise description of any alternative solutions or features you've
**Additional context**
Add any other context or screenshots about the feature request here.
** Are you willing to contribute code or documentation toward this new feature? **
**Are you willing to contribute code or documentation toward this new feature?**
If you plan to contribute to simdjson, please read our
* CONTRIBUTING guide: https://github.com/simdjson/simdjson/blob/master/CONTRIBUTING.md and our
* HACKING guide: https://github.com/simdjson/simdjson/blob/master/HACKING.md
+2 -1
View File
@@ -20,7 +20,7 @@ jobs:
# fuzzers that change behaviour with SIMDJSON_FORCE_IMPLEMENTATION
defaultimplfuzzers: atpointer dump dump_raw_tape element minify parser print_json
# fuzzers that loop over the implementations themselves, or don't need to switch.
implfuzzers: implementations minifyimpl ndjson ondemand padded utf8 # TODO add singlestage
implfuzzers: implementations minifyimpl ndjson ondemand padded utf8
implementations: haswell westmere fallback
UBSAN_OPTIONS: halt_on_error=1
MAXLEN: -max_len=4000
@@ -34,6 +34,7 @@ jobs:
sudo apt update
sudo apt-get install --quiet ninja-build valgrind zip unzip lsb-release wget software-properties-common gnupg
wget https://apt.llvm.org/llvm.sh
sudo apt-get purge --auto-remove llvm python3-lldb-14 llvm-14
chmod +x llvm.sh
sudo ./llvm.sh $CLANGVERSION
+11
View File
@@ -31,3 +31,14 @@ jobs:
echo -e '#include <simdjson.h>\nint main(int argc,char**argv) {simdjson::dom::parser parser;simdjson::dom::element tweets = parser.load(argv[1]); }' > tmp.cpp && c++ -Idestination/include -Ldestination/lib -std=c++17 -Wl,-rpath,destination/lib -o linkandrun tmp.cpp -lsimdjson && ./linkandrun jsonexamples/twitter.json &&
cd ../tests/installation_tests/find &&
mkdir build && cd build && cmake -DCMAKE_INSTALL_PREFIX:PATH=../../../build/destination .. && cmake --build .
- name: Use cmake (shared)
run: |
mkdir buildshared &&
cd buildshared &&
cmake -DSIMDJSON_GOOGLE_BENCHMARKS=ON -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=ON -DCMAKE_INSTALL_PREFIX:PATH=destination .. &&
cmake --build . &&
ctest --output-on-failure -LE explicitonly -j &&
cmake --install . &&
echo -e '#include <simdjson.h>\nint main(int argc,char**argv) {simdjson::dom::parser parser;simdjson::dom::element tweets = parser.load(argv[1]); }' > tmp.cpp && c++ -Idestination/include -Ldestination/lib -std=c++17 -Wl,-rpath,destination/lib -o linkandrun tmp.cpp -lsimdjson && ./linkandrun jsonexamples/twitter.json &&
cd ../tests/installation_tests/find &&
mkdir buildshared && cd buildshared && cmake -DCMAKE_INSTALL_PREFIX:PATH=../../../buildshared/destination .. && cmake --build .
+29
View File
@@ -0,0 +1,29 @@
name: Ubuntu riscv64 (GCC 11)
on:
push:
branches:
- master
pull_request:
branches:
- master
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: uraimo/run-on-arch-action@v2
name: Test
id: runcmd
with:
arch: riscv64
distro: ubuntu_latest
githubToken: ${{ github.token }}
install: |
apt-get update -q -y
apt-get install -y cmake make g++
run: |
cmake -DCMAKE_BUILD_TYPE=Release -B build
cmake --build build -j=2
ctest --output-on-failure --test-dir build
+12 -1
View File
@@ -3,7 +3,7 @@ name: Ubuntu 20.04 CI (GCC 9) With Memory Sanitizer
on: [push, pull_request]
jobs:
ubuntu-build:
ubuntu-build-address-sanitizier:
if: >-
! contains(toJSON(github.event.commits.*.message), '[skip ci]') &&
! contains(toJSON(github.event.commits.*.message), '[skip github]')
@@ -21,6 +21,17 @@ jobs:
cmake -DSIMDJSON_SANITIZE=ON -DCMAKE_BUILD_TYPE=Debug -DSIMDJSON_GOOGLE_BENCHMARKS=OFF -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=OFF .. &&
cmake --build . &&
ctest --output-on-failure -LE explicitonly -j
ubuntu-build-undefined-sanitizer:
if: >-
! contains(toJSON(github.event.commits.*.message), '[skip ci]') &&
! contains(toJSON(github.event.commits.*.message), '[skip github]')
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v3
- uses: actions/cache@v3
with:
path: dependencies/.cache
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
- name: Use cmake with undefined sanitizer
run: |
mkdir builddebugundefsani &&
+14
View File
@@ -14,6 +14,20 @@ jobs:
with:
path: dependencies/.cache
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
- name: Use cmake to build just the library
run: |
mkdir buildjustlib &&
cd buildjustlib &&
cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DSIMDJSON_DEVELOPER_MODE=OFF -DCMAKE_INSTALL_PREFIX:PATH=destination .. &&
cmake --build . &&
cmake --install . &&
echo -e '#include <simdjson.h>\nint main(int argc,char**argv) {simdjson::dom::parser parser;simdjson::dom::element tweets = parser.load(argv[1]); }' > tmp.cpp &&
c++ -Idestination/include -Ldestination/lib -std=c++17 -Wl,-rpath,destination/lib -o linkandrun tmp.cpp -lsimdjson &&
cd ../tests/installation_tests/find &&
mkdir buildjustlib &&
cd buildjustlib &&
cmake -DCMAKE_INSTALL_PREFIX:PATH=../../../buildjustlib/destination .. &&
cmake --build .
- name: Use cmake
run: |
mkdir builddebug &&
-2
View File
@@ -14,8 +14,6 @@ jobs:
with:
path: dependencies/.cache
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
- name: Install clang++-13
run: sudo apt-get install -y clang++-13
- name: Use cmake
run: |
mkdir build &&
-2
View File
@@ -14,8 +14,6 @@ jobs:
with:
path: dependencies/.cache
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
- name: Install clang++-14
run: sudo apt-get install -y clang++-14
- name: Use cmake
run: |
mkdir build &&
@@ -1,4 +1,4 @@
name: Ubuntu 20.04 CI (GCC 9) with Thread Sanitizer
name: Ubuntu 22.04 CI (GCC 11) with Thread Sanitizer
on: [push, pull_request]
@@ -7,7 +7,7 @@ jobs:
if: >-
! contains(toJSON(github.event.commits.*.message), '[skip ci]') &&
! contains(toJSON(github.event.commits.*.message), '[skip github]')
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- uses: actions/cache@v3
+14
View File
@@ -14,6 +14,20 @@ jobs:
with:
path: dependencies/.cache
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
- name: Use cmake to build just the library
run: |
mkdir buildjustlib &&
cd buildjustlib &&
cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DSIMDJSON_DEVELOPER_MODE=OFF -DCMAKE_INSTALL_PREFIX:PATH=destination .. &&
cmake --build . &&
cmake --install . &&
echo -e '#include <simdjson.h>\nint main(int argc,char**argv) {simdjson::dom::parser parser;simdjson::dom::element tweets = parser.load(argv[1]); }' > tmp.cpp &&
c++ -Idestination/include -Ldestination/lib -std=c++17 -Wl,-rpath,destination/lib -o linkandrun tmp.cpp -lsimdjson &&
cd ../tests/installation_tests/find &&
mkdir buildjustlib &&
cd buildjustlib &&
cmake -DCMAKE_INSTALL_PREFIX:PATH=../../../buildjustlib/destination .. &&
cmake --build .
- name: Use cmake
run: |
mkdir builddebug &&
+32 -5
View File
@@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.14)
project(
simdjson
# The version number is modified by tools/release.py
VERSION 3.2.1
VERSION 3.6.2
DESCRIPTION "Parsing gigabytes of JSON per second"
HOMEPAGE_URL "https://simdjson.org/"
LANGUAGES CXX C
@@ -20,8 +20,10 @@ string(
# ---- Options, variables ----
# These version numbers are modified by tools/release.py
set(SIMDJSON_LIB_VERSION "16.0.0" CACHE STRING "simdjson library version")
set(SIMDJSON_LIB_SOVERSION "16" CACHE STRING "simdjson library soversion")
set(SIMDJSON_LIB_VERSION "19.0.0" CACHE STRING "simdjson library version")
set(SIMDJSON_LIB_SOVERSION "19" CACHE STRING "simdjson library soversion")
option(SIMDJSON_BUILD_STATIC_LIB "Build simdjson_static library along with simdjson" OFF)
option(SIMDJSON_ENABLE_THREADS "Link with thread support" ON)
@@ -56,8 +58,17 @@ include(cmake/developer-options.cmake)
# ---- simdjson library ----
add_library(simdjson src/simdjson.cpp)
set(SIMDJSON_SOURCES src/simdjson.cpp)
add_library(simdjson ${SIMDJSON_SOURCES})
add_library(simdjson::simdjson ALIAS simdjson)
set(SIMDJSON_LIBRARIES simdjson)
if(SIMDJSON_BUILD_STATIC_LIB)
add_library(simdjson_static STATIC ${SIMDJSON_SOURCES})
add_library(simdjson::simdjson_static ALIAS simdjson_static)
list(APPEND SIMDJSON_LIBRARIES simdjson_static)
endif()
set_target_properties(
simdjson PROPERTIES
@@ -117,6 +128,9 @@ if(SIMDJSON_ENABLE_THREADS)
endif()
simdjson_apply_props(simdjson)
if(SIMDJSON_BUILD_STATIC_LIB)
simdjson_apply_props(simdjson_static)
endif()
# ---- Install rules ----
@@ -138,7 +152,6 @@ install(
ARCHIVE COMPONENT simdjson_Development
INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
)
configure_file(cmake/simdjson-config.cmake.in simdjson-config.cmake @ONLY)
write_basic_package_version_file(
@@ -167,6 +180,20 @@ install(
COMPONENT simdjson_Development
)
if(SIMDJSON_BUILD_STATIC_LIB)
install(
TARGETS simdjson_static
EXPORT simdjson_staticTargets
ARCHIVE COMPONENT simdjson_Development
)
install(
EXPORT simdjson_staticTargets
NAMESPACE simdjson::
DESTINATION "${SIMDJSON_INSTALL_CMAKEDIR}"
COMPONENT simdjson_Development
)
endif()
# pkg-config
include(cmake/JoinPaths.cmake)
join_paths(PKGCONFIG_INCLUDEDIR "\${prefix}" "${CMAKE_INSTALL_INCLUDEDIR}")
+1 -1
View File
@@ -38,7 +38,7 @@ PROJECT_NAME = simdjson
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER = "3.2.1"
PROJECT_NUMBER = "3.6.2"
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
+4 -3
View File
@@ -1,8 +1,6 @@
[![Ubuntu 20.04 CI](https://github.com/simdjson/simdjson/workflows/Ubuntu%2020.04%20CI%20(GCC%209)/badge.svg)](https://simdjson.org/plots.html)
![VS16-CI](https://github.com/simdjson/simdjson/workflows/VS16-CI/badge.svg)
[![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/simdjson.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:simdjson)
![MinGW64-CI](https://github.com/simdjson/simdjson/workflows/MinGW64-CI/badge.svg)
[![][license img]][license]
[![Doxygen Documentation](https://img.shields.io/badge/docs-doxygen-green.svg)](https://simdjson.github.io/simdjson/)
@@ -42,8 +40,10 @@ Table of Contents
Real-world usage
----------------
- [Node.js](https://nodejs.org/)
- [ClickHouse](https://github.com/ClickHouse/ClickHouse)
- [Facebook/Meta Velox](https://velox-lib.io)
- [Meta Velox](https://velox-lib.io)
- [Google Pax](https://github.com/google/paxml)
- [milvus](https://github.com/milvus-io/milvus)
- [Clang Build Analyzer](https://github.com/aras-p/ClangBuildAnalyzer)
- [Shopify HeapProfiler](https://github.com/Shopify/heap-profiler)
@@ -165,6 +165,7 @@ We distinguish between "bindings" (which just wrap the C++ code) and a port to a
- [simdjzon](https://github.com/travisstaloch/simdjzon): zig port.
- [JSON-Simd](https://github.com/rawleyfowler/JSON-simd): Raku bindings.
- [JSON::SIMD](https://metacpan.org/pod/JSON::SIMD): Perl bindings; fully-featured JSON module that uses simdjson for decoding.
- [gemmaJSON](https://github.com/sainttttt/gemmaJSON): Nim json parser based on simdjson bindings.
About simdjson
--------------
@@ -1,72 +0,0 @@
#pragma once
#if SIMDJSON_EXCEPTIONS
#include "amazon_cellphones.h"
namespace amazon_cellphones {
using namespace simdjson;
template<bool threaded>
struct simdjson_singlestage {
using StringType = std::string;
singlestage::parser parser{};
bool run(simdjson::padded_string &json, std::map<StringType, brand> &result) {
#ifdef SIMDJSON_THREADS_ENABLED
parser.threaded = threaded;
#endif
singlestage::document_stream stream = parser.iterate_many(json);
singlestage::document_stream::iterator i = stream.begin();
++i; // Skip first line
for (;i != stream.end(); ++i) {
auto doc = *i;
size_t index{0};
StringType copy;
double rating;
uint64_t reviews;
for ( auto value : doc ) {
switch (index)
{
case 1:
copy = StringType(std::string_view(value));
break;
case 5:
rating = double(value);
break;
case 7:
reviews = uint64_t(value);
break;
default:
break;
}
index++;
}
auto x = result.find(copy);
if (x == result.end()) { // If key not found, add new key
result.emplace(copy, amazon_cellphones::brand{
rating * reviews,
reviews
});
} else { // Otherwise, update key data
x->second.cumulative_rating += rating * reviews;
x->second.reviews_count += reviews;
}
}
return true;
}
};
BENCHMARK_TEMPLATE(amazon_cellphones, simdjson_singlestage<UNTHREADED>)->UseManualTime();
#ifdef SIMDJSON_THREADS_ENABLED
BENCHMARK_TEMPLATE(amazon_cellphones, simdjson_singlestage<THREADED>)->UseManualTime();
#endif
} // namespace amazon_cellphones
#endif // SIMDJSON_EXCEPTIONS
File diff suppressed because it is too large Load Diff
-13
View File
@@ -26,7 +26,6 @@ SIMDJSON_PUSH_DISABLE_ALL_WARNINGS
SIMDJSON_POP_DISABLE_WARNINGS
#include "json2msgpack/simdjson_ondemand.h"
#include "json2msgpack/simdjson_singlestage.h"
#include "json2msgpack/simdjson_dom.h"
#include "json2msgpack/yyjson.h"
#include "json2msgpack/rapidjson.h"
@@ -36,7 +35,6 @@ SIMDJSON_POP_DISABLE_WARNINGS
#include "json2msgpack/nlohmann_json.h"
#include "partial_tweets/simdjson_ondemand.h"
#include "partial_tweets/simdjson_singlestage.h"
#include "partial_tweets/simdjson_dom.h"
#include "partial_tweets/yyjson.h"
#if SIMDJSON_COMPETITION_ONDEMAND_SAJSON
@@ -54,8 +52,6 @@ SIMDJSON_POP_DISABLE_WARNINGS
#include "distinct_user_id/simdjson_ondemand.h"
#include "distinct_user_id/simdjson_ondemand_json_pointer.h"
#include "distinct_user_id/simdjson_singlestage.h"
#include "distinct_user_id/simdjson_singlestage_json_pointer.h"
#include "distinct_user_id/simdjson_dom.h"
#include "distinct_user_id/simdjson_dom_json_pointer.h"
#include "distinct_user_id/yyjson.h"
@@ -72,7 +68,6 @@ SIMDJSON_POP_DISABLE_WARNINGS
#endif // SIMDJSON_COMPETITION_SAX
#include "find_tweet/simdjson_ondemand.h"
#include "find_tweet/simdjson_singlestage.h"
#include "find_tweet/simdjson_dom.h"
#include "find_tweet/yyjson.h"
#if SIMDJSON_COMPETITION_ONDEMAND_SAJSON
@@ -88,7 +83,6 @@ SIMDJSON_POP_DISABLE_WARNINGS
#endif // SIMDJSON_COMPETITION_SAX
#include "top_tweet/simdjson_ondemand.h"
#include "top_tweet/simdjson_singlestage.h"
#include "top_tweet/simdjson_dom.h"
#include "top_tweet/yyjson.h"
#if SIMDJSON_COMPETITION_ONDEMAND_SAJSON
@@ -105,7 +99,6 @@ SIMDJSON_POP_DISABLE_WARNINGS
#include "kostya/simdjson_ondemand.h"
#include "kostya/simdjson_singlestage.h"
#include "kostya/simdjson_dom.h"
#include "kostya/yyjson.h"
#if SIMDJSON_COMPETITION_ONDEMAND_SAJSON
@@ -124,10 +117,6 @@ SIMDJSON_POP_DISABLE_WARNINGS
#if SIMDJSON_COMPETITION_ONDEMAND_UNORDERED
#include "large_random/simdjson_ondemand_unordered.h"
#endif // SIMDJSON_COMPETITION_ONDEMAND_UNORDERED
#include "large_random/simdjson_singlestage.h"
#if SIMDJSON_COMPETITION_SINGLESTAGE_UNORDERED
#include "large_random/simdjson_singlestage_unordered.h"
#endif // SIMDJSON_COMPETITION_SINGLESTAGE_UNORDERED
#include "large_random/simdjson_dom.h"
#include "large_random/yyjson.h"
#if SIMDJSON_COMPETITION_ONDEMAND_SAJSON
@@ -144,10 +133,8 @@ SIMDJSON_POP_DISABLE_WARNINGS
#include "amazon_cellphones/simdjson_dom.h"
#include "amazon_cellphones/simdjson_ondemand.h"
#include "amazon_cellphones/simdjson_singlestage.h"
#include "large_amazon_cellphones/simdjson_dom.h"
#include "large_amazon_cellphones/simdjson_ondemand.h"
#include "large_amazon_cellphones/simdjson_singlestage.h"
BENCHMARK_MAIN();
+13 -9
View File
@@ -445,7 +445,7 @@ struct benchmarker {
return 100.0 * a / b;
}
void print(bool tabbed_output) const {
void print(bool tabbed_output, bool stage1_only) const {
if (tabbed_output) {
char* filename_copy = reinterpret_cast<char*>(malloc(strlen(filename)+1));
SIMDJSON_PUSH_DISABLE_WARNINGS
@@ -503,17 +503,21 @@ struct benchmarker {
stats->blocks_with_16_structurals_flipped, percent(stats->blocks_with_16_structurals_flipped, stats->blocks));
}
printf("\n");
printf("All Stages (excluding allocation)\n");
print_aggregate("| " , all_stages_without_allocation.best);
// frequently, allocation is a tiny fraction of the running time so we omit it
if(allocate_stage.best.elapsed_sec() > 0.01 * all_stages_without_allocation.best.elapsed_sec()) {
printf("|- Allocation\n");
print_aggregate("| ", allocate_stage.best);
if(!stage1_only) {
printf("All Stages (excluding allocation)\n");
print_aggregate("| " , all_stages_without_allocation.best);
// frequently, allocation is a tiny fraction of the running time so we omit it
if(allocate_stage.best.elapsed_sec() > 0.01 * all_stages_without_allocation.best.elapsed_sec()) {
printf("|- Allocation\n");
print_aggregate("| ", allocate_stage.best);
}
}
printf("|- Stage 1\n");
print_aggregate("| ", stage1.best);
printf("|- Stage 2\n");
print_aggregate("| ", stage2.best);
if(!stage1_only) {
printf("|- Stage 2\n");
print_aggregate("| ", stage2.best);
}
if (collector.has_events()) {
double freq1 = (stage1.best.cycles() / stage1.best.elapsed_sec()) / 1000000000.0;
double freq2 = (stage2.best.cycles() / stage2.best.elapsed_sec()) / 1000000000.0;
@@ -1,37 +0,0 @@
#pragma once
#if SIMDJSON_EXCEPTIONS
#include "distinct_user_id.h"
namespace distinct_user_id {
using namespace simdjson;
struct simdjson_singlestage {
singlestage::parser parser{};
bool run(simdjson::padded_string &json, std::vector<uint64_t> &result) {
// Walk the document, parsing as we go
auto doc = parser.iterate(json);
for (singlestage::object tweet : doc.find_field("statuses")) {
// We believe that all statuses have a matching
// user, and we are willing to throw when they do not.
result.push_back(tweet.find_field("user").find_field("id"));
// Not all tweets have a "retweeted_status", but when they do
// we want to go and find the user within.
auto retweet = tweet.find_field("retweeted_status");
if (!retweet.error()) {
result.push_back(retweet.find_field("user").find_field("id"));
}
}
return true;
}
};
BENCHMARK_TEMPLATE(distinct_user_id, simdjson_singlestage)->UseManualTime();
} // namespace distinct_user_id
#endif // SIMDJSON_EXCEPTIONS
@@ -1,37 +0,0 @@
#pragma once
#if SIMDJSON_EXCEPTIONS
#include "distinct_user_id.h"
namespace distinct_user_id {
using namespace simdjson;
struct simdjson_singlestage_json_pointer {
singlestage::parser parser{};
bool run(simdjson::padded_string &json, std::vector<uint64_t> &result) {
// Walk the document, parsing as we go
auto doc = parser.iterate(json);
for (singlestage::object tweet : doc.find_field("statuses")) {
// We believe that all statuses have a matching
// user, and we are willing to throw when they do not.
result.push_back(tweet.at_pointer("/user/id"));
// Not all tweets have a "retweeted_status", but when they do
// we want to go and find the user within.
auto retweet_id = tweet.at_pointer("/retweeted_status/user/id");
if (retweet_id.error() != NO_SUCH_FIELD) {
result.push_back(retweet_id);
}
}
return true;
}
};
BENCHMARK_TEMPLATE(distinct_user_id, simdjson_singlestage_json_pointer)->UseManualTime();
} // namespace distinct_user_id
#endif // SIMDJSON_EXCEPTIONS
+1 -1
View File
@@ -218,7 +218,7 @@ int main(int argc, char *argv[]) {
if (!options.verbose) { progress.erase(); }
for (size_t i=0; i<options.files.size(); i++) {
benchmarkers[i]->print(options.tabbed_output);
benchmarkers[i]->print(options.tabbed_output, options.stage1_only);
delete benchmarkers[i];
}
+28 -3
View File
@@ -34,11 +34,15 @@
#include <string>
#include <vector>
#include "linux-perf-events.h"
#ifdef __linux__
#include "linux-perf-events.h"
#include <libgen.h>
#endif
#if __APPLE__ && __aarch64__
#include "apple/apple_arm_events.h"
#endif
#include "simdjson.h"
using std::string;
@@ -134,7 +138,7 @@ struct event_collector {
#if defined(__linux__)
LinuxEvents<PERF_TYPE_HARDWARE> linux_events;
event_collector(simdjson_unused bool quiet = false) : linux_events(vector<int>{
event_collector() : linux_events(vector<int>{
#if SIMDJSON_SIMPLE_PERFORMANCE_COUNTERS
PERF_COUNT_HW_CPU_CYCLES,
PERF_COUNT_HW_INSTRUCTIONS,
@@ -149,8 +153,17 @@ struct event_collector {
bool has_events() {
return linux_events.is_working();
}
#elif __APPLE__ && __aarch64__
AppleEvents apple_events;
performance_counters diff;
event_collector() : diff(0) {
apple_events.setup_performance_counters();
}
bool has_events() {
return apple_events.setup_performance_counters();
}
#else
event_collector(simdjson_unused bool _quiet = false) {}
event_collector() {}
bool has_events() {
return false;
}
@@ -159,6 +172,8 @@ struct event_collector {
simdjson_inline void start() {
#if defined(__linux)
linux_events.start();
#elif __APPLE__ && __aarch64__
if(has_events()) { diff = apple_events.get_counters(); }
#endif
start_clock = steady_clock::now();
}
@@ -166,6 +181,16 @@ struct event_collector {
time_point<steady_clock> end_clock = steady_clock::now();
#if defined(__linux)
linux_events.end(count.event_counts);
#elif __APPLE__ && __aarch64__
if(has_events()) {
performance_counters end = apple_events.get_counters();
diff = end - diff;
}
count.event_counts[0] = diff.cycles;
count.event_counts[1] = diff.instructions;
count.event_counts[2] = diff.missed_branches;
count.event_counts[3] = 0;
count.event_counts[4] = 0;
#endif
count.elapsed = end_clock - start_clock;
return count;
@@ -1,33 +0,0 @@
#pragma once
#if SIMDJSON_EXCEPTIONS
#include "find_tweet.h"
namespace find_tweet {
using namespace simdjson;
struct simdjson_singlestage {
using StringType=std::string_view;
singlestage::parser parser{};
bool run(simdjson::padded_string &json, uint64_t find_id, std::string_view &result) {
// Walk the document, parsing as we go
auto doc = parser.iterate(json);
for (auto tweet : doc.find_field("statuses")) {
if (uint64_t(tweet.find_field("id")) == find_id) {
result = tweet.find_field("text");
return true;
}
}
return false;
}
};
BENCHMARK_TEMPLATE(find_tweet, simdjson_singlestage)->UseManualTime();
} // namespace find_tweet
#endif // SIMDJSON_EXCEPTIONS
+14 -14
View File
@@ -8,7 +8,7 @@ namespace json2msgpack {
using namespace simdjson;
/**
* @brief The simdjsonondemand2msgpack struct is used to quickly convert
* @brief The simdjson2msgpack struct is used to quickly convert
* JSON strings to msgpack views. You must provide a pointer to
* a large memory region where the msgpack gets written. The
* buffer should be large enough to store the msgpack output (which
@@ -17,7 +17,7 @@ using namespace simdjson;
*
* Recommended usage:
*
* simdjsonondemand2msgpack parser{};
* simdjson2msgpack parser{};
* simdjson::padded_string json = "[1,2]"_padded; // some JSON
* uint8_t * buffer = new uint8_t[3*json.size() + simdjson::SIMDJSON_PADDING]; // large buffer
*
@@ -26,10 +26,10 @@ using namespace simdjson;
* The result (msgpack) is a string view to a msgpack serialization of the input JSON,
* it points inside the buffer you provided.
*
* You may reuse the simdjsonondemand2msgpack instance though you should use
* You may reuse the simdjson2msgpack instance though you should use
* one per thread.
*/
struct simdjsonondemand2msgpack {
struct simdjson2msgpack {
/**
* @brief Converts the provided JSON into msgpack.
*
@@ -58,7 +58,7 @@ private:
};
std::string_view
simdjsonondemand2msgpack::to_msgpack(const simdjson::padded_string &json,
simdjson2msgpack::to_msgpack(const simdjson::padded_string &json,
uint8_t *buf) {
buff = buf;
ondemand::document doc = parser.iterate(json);
@@ -106,33 +106,33 @@ simdjsonondemand2msgpack::to_msgpack(const simdjson::padded_string &json,
return std::string_view(reinterpret_cast<char *>(buf), size_t(buff - buf));
}
void simdjsonondemand2msgpack::write_double(const double d) noexcept {
void simdjson2msgpack::write_double(const double d) noexcept {
*buff++ = 0xcb;
::memcpy(buff, &d, sizeof(d));
buff += sizeof(d);
}
void simdjsonondemand2msgpack::write_byte(const uint8_t b) noexcept {
void simdjson2msgpack::write_byte(const uint8_t b) noexcept {
*buff = b;
buff++;
}
void simdjsonondemand2msgpack::write_uint32(const uint32_t w) noexcept {
void simdjson2msgpack::write_uint32(const uint32_t w) noexcept {
::memcpy(buff, &w, sizeof(w));
buff += sizeof(w);
}
uint8_t *simdjsonondemand2msgpack::skip_uint32() noexcept {
uint8_t *simdjson2msgpack::skip_uint32() noexcept {
uint8_t *ret = buff;
buff += sizeof(uint32_t);
return ret;
}
void simdjsonondemand2msgpack::write_uint32_at(const uint32_t w, uint8_t *p) noexcept {
void simdjson2msgpack::write_uint32_at(const uint32_t w, uint8_t *p) noexcept {
::memcpy(p, &w, sizeof(w));
}
void simdjsonondemand2msgpack::write_raw_string(
void simdjson2msgpack::write_raw_string(
simdjson::ondemand::raw_json_string in) {
write_byte(0xdb);
uint8_t *location = skip_uint32();
@@ -140,7 +140,7 @@ void simdjsonondemand2msgpack::write_raw_string(
write_uint32_at(uint32_t(v.size()), location);
}
void simdjsonondemand2msgpack::recursive_processor(simdjson::ondemand::value element) {
void simdjson2msgpack::recursive_processor(simdjson::ondemand::value element) {
switch (element.type()) {
case simdjson::ondemand::json_type::array: {
uint32_t counter = 0;
@@ -185,7 +185,7 @@ void simdjsonondemand2msgpack::recursive_processor(simdjson::ondemand::value ele
}
void simdjsonondemand2msgpack::recursive_processor_ref(simdjson::ondemand::value& element) {
void simdjson2msgpack::recursive_processor_ref(simdjson::ondemand::value& element) {
switch (element.type()) {
case simdjson::ondemand::json_type::array: {
uint32_t counter = 0;
@@ -234,7 +234,7 @@ void simdjsonondemand2msgpack::recursive_processor_ref(simdjson::ondemand::value
struct simdjson_ondemand {
using StringType = std::string_view;
simdjsonondemand2msgpack parser{};
simdjson2msgpack parser{};
bool run(simdjson::padded_string &json, char *buffer,
std::string_view &result) {
@@ -1,250 +0,0 @@
#pragma once
#if SIMDJSON_EXCEPTIONS
#include "json2msgpack.h"
namespace json2msgpack {
using namespace simdjson;
/**
* @brief The simdjsonsinglestage2msgpack struct is used to quickly convert
* JSON strings to msgpack views. You must provide a pointer to
* a large memory region where the msgpack gets written. The
* buffer should be large enough to store the msgpack output (which
* can never be 3x larger than the input JSON) with an additional
* simdjson::SIMDJSON_PADDING bytes.
*
* Recommended usage:
*
* simdjsonsinglestage2msgpack parser{};
* simdjson::padded_string json = "[1,2]"_padded; // some JSON
* uint8_t * buffer = new uint8_t[3*json.size() + simdjson::SIMDJSON_PADDING]; // large buffer
*
* std::string_view msgpack = parser.to_msgpack(json, buffer);
*
* The result (msgpack) is a string view to a msgpack serialization of the input JSON,
* it points inside the buffer you provided.
*
* You may reuse the simdjsonsinglestage2msgpack instance though you should use
* one per thread.
*/
struct simdjsonsinglestage2msgpack {
/**
* @brief Converts the provided JSON into msgpack.
*
* @param json JSON input
* @param buf temporary buffer (must be large enough, with simdjson::SIMDJSON_PADDING bytes
* of padding)
* @return std::string_view msgpack output, writing to the temporary buffer
*/
inline std::string_view to_msgpack(const simdjson::padded_string &json,
uint8_t *buf);
private:
simdjson_inline void write_double(const double d) noexcept;
simdjson_inline void write_byte(const uint8_t b) noexcept;
simdjson_inline void write_uint32(const uint32_t w) noexcept;
simdjson_inline uint8_t *skip_uint32() noexcept;
simdjson_inline void write_uint32_at(const uint32_t w,
uint8_t *p) noexcept;
simdjson_inline void
write_raw_string(simdjson::singlestage::raw_json_string rjs);
inline void recursive_processor(simdjson::singlestage::value element);
inline void recursive_processor_ref(simdjson::singlestage::value& element);
simdjson::singlestage::parser parser;
uint8_t *buff{};
};
std::string_view
simdjsonsinglestage2msgpack::to_msgpack(const simdjson::padded_string &json,
uint8_t *buf) {
buff = buf;
singlestage::document doc = parser.iterate(json);
if (doc.is_scalar()) {
// we have a special case where the JSON document is a single document...
switch (doc.type()) {
case simdjson::singlestage::json_type::number:
write_double(doc.get_double());
break;
case simdjson::singlestage::json_type::string:
write_raw_string(doc.get_raw_json_string());
break;
case simdjson::singlestage::json_type::boolean:
write_byte(0xc2 + doc.get_bool());
break;
case simdjson::singlestage::json_type::null:
// We check that the value is indeed null
// otherwise: an error is thrown.
if(doc.is_null()) {
write_byte(0xc0);
}
break;
case simdjson::singlestage::json_type::array:
case simdjson::singlestage::json_type::object:
default:
// impossible
SIMDJSON_UNREACHABLE();
}
} else {
simdjson::singlestage::value val = doc;
#define SIMDJSON_GCC_COMPILER ((__GNUC__) && !(__clang__) && !(__INTEL_COMPILER))
#if SIMDJSON_GCC_COMPILER
// the GCC compiler does well with by-value passing.
// GCC has superior recursive inlining:
// https://stackoverflow.com/questions/29186186/why-does-gcc-generate-a-faster-program-than-clang-in-this-recursive-fibonacci-co
// https://godbolt.org/z/TeK4doE51
recursive_processor(val);
#else
recursive_processor_ref(val);
#endif
}
if (!doc.at_end()) {
throw "There are unexpectedly tokens after the end of the json in the json2msgpack sample data";
}
return std::string_view(reinterpret_cast<char *>(buf), size_t(buff - buf));
}
void simdjsonsinglestage2msgpack::write_double(const double d) noexcept {
*buff++ = 0xcb;
::memcpy(buff, &d, sizeof(d));
buff += sizeof(d);
}
void simdjsonsinglestage2msgpack::write_byte(const uint8_t b) noexcept {
*buff = b;
buff++;
}
void simdjsonsinglestage2msgpack::write_uint32(const uint32_t w) noexcept {
::memcpy(buff, &w, sizeof(w));
buff += sizeof(w);
}
uint8_t *simdjsonsinglestage2msgpack::skip_uint32() noexcept {
uint8_t *ret = buff;
buff += sizeof(uint32_t);
return ret;
}
void simdjsonsinglestage2msgpack::write_uint32_at(const uint32_t w, uint8_t *p) noexcept {
::memcpy(p, &w, sizeof(w));
}
void simdjsonsinglestage2msgpack::write_raw_string(
simdjson::singlestage::raw_json_string in) {
write_byte(0xdb);
uint8_t *location = skip_uint32();
std::string_view v = parser.unescape(in, buff);
write_uint32_at(uint32_t(v.size()), location);
}
void simdjsonsinglestage2msgpack::recursive_processor(simdjson::singlestage::value element) {
switch (element.type()) {
case simdjson::singlestage::json_type::array: {
uint32_t counter = 0;
write_byte(0xdd);
uint8_t *location = skip_uint32();
for (auto child : element.get_array()) {
counter++;
recursive_processor(child.value());
}
write_uint32_at(counter, location);
} break;
case simdjson::singlestage::json_type::object: {
uint32_t counter = 0;
write_byte(0xdf);
uint8_t *location = skip_uint32();
for (auto field : element.get_object()) {
counter++;
write_raw_string(field.key());
recursive_processor(field.value());
}
write_uint32_at(counter, location);
} break;
case simdjson::singlestage::json_type::number:
write_double(element.get_double());
break;
case simdjson::singlestage::json_type::string:
write_raw_string(element.get_raw_json_string());
break;
case simdjson::singlestage::json_type::boolean:
write_byte(0xc2 + element.get_bool());
break;
case simdjson::singlestage::json_type::null:
// We check that the value is indeed null
// otherwise: an error is thrown.
if(element.is_null()) {
write_byte(0xc0);
}
break;
default:
SIMDJSON_UNREACHABLE();
}
}
void simdjsonsinglestage2msgpack::recursive_processor_ref(simdjson::singlestage::value& element) {
switch (element.type()) {
case simdjson::singlestage::json_type::array: {
uint32_t counter = 0;
write_byte(0xdd);
uint8_t *location = skip_uint32();
for (auto child : element.get_array()) {
counter++;
simdjson::singlestage::value v = child.value();
recursive_processor_ref(v);
}
write_uint32_at(counter, location);
} break;
case simdjson::singlestage::json_type::object: {
uint32_t counter = 0;
write_byte(0xdf);
uint8_t *location = skip_uint32();
for (auto field : element.get_object()) {
counter++;
write_raw_string(field.key());
simdjson::singlestage::value v = field.value();
recursive_processor_ref(v);
}
write_uint32_at(counter, location);
} break;
case simdjson::singlestage::json_type::number:
write_double(element.get_double());
break;
case simdjson::singlestage::json_type::string:
write_raw_string(element.get_raw_json_string());
break;
case simdjson::singlestage::json_type::boolean:
write_byte(0xc2 + element.get_bool());
break;
case simdjson::singlestage::json_type::null:
// We check that the value is indeed null
// otherwise: an error is thrown.
if(element.is_null()) {
write_byte(0xc0);
}
break;
default:
SIMDJSON_UNREACHABLE();
}
}
struct simdjson_singlestage {
using StringType = std::string_view;
simdjsonsinglestage2msgpack parser{};
bool run(simdjson::padded_string &json, char *buffer,
std::string_view &result) {
result = parser.to_msgpack(json, reinterpret_cast<uint8_t *>(buffer));
return true;
}
};
BENCHMARK_TEMPLATE(json2msgpack, simdjson_singlestage)->UseManualTime();
} // namespace json2msgpack
#endif // SIMDJSON_EXCEPTIONS
@@ -13,15 +13,13 @@ void maybe_display_implementation() {
std::cout << "simdjson::dom implementation: " << simdjson::get_active_implementation()->name() << std::endl;
std::cout << "simdjson::ondemand implementation (stage 1): " << simdjson::get_active_implementation()->name() << std::endl;
std::cout << "simdjson::ondemand implementation (stage 2): " << simdjson::builtin_implementation()->name() << std::endl;
std::cout << "simdjson::singlestage implementation (stage 1): " << simdjson::get_active_implementation()->name() << std::endl;
std::cout << "simdjson::singlestage implementation (stage 2): " << simdjson::builtin_implementation()->name() << std::endl;
}
}
template<typename B, typename R> static void run_json_benchmark(benchmark::State &state) {
maybe_display_implementation();
event_collector collector(true);
event_collector collector;
event_aggregate events;
// Warmup and equality check (make sure the data is right!)
-29
View File
@@ -1,29 +0,0 @@
#pragma once
#if SIMDJSON_EXCEPTIONS
#include "kostya.h"
namespace kostya {
using namespace simdjson;
struct simdjson_singlestage {
static constexpr diff_flags DiffFlags = diff_flags::NONE;
singlestage::parser parser{};
bool run(simdjson::padded_string &json, std::vector<point> &result) {
auto doc = parser.iterate(json);
for (singlestage::object point : doc.find_field("coordinates")) {
result.emplace_back(json_benchmark::point{point.find_field("x"), point.find_field("y"), point.find_field("z")});
}
return true;
}
};
BENCHMARK_TEMPLATE(kostya, simdjson_singlestage)->UseManualTime();
} // namespace kostya
#endif // SIMDJSON_EXCEPTIONS
@@ -1,72 +0,0 @@
#pragma once
#if SIMDJSON_EXCEPTIONS
#include "large_amazon_cellphones.h"
namespace large_amazon_cellphones {
using namespace simdjson;
template<bool threaded>
struct simdjson_singlestage {
using StringType = std::string;
singlestage::parser parser{};
bool run(simdjson::padded_string &json, std::map<StringType, brand> &result) {
#ifdef SIMDJSON_THREADS_ENABLED
parser.threaded = threaded;
#endif
singlestage::document_stream stream = parser.iterate_many(json);
singlestage::document_stream::iterator i = stream.begin();
++i; // Skip first line
for (;i != stream.end(); ++i) {
auto doc = *i;
size_t index{0};
StringType copy;
double rating;
uint64_t reviews;
for ( auto value : doc ) {
switch (index)
{
case 1:
copy = StringType(std::string_view(value));
break;
case 5:
rating = double(value);
break;
case 7:
reviews = uint64_t(value);
break;
default:
break;
}
index++;
}
auto x = result.find(copy);
if (x == result.end()) { // If key not found, add new key
result.emplace(copy, large_amazon_cellphones::brand{
rating * reviews,
reviews
});
} else { // Otherwise, update key data
x->second.cumulative_rating += rating * reviews;
x->second.reviews_count += reviews;
}
}
return true;
}
};
BENCHMARK_TEMPLATE(large_amazon_cellphones, simdjson_singlestage<UNTHREADED>)->UseManualTime();
#ifdef SIMDJSON_THREADS_ENABLED
BENCHMARK_TEMPLATE(large_amazon_cellphones, simdjson_singlestage<THREADED>)->UseManualTime();
#endif
} // namespace amazon_cellphones
#endif // SIMDJSON_EXCEPTIONS
@@ -1,29 +0,0 @@
#pragma once
#if SIMDJSON_EXCEPTIONS
#include "large_random.h"
namespace large_random {
using namespace simdjson;
struct simdjson_singlestage {
static constexpr diff_flags DiffFlags = diff_flags::NONE;
singlestage::parser parser{};
bool run(simdjson::padded_string &json, std::vector<point> &result) {
auto doc = parser.iterate(json);
for (singlestage::object coord : doc) {
result.emplace_back(json_benchmark::point{coord.find_field("x"), coord.find_field("y"), coord.find_field("z")});
}
return true;
}
};
BENCHMARK_TEMPLATE(large_random, simdjson_singlestage)->UseManualTime();
} // namespace large_random
#endif // SIMDJSON_EXCEPTIONS
@@ -1,29 +0,0 @@
#pragma once
#if SIMDJSON_EXCEPTIONS
#include "large_random.h"
namespace large_random {
using namespace simdjson;
struct simdjson_singlestage_unordered {
static constexpr diff_flags DiffFlags = diff_flags::NONE;
singlestage::parser parser{};
bool run(simdjson::padded_string &json, std::vector<point> &result) {
auto doc = parser.iterate(json);
for (singlestage::object coord : doc) {
result.emplace_back(json_benchmark::point{coord["x"], coord["y"], coord["z"]});
}
return true;
}
};
BENCHMARK_TEMPLATE(large_random, simdjson_singlestage_unordered)->UseManualTime();
} // namespace large_random
#endif // SIMDJSON_EXCEPTIONS
-37
View File
@@ -1,37 +0,0 @@
#pragma once
#if SIMDJSON_EXCEPTIONS
#include "largerandom.h"
namespace largerandom {
using namespace simdjson;
class OnDemand {
public:
simdjson_inline bool Run(const padded_string &json);
simdjson_inline const std::vector<my_point> &Result() { return container; }
simdjson_inline size_t ItemCount() { return container.size(); }
private:
singlestage::parser parser{};
std::vector<my_point> container{};
};
simdjson_inline bool OnDemand::Run(const padded_string &json) {
container.clear();
auto doc = parser.iterate(json);
for (singlestage::object coord : doc) {
container.emplace_back(my_point{coord.find_field("x"), coord.find_field("y"), coord.find_field("z")});
}
return true;
}
BENCHMARK_TEMPLATE(LargeRandom, OnDemand);
} // namespace largerandom
#endif // SIMDJSON_EXCEPTIONS
@@ -1,48 +0,0 @@
#pragma once
#if SIMDJSON_EXCEPTIONS
#include "partial_tweets.h"
namespace partial_tweets {
using namespace simdjson;
struct simdjson_singlestage {
using StringType=std::string_view;
singlestage::parser parser{};
simdjson_inline uint64_t nullable_int(singlestage::value value) {
if (value.is_null()) { return 0; }
return value;
}
simdjson_inline twitter_user<std::string_view> read_user(singlestage::object user) {
return { user.find_field("id"), user.find_field("screen_name") };
}
bool run(simdjson::padded_string &json, std::vector<tweet<std::string_view>> &result) {
// Walk the document, parsing the tweets as we go
auto doc = parser.iterate(json);
for (singlestage::object tweet : doc.find_field("statuses")) {
result.emplace_back(partial_tweets::tweet<std::string_view>{
tweet.find_field("created_at"),
tweet.find_field("id"),
tweet.find_field("text"),
nullable_int(tweet.find_field("in_reply_to_status_id")),
read_user(tweet.find_field("user")),
tweet.find_field("retweet_count"),
tweet.find_field("favorite_count")
});
}
return true;
}
};
BENCHMARK_TEMPLATE(partial_tweets, simdjson_singlestage)->UseManualTime();
} // namespace partial_tweets
#endif // SIMDJSON_EXCEPTIONS
-63
View File
@@ -1,63 +0,0 @@
#pragma once
#if SIMDJSON_EXCEPTIONS
#include "partial_tweets.h"
namespace partial_tweets {
using namespace simdjson;
class SingleStage {
public:
SingleStage() {
if(!displayed_implementation) {
std::cout << "On Demand implementation: " << builtin_implementation()->name() << std::endl;
displayed_implementation = true;
}
}
simdjson_inline bool Run(const padded_string &json);
simdjson_inline const std::vector<tweet> &Result() { return tweets; }
simdjson_inline size_t ItemCount() { return tweets.size(); }
private:
singlestage::parser parser{};
std::vector<tweet> tweets{};
simdjson_inline uint64_t nullable_int(singlestage::value value) {
if (value.is_null()) { return 0; }
return value;
}
simdjson_inline twitter_user read_user(singlestage::object user) {
return { user.find_field("id"), user.find_field("screen_name") };
}
static inline bool displayed_implementation = false;
};
simdjson_inline bool SingleStage::Run(const padded_string &json) {
tweets.clear();
// Walk the document, parsing the tweets as we go
auto doc = parser.iterate(json);
for (singlestage::object tweet : doc.find_field("statuses")) {
tweets.emplace_back(partial_tweets::tweet{
tweet.find_field("created_at"),
tweet.find_field("id"),
tweet.find_field("text"),
nullable_int(tweet.find_field("in_reply_to_status_id")),
read_user(tweet.find_field("user")),
tweet.find_field("retweet_count"),
tweet.find_field("favorite_count")
});
}
return true;
}
BENCHMARK_TEMPLATE(PartialTweets, SingleStage);
} // namespace partial_tweets
#endif // SIMDJSON_EXCEPTIONS
@@ -1,80 +0,0 @@
#pragma once
#if SIMDJSON_EXCEPTIONS
#include "top_tweet.h"
namespace top_tweet {
using namespace simdjson;
struct simdjson_singlestage {
using StringType=std::string_view;
singlestage::parser parser{};
bool run(simdjson::padded_string &json, int64_t max_retweet_count, top_tweet_result<StringType> &result) {
result.retweet_count = -1;
// We save these DOM values for later so we don't have to parse them
// into string_views until we're sure which ones we want to parse
// NOTE: simdjson does not presently support reuse of objects or arrays--just scalars. This is
// why we have to grab the text and screen_name fields instead of just saving the tweet object.
singlestage::value screen_name, text;
auto doc = parser.iterate(json);
for (auto tweet : doc["statuses"]) {
// Since text, user.screen_name, and retweet_count generally appear in order, it's nearly free
// for us to retrieve them here (and will cost a bit more if we do it in the if
// statement).
auto tweet_text = tweet["text"];
auto tweet_screen_name = tweet["user"]["screen_name"];
int64_t retweet_count = tweet["retweet_count"];
if (retweet_count <= max_retweet_count && retweet_count >= result.retweet_count) {
result.retweet_count = retweet_count;
// TODO std::move should not be necessary
text = std::move(tweet_text);
screen_name = std::move(tweet_screen_name);
}
}
// Now that we know which was the most retweeted, parse the values in it
result.screen_name = screen_name;
result.text = text;
return result.retweet_count != -1;
}
};
BENCHMARK_TEMPLATE(top_tweet, simdjson_singlestage)->UseManualTime();
struct simdjson_singlestage_forward_only {
using StringType=std::string_view;
singlestage::parser parser{};
bool run(simdjson::padded_string &json, int64_t max_retweet_count, top_tweet_result<StringType> &result) {
result.retweet_count = -1;
auto doc = parser.iterate(json);
for (auto tweet : doc["statuses"]) {
// Since text, user.screen_name, and retweet_count generally appear in order, it's nearly free
// for us to retrieve them here (and will cost a bit more if we do it in the if
// statement).
auto tweet_text = tweet["text"];
auto tweet_screen_name = tweet["user"]["screen_name"];
int64_t retweet_count = tweet["retweet_count"];
if (retweet_count <= max_retweet_count && retweet_count >= result.retweet_count) {
result.retweet_count = retweet_count;
result.text = tweet_text;
result.screen_name = tweet_screen_name;
}
}
return result.retweet_count != -1;
}
};
BENCHMARK_TEMPLATE(top_tweet, simdjson_singlestage_forward_only)->UseManualTime();
} // namespace top_tweet
#endif // SIMDJSON_EXCEPTIONS
+5 -1
View File
@@ -114,10 +114,14 @@ set(SIMDJSON_CXX_STANDARD 17 CACHE STRING "the C++ standard to use for simdjson"
set(CMAKE_CXX_STANDARD ${SIMDJSON_CXX_STANDARD})
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_MACOSX_RPATH OFF)
set(CMAKE_THREAD_PREFER_PTHREAD ON)
set(THREADS_PREFER_PTHREAD_FLAG ON)
set(SIMDJSON_STRUCTURAL_INDEXER_STEP CACHE STRING "the SIMDJSON_STRUCTURAL_INDEXER_STEP variable")
if(SIMDJSON_STRUCTURAL_INDEXER_STEP)
message(STATUS "Setting SIMDJSON_STRUCTURAL_INDEXER_STEP to ${SIMDJSON_STRUCTURAL_INDEXER_STEP}.")
add_compile_definitions(SIMDJSON_STRUCTURAL_INDEXER_STEP=${SIMDJSON_STRUCTURAL_INDEXER_STEP})
endif()
# LTO seems to create all sorts of fun problems. Let us
# disable temporarily.
#include(CheckIPOSupported)
+1
View File
@@ -4,3 +4,4 @@ if("@SIMDJSON_ENABLE_THREADS@")
endif()
include("${CMAKE_CURRENT_LIST_DIR}/simdjsonTargets.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/simdjson_staticTargets.cmake" OPTIONAL)
+203 -46
View File
@@ -30,6 +30,7 @@ An overview of what you need to know to use simdjson, with examples.
- [Dynamic Number Types](#dynamic-number-types)
- [Raw Strings](#raw-strings)
- [General Direct Access to the Raw JSON String](#general-direct-access-to-the-raw-json-string)
- [Storing Directly into an Existing String Instance](#storing-directly-into-an-existing-string-instance)
- [Thread Safety](#thread-safety)
- [Standard Compliance](#standard-compliance)
- [Backwards Compatibility](#backwards-compatibility)
@@ -85,7 +86,7 @@ include(FetchContent)
FetchContent_Declare(
simdjson
GIT_REPOSITORY https://github.com/simdjson/simdjson.git
GIT_TAG tags/v0.9.6
GIT_TAG tags/v3.6.0
GIT_SHALLOW TRUE)
FetchContent_MakeAvailable(simdjson)
@@ -179,8 +180,8 @@ strcpy(json, "[1]");
ondemand::document doc = parser.iterate(json, strlen(json), sizeof(json));
```
The simdjson library will also accept `std::string` instances, as long as the `capacity()` of
the string exceeds the `size()` by at least `SIMDJSON_PADDING`. You can increase the `capacity()` with the `reserve()` function of your strings.
The simdjson library will also accept `std::string` instances. If the provided
reference is non-const, it will allocate padding as needed.
You can copy your data directly on a `simdjson::padded_string` as follows:
@@ -218,7 +219,8 @@ This means that while you iterate an array, or search for a field in an object,
walking through the original JSON text, merrily reading commas and colons and brackets to make sure
you get where you are going. This is the key to On Demand's performance: since it's just an iterator,
it lets you parse values as you use them. And particularly, it lets you *skip* values you do not want
to use.
to use. On Demand is also ideally suited when you want to capture part of the document without parsing it
immediately (e.g., see [Raw Strings](#raw-strings)).
We refer to "On Demand" as a front-end component since it is an interface between the
low-level parsing functions and the user. It hides much of the complexity of parsing JSON
@@ -253,7 +255,8 @@ copy the data into their own favorite class instances (e.g., alternatives to `st
A `std::string_view` instance is effectively just a pointer to a region in memory representing
a string. In simdjson, we return `std::string_view` instances that either point within the
input string you parsed, or to a temporary string buffer inside our parser class instances.
input string you parsed (when using [raw Strings](#raw-strings)), or to a temporary string buffer inside
our parser class instances that is valid until the parser object is destroyed or you use it to parse another document.
When using `std::string_view` instances, it is your responsibility to ensure that
`std::string_view` instance does not outlive the pointed-to memory (e.g., either the input
buffer or the parser instance). Furthermore, some operations reset the string buffer
@@ -261,6 +264,7 @@ inside our parser instances: e.g., when we parse a new document. Thus a `std::st
is often best viewed as a temporary string value that is tied to the document you are parsing.
At the cost of some memory allocation, you may convert your `std::string_view` instances for long-term storage into `std::string` instances:
`std::string mycopy(view)` (C++17) or `std::string mycopy(view.begin(), view.end())` (prior to C++17).
For convenience, we also allow [storing an escaped string directly into an existing string instance](#storing-directly-into-an-existing-string-instance).
The `std::string_view` class has become standard as part of C++17 but it is not always available
on compilers which only supports C++11. When we detect that `string_view` is natively
@@ -355,7 +359,7 @@ support for users who avoid exceptions. See [the simdjson error handling documen
* **Field Access:** To get the value of the "foo" field in an object, use `object["foo"]`. This will
scan through the object looking for the field with the matching string, doing a character-by-character
comparison. It may generate the error `simdjson::NO_SUCH_FIELD` if there is no such key in the object, it may throw an exception (see [Error Handling](#error-handling)). For efficiency reason, you should avoid looking up the same field repeatedly: e.g., do
not do `object["foo"]` followed by `object["foo"]` with the same `object` instance. Keep in mind that On Demand does not buffer or save the result of the parsing: if you repeatedly access `object["foo"]`, then it must repeatedly seek the key and parse the content. The library does not provide a distinct function to check if a key is present, instead we recommend you attempt to access the key: e.g., by doing `ondemand::value val{}; if(!object["foo"].get(val)) {...}`, you have that `val` contains the requested value inside the if clause. It is your responsibility as a user to temporarily keep a reference to the value (`auto v = object["foo"]`), or to consume the content and store it in your own data structures. If you consume an
not do `object["foo"]` followed by `object["foo"]` with the same `object` instance. For best performance, you should try to query the keys in the same order they appear in the document. If you need several keys and you cannot predict the order they will appear in, it is recommended to iterate through all keys `for(auto field : object) {...}`. Keep in mind that On Demand does not buffer or save the result of the parsing: if you repeatedly access `object["foo"]`, then it must repeatedly seek the key and parse the content. The library does not provide a distinct function to check if a key is present, instead we recommend you attempt to access the key: e.g., by doing `ondemand::value val{}; if (!object["foo"].get(val)) {...}`, you have that `val` contains the requested value inside the if clause. It is your responsibility as a user to temporarily keep a reference to the value (`auto v = object["foo"]`), or to consume the content and store it in your own data structures. If you consume an
object twice: `std::string_view(object["foo"]` followed by `std::string_view(object["foo"]` then your code
is in error. Furthermore, you can only consume one field at a time, on the same object. The
value instance you get from `content["bids"]` becomes invalid when you call `content["asks"]`.
@@ -370,7 +374,11 @@ support for users who avoid exceptions. See [the simdjson error handling documen
> as a key, it will not be recognized. This is not generally a problem. Nevertheless, if you do need
> to support escaped keys, the method `unescaped_key()` provides the desired unescaped keys by
> parsing and writing out the unescaped keys to a string buffer and returning a `std::string_view`
> instance. You should expect a performance penalty when using `unescaped_key()`.
> instance. The `unescaped_key` takes an optional Boolean value: passing it true will decode invalid
> Unicode sequences with replacement, meaning that the decoding always succeeds but bogus Unicode
> replacement characters are inserted. In general, you should expect a performance penalty
> when using `unescaped_key()` compared to `key()` because of the string processing: the `key()`
> function just points inside the source JSON document.
>
> ```c++
> auto json = R"({"k\u0065y": 1})"_padded;
@@ -381,7 +389,7 @@ support for users who avoid exceptions. See [the simdjson error handling documen
> // parses and writes out the key, after unescaping it,
> // to a string buffer. It causes a performance penalty.
> std::string_view keyv = field.unescaped_key();
> if(keyv == "key") { std::cout << uint64_t(field.value()); }
> if (keyv == "key") { std::cout << uint64_t(field.value()); }
> }
> ```
>
@@ -414,8 +422,10 @@ support for users who avoid exceptions. See [the simdjson error handling documen
step through each value in the JSON array.
If you know the type of the value, you can cast it right there, too! `for (double value : array) { ... }`.
* **Object Iteration:** You can iterate through an object's fields, as well: `for (auto field : object) { ... }`
- `field.unescaped_key()` will get you the unescaped key string.
You may also use explicit iterators: `for(auto i = array.begin(); i != array.end(); i++) {}`. You can check that an array is empty with the condition `auto i = array.begin(); if(i == array.end()) {...}`.
* **Object Iteration:** You can iterate through an object's fields, as well: `for (auto field : object) { ... }`. You may also use explicit iterators : `for(auto i = object.begin(); i != object.end(); i++) { auto field = *i; .... }`. You can check that an object is empty with the condition `auto i = object.begin(); if(i == object.end()) {...}`.
- `field.unescaped_key()` will get you the unescaped key string. E.g., the JSON string `"\u00e1"` becomes the Unicode string `á`. Optionally, you pass `true` as a parameter to the `unescaped_key` method if you want invalid escape sequences to be replaced by a default replacement character (e.g., `\ud800\ud801\ud811`): otherwise bad escape sequences lead to an immediate error.
- `field.value()` will get you the value, which you can then use all these other methods on.
* **Array Index:** Because it is forward-only, you cannot look up an array element by index by index. Instead,
you should iterate through the array and keep an index yourself.
@@ -445,7 +455,7 @@ support for users who avoid exceptions. See [the simdjson error handling documen
> {
> ondemand::parser parser;
> for (ondemand::object car : parser.iterate(cars_json)) {
> if(uint64_t(car["year"]) > 2000) {
> if (uint64_t(car["year"]) > 2000) {
> arrays.push_back(simdjson::to_json_string(car["tire_pressure"]));
> }
> }
@@ -454,7 +464,7 @@ support for users who avoid exceptions. See [the simdjson error handling documen
> std::ostringstream oss;
> oss << "[";
> for(size_t i = 0; i < arrays.size(); i++) {
> if(i>0) { oss << ","; }
> if (i>0) { oss << ","; }
> oss << arrays[i];
> }
> oss << "]";
@@ -535,9 +545,7 @@ support for users who avoid exceptions. See [the simdjson error handling documen
* **Tree Walking and JSON Element Types:** Sometimes you don't necessarily have a document
with a known type, and are trying to generically inspect or walk over JSON elements.
You can also represent arbitrary JSON values with
`ondemand::value` instances: it can represent anything except a scalar document (lone number, string, null or Boolean). You can check for scalar documents with the method `scalar()`.
You can query the type of a document or a value with the `type()` method.
The `type()` method does not consume or validate documents and values, but it tells you whether they are
`ondemand::value` instances: it can represent anything except a scalar document (lone number, string, null or Boolean). You can check for scalar documents with the method `scalar()`. You can cast a document that is either an array or an object to an `ondemand::value` instance immediately after you create the document instance: you cannot create a `ondemand::value` instance from a document that has already been accessed as it would mean that you would have two instances of the object or array simultaneously (see [rewinding](#rewinding)). You can query the type of a document or a value with the `type()` method. The `type()` method does not consume or validate documents and values, but it tells you whether they are
- arrays (`json_type::array`),
- objects (`json_type::object`)
- numbers (`json_type::number`),
@@ -597,7 +605,7 @@ support for users who avoid exceptions. See [the simdjson error handling documen
case ondemand::json_type::null:
// We check that the value is indeed null
// otherwise: an error is thrown.
if(element.is_null()) {
if (element.is_null()) {
cout << "null";
}
break;
@@ -910,11 +918,11 @@ bool simple_error_example() {
ondemand::parser parser;
auto json = R"({"bad number":3.14.1 })"_padded;
ondemand::document doc;
if( parser.iterate(json).get(doc) != SUCCESS ) { return false; }
if (parser.iterate(json).get(doc) != SUCCESS) { return false; }
double x;
auto error = doc["bad number"].get_double().get(x);
// returns "simdjson::NUMBER_ERROR"
if(error != SUCCESS) {
if (error != SUCCESS) {
std::cout << error << std::endl;
return false;
}
@@ -976,10 +984,10 @@ it selects the key `"count"` within that object.
int main(void) {
simdjson::ondemand::parser parser;
auto error = padded_string::load("twitter.json").get(json);
if(error) { std::cerr << error << std::endl; return EXIT_FAILURE; }
if (error) { std::cerr << error << std::endl; return EXIT_FAILURE; }
simdjson::ondemand::document tweets;
error = parser.iterate(json).get(tweets);
if( error ) { std::cerr << error << std::endl; return EXIT_FAILURE; }
if (error) { std::cerr << error << std::endl; return EXIT_FAILURE; }
simdjson::ondemand::value res;
error = tweets["search_metadata"]["count"].get(res);
if (error != SUCCESS) {
@@ -1010,12 +1018,12 @@ int main(void) {
simdjson::ondemand::document tweets;
padded_string json;
auto error = padded_string::load("twitter.json").get(json);
if(error) { std::cerr << error << std::endl; return EXIT_FAILURE; }
if (error) { std::cerr << error << std::endl; return EXIT_FAILURE; }
error = parser.iterate(json).get(tweets);
if(error) { std::cerr << error << std::endl; return EXIT_FAILURE; }
if (error) { std::cerr << error << std::endl; return EXIT_FAILURE; }
uint64_t identifier;
error = tweets["statuses"].at(0)["id"].get(identifier);
if(error) { std::cerr << error << std::endl; return EXIT_FAILURE; }
if (error) { std::cerr << error << std::endl; return EXIT_FAILURE; }
std::cout << identifier << std::endl;
}
```
@@ -1039,40 +1047,40 @@ bool parse() {
// Iterating through an array of objects
auto error = parser.iterate(cars_json).get(doc);
if(error) { std::cerr << error << std::endl; return false; }
if (error) { std::cerr << error << std::endl; return false; }
ondemand::array cars; // invalid until the get() succeeds
error = doc.get_array().get(cars);
for (auto car_value : cars) {
ondemand::object car; // invalid until the get() succeeds
error = car_value.get_object().get(car);
if(error) { std::cerr << error << std::endl; return false; }
if (error) { std::cerr << error << std::endl; return false; }
// Accessing a field by name
std::string_view make;
std::string_view model;
error = car["make"].get(make);
if(error) { std::cerr << error << std::endl; return false; }
if (error) { std::cerr << error << std::endl; return false; }
error = car["model"].get(model);
if(error) { std::cerr << error << std::endl; return false; }
if (error) { std::cerr << error << std::endl; return false; }
cout << "Make/Model: " << make << "/" << model << endl;
// Casting a JSON element to an integer
uint64_t year{};
error = car["year"].get(year);
if(error) { std::cerr << error << std::endl; return false; }
if (error) { std::cerr << error << std::endl; return false; }
cout << "- This car is " << 2020 - year << " years old." << endl;
// Iterating through an array of floats
double total_tire_pressure = 0;
ondemand::array pressures;
error = car["tire_pressure"].get_array().get(pressures);
if(error) { std::cerr << error << std::endl; return false; }
if (error) { std::cerr << error << std::endl; return false; }
for (auto tire_pressure_value : pressures) {
double tire_pressure;
error = tire_pressure_value.get_double().get(tire_pressure);
if(error) { std::cerr << error << std::endl; return false; }
if (error) { std::cerr << error << std::endl; return false; }
total_tire_pressure += tire_pressure;
}
cout << "- Average tire pressure: " << (total_tire_pressure / 4) << endl;
@@ -1088,7 +1096,7 @@ after you have initialized them and checked that there is no error:
ondemand::object car; // invalid until the get() succeeds
// the `car` instance should not use used before it is initialized
error = car_value.get_object().get(car);
if(error) {
if (error) {
// the `car` instance should not use used
} else {
// the `car` instance can be safely used
@@ -1102,20 +1110,20 @@ having to handle exceptions.
ondemand::parser parser;
ondemand::document doc;
auto error = parser.iterate(json).get(doc);
if(error) { return false; }
if (error) { return false; }
ondemand::object object; // invalid until the get() succeeds
error = doc.get_object().get(object);
if(error) { return false; }
if (error) { return false; }
for(auto field : object) {
// We could replace 'field.key() with field.unescaped_key(),
// and ondemand::raw_json_string by std::string_view.
ondemand::raw_json_string keyv;
error = field.key().get(keyv);
if(error) { return false; }
if(keyv == "key") {
if (error) { return false; }
if (keyv == "key") {
uint64_t intvalue;
error = field.value().get(intvalue);
if(error) { return false; }
if (error) { return false; }
std::cout << intvalue;
}
}
@@ -1294,7 +1302,7 @@ content.
for (uint64_t values : array) {
std::cout << values << std::endl;
}
if(!doc.at_end()) {
if (!doc.at_end()) {
// In this instance, we will be left pointing at 'foo' since we have consumed the array [1,2].
std::cerr << "trailing content at byte index " << doc.current_location() - json.data() << std::endl;
}
@@ -1324,7 +1332,7 @@ before printout the data.
auto doc = parser.iterate(cars_json);
for (simdjson_unused ondemand::object car : doc) {
if(car["make"] == "Toyota") { count++; }
if (car["make"] == "Toyota") { count++; }
}
std::cout << "We have " << count << " Toyota cars.\n";
doc.rewind(); // requires simdjson 1.0 or better
@@ -1392,18 +1400,18 @@ ondemand::parser parser;
ondemand::document_stream stream;
size_t counter{0};
auto error = parser.iterate_many(json, 50).get(stream);
if( error ) { /* handle the error */ }
if (error) { /* handle the error */ }
for (auto doc: stream) {
if(counter < 6) {
if (counter < 6) {
int64_t val;
error = doc.at_pointer("/4").get(val);
if( error ) { /* handle the error */ }
if (error) { /* handle the error */ }
std::cout << "5 = " << val << std::endl;
} else {
ondemand::value val;
error = doc.at_pointer("/4").get(val);
// error == simdjson::CAPACITY
if(error) {
if (error) {
std::cerr << error << std::endl;
// We left 293 bytes unprocessed at the tail end of the input.
std::cout << " unprocessed bytes at the end: " << stream.truncated_bytes() << std::endl;
@@ -1647,7 +1655,7 @@ JSON string to a user-provided buffer:
General Direct Access to the Raw JSON String
--------------------------------
If your value is a string, the `raw_json_string` gives you direct access to the unprocess
If your value is a string, the `raw_json_string` you with `get_raw_json_string()` gives you direct access to the unprocessed
string. The simdjson library allows you to have access to the raw underlying JSON
more generally.
@@ -1682,9 +1690,9 @@ string_view token = obj["value"].raw_json_token();
The `raw_json_token()` should be fast and free of allocation.
If you value is an array or an object, `raw_json_token()` returns effectively a single
If your value is an array or an object, `raw_json_token()` returns effectively a single
character (`[`) or (`}`) which is not very useful. For arrays and objects, we have another
method called `raw_json()` which consumes (traverse) the array or the object.
method called `raw_json()` which consumes (traverses) the array or the object.
```C++
simdjson::ondemand::parser parser;
@@ -1716,6 +1724,82 @@ obj.reset(); // revise the object
uint64_t x = obj["value"]; // gives me 123
```
You can use `raw_json()` with the values inside an array and object. When
calling `raw_json()` on an untyped value, it acts as `raw_json()` when the
value is an array or an object. Otherwise, it acts as `raw_json_token()`.
It is useful if you do not care for the type of the value and just wants a
string representation.
```C++
auto json = R"( [1,2,"fds", {"a":1}, [1,344]] )"_padded;
ondemand::parser parser;
ondemand::document doc = parser.iterate(json);
size_t counter = 0;
for(auto array: doc) {
std::string_view raw = array.raw_json();
// will capture "1", "2", "\"fds\"", "{\"a\":1}", "[1,344]"
}
```
```C++
auto json = R"( {"key1":1,"key2":2,"key3":"fds", "key4":{"a":1}, "key5":[1,344]} )"_padded;
ondemand::parser parser;
ondemand::document doc = parser.iterate(json);
size_t counter = 0;
for(auto key_value: doc.get_object()) {
std::string_view raw = key_value.value().raw_json();
// will capture "1", "2", "\"fds\"", "{\"a\":1}", "[1,344]"
}
```
Storing Directly into an Existing String Instance
-----------------------------------------------------
The simdjson library favours the use of `std::string_view` instances because
it tends to lead to better performance due to causing fewer memory allocations.
However, they are cases where you need to store a string result in an `std::string``
instance. You can do so with a templated version of the `to_string()` method which takes as
a parameter a reference to an `std::string`.
```C++
auto json = R"({
"name": "Daniel",
"age": 42
})"_padded;
ondemand::parser parser;
ondemand::document doc = parser.iterate(json);
std::string name;
doc["name"].get_string(name);
```
The same routine can be written without exceptions handling:
```C++
std::string name;
auto err = doc["name"].get_string(name);
if(err) { /* handle error */ }
```
The `std::string` instance, once created, is independent. Unlike our `std::string_view` instances,
it does not point at data that is within our `parser` instance. The same caveat applies: you should
only consume a JSON string once.
Because `get_string()` is a template that requires a type that can be assigned an `std::string`, you
can use it with features such as `std::optional`:
```C++
auto json = R"({ "foo1": "3.1416" } )"_padded;
ondemand::parser parser;
ondemand::document doc = parser.iterate(json);
std::optional<std::string> value;
if(doc["foo1"].get_string(value)) { /* error */ }
// value was populated with "3.1416"
```
You should be mindful of the trade-off: allocating multiple
`std::string` instances can become expensive.
Thread Safety
-------------
@@ -1944,6 +2028,79 @@ bool example() {
}
```
* Example 3: CRT
```C++
bool example() {
padded_string padded_input_json = R"([
{ "monitor": [
{ "id": "monitor", "type": "toggle", "label": "monitor" },
{ "id": "profile", "type": "selector", "label": "collection" },
{ "id": "overlay", "type": "selector", "label": "overlay" },
{ "id": "zoom", "type": "toggleSlider", "label": "zoom" }
] },
{ "crt": [
{ "id": "system", "type": "multi", "label": "system", "choices": "PAL, NTSC" },
{ "type": "spacer" },
{ "id": "brightness", "type": "slider", "icon": "brightness" },
{ "id": "contrast", "type": "slider", "icon": "contrast" },
{ "id": "saturation", "type": "slider", "icon": "saturation" },
{ "type": "spacer" },
{ "id": "overscan", "type": "toggleSlider", "label": "overscan" },
{ "type": "spacer" },
{ "id": "emulation", "type": "toggle", "label": "CRT emulation" },
{ "type": "spacer" },
{ "id": "curve", "type": "toggleSlider", "label": "curve" },
{ "id": "bleed", "type": "toggleSlider", "label": "bleed" },
{ "id": "vignette", "type": "toggleSlider", "label": "vignette" },
{ "id": "scanlines", "type": "toggleSlider", "label": "scanlines" },
{ "id": "gridlines", "type": "toggleSlider", "label": "gridlines" },
{ "id": "glow", "type": "toggleSlider", "label": "glow" },
{ "id": "flicker", "type": "toggleSlider", "label": "flicker" },
{ "id": "noise", "type": "toggleSlider", "label": "noise" },
{}
] }
])"_padded;
auto parser = ondemand::parser{};
auto doc = parser.iterate(padded_input_json);
auto root_array = doc.get_array();
// the root should be an object, not an array, but that's the JSON we are
// given.
for (ondemand::object node : root_array) {
// We know that we are going to have just one element in the object.
for (auto field : node) {
std::cout << "\n\ntop level:" << field.key() << std::endl;
// You can get a proper std::string_view for the key with:
// std::string_view key = field.unescaped_key();
// and second for-range loop to get child-elements here
for (ondemand::object inner_object : field.value()) {
auto i = inner_object.begin();
if (i == inner_object.end()) {
std::cout << "empty object" << std::endl;
continue;
} else {
for (; i != inner_object.end(); ++i) {
auto inner_field = *i;
std::cout << '"' << inner_field.key()
<< "\" : " << inner_field.value() << ", ";
// You can get proper std::string_view for the key and value with:
// std::string_view inner_key = field.unescaped_key();
// std::string_view value_str = field.value();
}
}
std::cout << std::endl;
}
// You can break here if you only want just the first element.
// break;
}
}
return true;
}
```
Performance Tips
--------
@@ -1969,4 +2126,4 @@ Performance Tips
std::string_view year = data["year"];
std::string_view rating = data["rating"];
```
- To better understand the operation of your On Demand parser, and whether it is performing as well as you think it should be, there is a logger feature built in to simdjson! To use it, define the pre-processor directive `SIMDJSON_VERBOSE_LOGGING` prior to including the `simdjson.h` header, which enables logging in simdjson. Run your code. It may generate a lot of logging output; adding printouts from your application that show each section may be helpful. The log's output will show step-by-step information on state, buffer pointer position, depth, and key retrieval status. Importantly, unless `SIMDJSON_VERBOSE_LOGGING` is defined, logging is entirely disabled and thus carries no overhead.
- To better understand the operation of your On Demand parser, and whether it is performing as well as you think it should be, there is a logger feature built in to simdjson! To use it, define the pre-processor directive `SIMDJSON_VERBOSE_LOGGING` prior to including the `simdjson.h` header, which enables logging in simdjson. Run your code. It may generate a lot of logging output; adding printouts from your application that show each section may be helpful. The log's output will show step-by-step information on state, buffer pointer position, depth, and key retrieval status. Importantly, unless `SIMDJSON_VERBOSE_LOGGING` is defined, logging is entirely disabled and thus carries no overhead.
+2 -2
View File
@@ -329,10 +329,10 @@ int main(void) {
simdjson::dom::parser parser;
simdjson::dom::element tweets; // invalid until the get() succeeds
auto error = parser.load("twitter.json").get(tweets);
if(error) { std::cerr << error << std::endl; return EXIT_FAILURE; }
if (error) { std::cerr << error << std::endl; return EXIT_FAILURE; }
uint64_t identifier;
error = tweets["statuses"].at(0)["id"].get(identifier);
if(error) { std::cerr << error << std::endl; return EXIT_FAILURE; }
if (error) { std::cerr << error << std::endl; return EXIT_FAILURE; }
std::cout << identifier << std::endl;
return EXIT_SUCCESS;
}
+3 -3
View File
@@ -101,8 +101,8 @@ by comparing it with the null pointer.
```c++
auto my_implementation = simdjson::get_available_implementations()["haswell"];
if(! my_implementation) { exit(1); }
if(! my_implementation->supported_by_runtime_system()) { exit(1); }
if (! my_implementation) { exit(1); }
if (! my_implementation->supported_by_runtime_system()) { exit(1); }
simdjson::get_active_implementation() = my_implementation;
```
@@ -113,7 +113,7 @@ You should call `supported_by_runtime_system()` to compare the processor's featu
```c++
for (auto implementation : simdjson::get_available_implementations()) {
if(implementation->supported_by_runtime_system()) {
if (implementation->supported_by_runtime_system()) {
cout << implementation->name() << ": " << implementation->description() << endl;
}
}
+7 -4
View File
@@ -17,6 +17,9 @@ Contents
- [Motivations](#motivations)
- [How it works](#how-it-works)
- [Context](#context)
- [Design](#design)
- [Threads](#threads)
- [Support](#support)
- [API](#api)
- [Use cases](#use-cases)
@@ -193,12 +196,12 @@ Let us illustrate the idea with code:
simdjson::ondemand::parser parser;
simdjson::ondemand::document_stream stream;
auto error = parser.iterate_many(json).get(stream);
if( error ) { /* do something */ }
if (error) { /* do something */ }
auto i = stream.begin();
size_t count{0};
for(; i != stream.end(); ++i) {
auto doc = *i;
if(!i.error()) {
if (!i.error()) {
std::cout << "got full document at " << i.current_index() << std::endl;
std::cout << i.source() << std::endl;
count++;
@@ -234,7 +237,7 @@ Consider the following example where a truncated document (`{"key":"intentionall
simdjson::ondemand::parser parser;
simdjson::ondemand::document_stream stream;
auto error = parser.iterate_many(json,json.size()).get(stream);
if(error) { std::cerr << error << std::endl; return; }
if (error) { std::cerr << error << std::endl; return; }
for(auto i = stream.begin(); i != stream.end(); ++i) {
std::cout << i.source() << std::endl;
}
@@ -266,7 +269,7 @@ Example:
// we pass 'true' to the allow_comma parameter, the batch size will be set to at least
// the document size.
auto error = parser.iterate_many(json, 32, true).get(doc_stream);
if(error) { std::cerr << error << std::endl; return; }
if (error) { std::cerr << error << std::endl; return; }
for (auto doc : doc_stream) {
std::cout << doc.type() << std::endl;
}
+4 -4
View File
@@ -679,11 +679,11 @@ in production systems:
ondemand::object c1 = parent["child1"];
// c1 owns the focus
//
if(std::string_view(c1["name"]) != "John") { ... }
if (std::string_view(c1["name"]) != "John") { ... }
// c2 attempts to grab the focus from parent but fails
ondemand::object c2 = parent["child2"];
// c2 is now in an unsafe state and the following line would be unsafe
// if(std::string_view(c2["name"]) != "Daniel") { return false; }
// if (std::string_view(c2["name"]) != "Daniel") { return false; }
```
A correct usage is given by the following example:
@@ -697,7 +697,7 @@ in production systems:
{
ondemand::object c1 = parent["child1"];
// c1 grabbed the focus from parent
if(std::string_view(c1["name"]) != "John") { return false; }
if (std::string_view(c1["name"]) != "John") { return false; }
}
// c1 went out of scope, so its destructor was called and the focus
// was handed back to parent.
@@ -705,7 +705,7 @@ in production systems:
ondemand::object c2 = parent["child2"];
// c2 grabbed the focus from parent
// the following is safe:
if(std::string_view(c2["name"]) != "Daniel") { return false; }
if (std::string_view(c2["name"]) != "Daniel") { return false; }
}
```
+3 -3
View File
@@ -184,12 +184,12 @@ Let us illustrate the idea with code:
simdjson::dom::parser parser;
simdjson::dom::document_stream stream;
auto error = parser.parse_many(json).get(stream);
if( error ) { /* do something */ }
if (error) { /* do something */ }
auto i = stream.begin();
size_t count{0};
for(; i != stream.end(); ++i) {
auto doc = *i;
if(!doc.error()) {
if (!doc.error()) {
std::cout << "got full document at " << i.current_index() << std::endl;
std::cout << i.source() << std::endl;
count++;
@@ -225,7 +225,7 @@ Consider the following example where a truncated document (`{"key":"intentionall
simdjson::dom::parser parser;
simdjson::dom::document_stream stream;
auto error = parser.parse_many(json,json.size()).get(stream);
if(error) { std::cerr << error << std::endl; return; }
if (error) { std::cerr << error << std::endl; return; }
for(auto doc : stream) {
std::cout << doc << std::endl;
}
-10
View File
@@ -35,14 +35,4 @@ IF(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
add_quickstart_test(quickstart_ondemand_noexceptions quickstart_ondemand_noexceptions.cpp NO_EXCEPTIONS LABELS quickstart_ondemand acceptance)
add_quickstart_test(quickstart_ondemand_noexceptions11 quickstart_ondemand_noexceptions.cpp NO_EXCEPTIONS CXX_STANDARD c++11 LABELS quickstart_ondemand)
# SingleStage Quick Start
if (SIMDJSON_EXCEPTIONS)
add_quickstart_test(quickstart_singlestage quickstart_singlestage.cpp LABELS quickstart_singlestage acceptance)
add_quickstart_test(quickstart_singlestage11 quickstart_singlestage.cpp CXX_STANDARD c++11 LABELS quickstart_singlestage acceptance)
add_quickstart_test(quickstart_singlestage14 quickstart_singlestage.cpp CXX_STANDARD c++14 LABELS quickstart_singlestage)
endif()
add_quickstart_test(quickstart_singlestage_noexceptions quickstart_singlestage_noexceptions.cpp NO_EXCEPTIONS LABELS quickstart_singlestage acceptance)
add_quickstart_test(quickstart_singlestage_noexceptions11 quickstart_singlestage_noexceptions.cpp NO_EXCEPTIONS CXX_STANDARD c++11 LABELS quickstart_singlestage)
endif()
@@ -1,9 +0,0 @@
#include <iostream>
#include "simdjson.h"
using namespace simdjson;
int main(void) {
ondemand::parser parser;
padded_string json = padded_string::load("twitter.json");
ondemand::document tweets = parser.iterate(json);
std::cout << uint64_t(tweets["search_metadata"]["count"]) << " results." << std::endl;
}
@@ -1,21 +0,0 @@
#include <iostream>
#include "simdjson.h"
using namespace simdjson;
int main(void) {
padded_string json;
auto error = padded_string::load("twitter.json").get(json);
if (error) { std::cerr << error << std::endl; return EXIT_FAILURE; }
ondemand::parser parser;
ondemand::document tweets;
error = parser.iterate(json).get(tweets);
if (error) { std::cerr << error << std::endl; return EXIT_FAILURE; }
uint64_t count;
error = tweets["search_metadata"]["count"].get(count);
if (error) { std::cerr << error << std::endl; return EXIT_FAILURE; }
std::cout << count << " results." << std::endl;
return EXIT_SUCCESS;
}
-1
View File
@@ -63,7 +63,6 @@ if(SIMDJSON_ENABLE_FUZZING)
implement_fuzzer(fuzz_minifyimpl) # minify *without* parsing, plus compare implementations
implement_fuzzer(fuzz_ndjson) # the ndjson api
implement_fuzzer(fuzz_ondemand)
# implement_fuzzer(fuzz_singlestage) # TODO why no worky
implement_fuzzer(fuzz_padded)
implement_fuzzer(fuzz_parser)
implement_fuzzer(fuzz_print_json)
-74
View File
@@ -1,74 +0,0 @@
#include "FuzzUtils.h"
#include "simdjson.h"
#include <cstddef>
#include <cstdint>
#include <string>
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
FuzzData fd(Data, Size);
const int action = fd.getInt<0, 12>();
// split the remainder of the document into strings
auto strings = fd.splitIntoStrings();
while (strings.size() < 1) {
strings.emplace_back();
}
#if SIMDJSON_EXCEPTIONS
try {
#endif
simdjson::singlestage::parser parser;
simdjson::padded_string padded(strings[0]);
auto doc = parser.iterate(padded);
if (doc.error()) {
return 0;
}
for (auto item : doc) {
switch (action) {
case 0: {
simdjson_unused auto x = item.get_string();
} break;
case 1: {
simdjson_unused auto x = item.get_bool();
} break;
case 2: {
simdjson_unused auto x = item.get_array();
} break;
case 3: {
simdjson_unused auto x = item.get_int64();
} break;
case 4: {
simdjson_unused auto x = item.get_double();
} break;
case 5: {
simdjson_unused auto x = item.get_object();
} break;
case 6: {
simdjson_unused auto x = item.get_uint64();
} break;
case 7: {
simdjson_unused auto x = item.get_raw_json_string();
} break;
case 8: {
simdjson_unused auto x = item.is_null();
} break;
case 9: {
simdjson_unused auto x = item.begin();
} break;
case 10: {
simdjson_unused auto x = item.end();
} break;
case 11: {
for (auto e : item) {
simdjson_unused auto x = e.is_null();
}
} break;
default:;
}
}
#if SIMDJSON_EXCEPTIONS
} catch (...) {
}
#endif
return 0;
}
-1
View File
@@ -53,6 +53,5 @@
#include "simdjson/dom.h"
#include "simdjson/ondemand.h"
#include "simdjson/singlestage.h"
#endif // SIMDJSON_H
+2 -9
View File
@@ -1,9 +1,9 @@
#ifndef SIMDJSON_ARM64_BASE_H
#define SIMDJSON_ARM64_BASE_H
#ifndef SIMDJSON_AMALGAMATED
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
#include "simdjson/base.h"
#endif // SIMDJSON_AMALGAMATED
#endif // SIMDJSON_CONDITIONAL_INCLUDE
namespace simdjson {
/**
@@ -23,11 +23,4 @@ template <typename T> struct simd8x64;
} // namespace arm64
} // namespace simdjson
#ifndef SIMDJSON_AMALGAMATED
// If we're editing one of the files in this directory, begin the implementation!
#ifndef SIMDJSON_IMPLEMENTATION
#include "simdjson/arm64/begin.h"
#endif
#endif // SIMDJSON_AMALGAMATED
#endif // SIMDJSON_ARM64_BASE_H
+2
View File
@@ -6,3 +6,5 @@
#include "simdjson/arm64/numberparsing_defs.h"
#include "simdjson/arm64/simd.h"
#include "simdjson/arm64/stringparsing_defs.h"
#define SIMDJSON_SKIP_BACKSLASH_SHORT_CIRCUIT 1
+4 -2
View File
@@ -1,11 +1,13 @@
#ifndef SIMDJSON_ARM64_BITMANIPULATION_H
#define SIMDJSON_ARM64_BITMANIPULATION_H
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
#include "simdjson/arm64/base.h"
#include "simdjson/arm64/intrinsics.h"
#endif // SIMDJSON_CONDITIONAL_INCLUDE
namespace simdjson {
namespace SIMDJSON_IMPLEMENTATION {
namespace arm64 {
namespace {
// We sometimes call trailing_zero on inputs that are zero,
@@ -98,7 +100,7 @@ simdjson_inline bool add_overflow(uint64_t value1, uint64_t value2, uint64_t *re
}
} // unnamed namespace
} // namespace SIMDJSON_IMPLEMENTATION
} // namespace arm64
} // namespace simdjson
#endif // SIMDJSON_ARM64_BITMANIPULATION_H
+3 -1
View File
@@ -1,10 +1,12 @@
#ifndef SIMDJSON_ARM64_BITMASK_H
#define SIMDJSON_ARM64_BITMASK_H
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
#include "simdjson/arm64/base.h"
#endif // SIMDJSON_CONDITIONAL_INCLUDE
namespace simdjson {
namespace SIMDJSON_IMPLEMENTATION {
namespace arm64 {
namespace {
//
+5
View File
@@ -1 +1,6 @@
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
#include "simdjson/arm64/base.h"
#endif // SIMDJSON_CONDITIONAL_INCLUDE
#undef SIMDJSON_SKIP_BACKSLASH_SHORT_CIRCUIT
#undef SIMDJSON_IMPLEMENTATION
+3 -2
View File
@@ -1,10 +1,11 @@
#ifndef SIMDJSON_ARM64_IMPLEMENTATION_H
#define SIMDJSON_ARM64_IMPLEMENTATION_H
#ifndef SIMDJSON_AMALGAMATED
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
#include "simdjson/base.h"
#include "simdjson/implementation.h"
#include "simdjson/internal/instruction_set.h"
#endif // SIMDJSON_AMALGAMATED
#endif // SIMDJSON_CONDITIONAL_INCLUDE
namespace simdjson {
namespace arm64 {
+4 -2
View File
@@ -1,12 +1,14 @@
#ifndef SIMDJSON_ARM64_INTRINSICS_H
#define SIMDJSON_ARM64_INTRINSICS_H
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
#include "simdjson/arm64/base.h"
#endif // SIMDJSON_CONDITIONAL_INCLUDE
// This should be the correct header whether
// you use visual studio or other compilers.
#include <arm_neon.h>
#include "simdjson/arm64/base.h"
static_assert(sizeof(uint8x16_t) <= simdjson::SIMDJSON_PADDING, "insufficient padding for arm64");
#endif // SIMDJSON_ARM64_INTRINSICS_H
+7 -8
View File
@@ -1,22 +1,21 @@
#ifndef SIMDJSON_ARM64_NUMBERPARSING_DEFS_H
#define SIMDJSON_ARM64_NUMBERPARSING_DEFS_H
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
#include "simdjson/arm64/base.h"
#include "simdjson/arm64/intrinsics.h"
#include "simdjson/internal/numberparsing_tables.h"
#endif // SIMDJSON_CONDITIONAL_INCLUDE
#include <cstring>
#if _M_ARM64
// __umulh requires intrin.h
#include <intrin.h>
#endif // _M_ARM64
#include <cstring>
#ifndef SIMDJSON_AMALGAMATED
#include "simdjson/internal/numberparsing_tables.h"
#endif // SIMDJSON_AMALGAMATED
namespace simdjson {
namespace SIMDJSON_IMPLEMENTATION {
namespace arm64 {
namespace numberparsing {
// we don't have SSE, so let us use a scalar function
@@ -49,7 +48,7 @@ simdjson_inline internal::value128 full_multiplication(uint64_t value1, uint64_t
}
} // namespace numberparsing
} // namespace SIMDJSON_IMPLEMENTATION
} // namespace arm64
} // namespace simdjson
#define SIMDJSON_SWAR_NUMBER_PARSING 1
+56 -93
View File
@@ -1,15 +1,14 @@
#ifndef SIMDJSON_ARM64_SIMD_H
#define SIMDJSON_ARM64_SIMD_H
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
#include "simdjson/arm64/base.h"
#include "simdjson/arm64/bitmanipulation.h"
#ifndef SIMDJSON_AMALGAMATED
#include "simdjson/internal/simdprune_tables.h"
#endif // SIMDJSON_AMALGAMATED
#endif // SIMDJSON_CONDITIONAL_INCLUDE
namespace simdjson {
namespace SIMDJSON_IMPLEMENTATION {
namespace arm64 {
namespace {
namespace simd {
@@ -18,89 +17,53 @@ namespace {
// Start of private section with Visual Studio workaround
/**
* make_uint8x16_t initializes a SIMD register (uint8x16_t).
* This is needed because, incredibly, the syntax uint8x16_t x = {1,2,3...}
* is not recognized under Visual Studio! This is a workaround.
* Using a std::initializer_list<uint8_t> as a parameter resulted in
* inefficient code. With the current approach, if the parameters are
* compile-time constants,
* GNU GCC compiles it to ldr, the same as uint8x16_t x = {1,2,3...}.
* You should not use this function except for compile-time constants:
* it is not efficient.
*/
simdjson_inline uint8x16_t make_uint8x16_t(uint8_t x1, uint8_t x2, uint8_t x3, uint8_t x4,
uint8_t x5, uint8_t x6, uint8_t x7, uint8_t x8,
uint8_t x9, uint8_t x10, uint8_t x11, uint8_t x12,
uint8_t x13, uint8_t x14, uint8_t x15, uint8_t x16) {
// Doing a load like so end ups generating worse code.
// uint8_t array[16] = {x1, x2, x3, x4, x5, x6, x7, x8,
// x9, x10,x11,x12,x13,x14,x15,x16};
// return vld1q_u8(array);
uint8x16_t x{};
// incredibly, Visual Studio does not allow x[0] = x1
x = vsetq_lane_u8(x1, x, 0);
x = vsetq_lane_u8(x2, x, 1);
x = vsetq_lane_u8(x3, x, 2);
x = vsetq_lane_u8(x4, x, 3);
x = vsetq_lane_u8(x5, x, 4);
x = vsetq_lane_u8(x6, x, 5);
x = vsetq_lane_u8(x7, x, 6);
x = vsetq_lane_u8(x8, x, 7);
x = vsetq_lane_u8(x9, x, 8);
x = vsetq_lane_u8(x10, x, 9);
x = vsetq_lane_u8(x11, x, 10);
x = vsetq_lane_u8(x12, x, 11);
x = vsetq_lane_u8(x13, x, 12);
x = vsetq_lane_u8(x14, x, 13);
x = vsetq_lane_u8(x15, x, 14);
x = vsetq_lane_u8(x16, x, 15);
return x;
}
#ifndef simdjson_make_uint8x16_t
#define simdjson_make_uint8x16_t(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, \
x13, x14, x15, x16) \
([=]() { \
uint8_t array[16] = {x1, x2, x3, x4, x5, x6, x7, x8, \
x9, x10, x11, x12, x13, x14, x15, x16}; \
return vld1q_u8(array); \
}())
#endif
#ifndef simdjson_make_int8x16_t
#define simdjson_make_int8x16_t(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, \
x13, x14, x15, x16) \
([=]() { \
int8_t array[16] = {x1, x2, x3, x4, x5, x6, x7, x8, \
x9, x10, x11, x12, x13, x14, x15, x16}; \
return vld1q_s8(array); \
}())
#endif
simdjson_inline uint8x8_t make_uint8x8_t(uint8_t x1, uint8_t x2, uint8_t x3, uint8_t x4,
uint8_t x5, uint8_t x6, uint8_t x7, uint8_t x8) {
uint8x8_t x{};
x = vset_lane_u8(x1, x, 0);
x = vset_lane_u8(x2, x, 1);
x = vset_lane_u8(x3, x, 2);
x = vset_lane_u8(x4, x, 3);
x = vset_lane_u8(x5, x, 4);
x = vset_lane_u8(x6, x, 5);
x = vset_lane_u8(x7, x, 6);
x = vset_lane_u8(x8, x, 7);
return x;
}
// We have to do the same work for make_int8x16_t
simdjson_inline int8x16_t make_int8x16_t(int8_t x1, int8_t x2, int8_t x3, int8_t x4,
int8_t x5, int8_t x6, int8_t x7, int8_t x8,
int8_t x9, int8_t x10, int8_t x11, int8_t x12,
int8_t x13, int8_t x14, int8_t x15, int8_t x16) {
// Doing a load like so end ups generating worse code.
// int8_t array[16] = {x1, x2, x3, x4, x5, x6, x7, x8,
// x9, x10,x11,x12,x13,x14,x15,x16};
// return vld1q_s8(array);
int8x16_t x{};
// incredibly, Visual Studio does not allow x[0] = x1
x = vsetq_lane_s8(x1, x, 0);
x = vsetq_lane_s8(x2, x, 1);
x = vsetq_lane_s8(x3, x, 2);
x = vsetq_lane_s8(x4, x, 3);
x = vsetq_lane_s8(x5, x, 4);
x = vsetq_lane_s8(x6, x, 5);
x = vsetq_lane_s8(x7, x, 6);
x = vsetq_lane_s8(x8, x, 7);
x = vsetq_lane_s8(x9, x, 8);
x = vsetq_lane_s8(x10, x, 9);
x = vsetq_lane_s8(x11, x, 10);
x = vsetq_lane_s8(x12, x, 11);
x = vsetq_lane_s8(x13, x, 12);
x = vsetq_lane_s8(x14, x, 13);
x = vsetq_lane_s8(x15, x, 14);
x = vsetq_lane_s8(x16, x, 15);
return x;
}
#ifndef simdjson_make_uint8x8_t
#define simdjson_make_uint8x8_t(x1, x2, x3, x4, x5, x6, x7, x8) \
([=]() { \
uint8_t array[8] = {x1, x2, x3, x4, x5, x6, x7, x8}; \
return vld1_u8(array); \
}())
#endif
#ifndef simdjson_make_int8x8_t
#define simdjson_make_int8x8_t(x1, x2, x3, x4, x5, x6, x7, x8) \
([=]() { \
int8_t array[8] = {x1, x2, x3, x4, x5, x6, x7, x8}; \
return vld1_s8(array); \
}())
#endif
#ifndef simdjson_make_uint16x8_t
#define simdjson_make_uint16x8_t(x1, x2, x3, x4, x5, x6, x7, x8) \
([=]() { \
uint16_t array[8] = {x1, x2, x3, x4, x5, x6, x7, x8}; \
return vld1q_u16(array); \
}())
#endif
#ifndef simdjson_make_int16x8_t
#define simdjson_make_int16x8_t(x1, x2, x3, x4, x5, x6, x7, x8) \
([=]() { \
int16_t array[8] = {x1, x2, x3, x4, x5, x6, x7, x8}; \
return vld1q_s16(array); \
}())
#endif
// End of private section with Visual Studio workaround
} // namespace
@@ -159,7 +122,7 @@ simdjson_inline int8x16_t make_int8x16_t(int8_t x1, int8_t x2, int8_t x3, int
// purposes (cutting it down to uint16_t costs performance in some compilers).
simdjson_inline uint32_t to_bitmask() const {
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
const uint8x16_t bit_mask = make_uint8x16_t(0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80,
const uint8x16_t bit_mask = simdjson_make_uint8x16_t(0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80,
0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80);
#else
const uint8x16_t bit_mask = {0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80,
@@ -193,7 +156,7 @@ simdjson_inline int8x16_t make_int8x16_t(int8_t x1, int8_t x2, int8_t x3, int
simdjson_inline simd8(
uint8_t v0, uint8_t v1, uint8_t v2, uint8_t v3, uint8_t v4, uint8_t v5, uint8_t v6, uint8_t v7,
uint8_t v8, uint8_t v9, uint8_t v10, uint8_t v11, uint8_t v12, uint8_t v13, uint8_t v14, uint8_t v15
) : simd8(make_uint8x16_t(
) : simd8(simdjson_make_uint8x16_t(
v0, v1, v2, v3, v4, v5, v6, v7,
v8, v9, v10,v11,v12,v13,v14,v15
)) {}
@@ -284,7 +247,7 @@ simdjson_inline int8x16_t make_int8x16_t(int8_t x1, int8_t x2, int8_t x3, int
uint8x16_t shufmask = vreinterpretq_u8_u64(shufmask64);
// we increment by 0x08 the second half of the mask
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
uint8x16_t inc = make_uint8x16_t(0, 0, 0, 0, 0, 0, 0, 0, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08);
uint8x16_t inc = simdjson_make_uint8x16_t(0, 0, 0, 0, 0, 0, 0, 0, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08);
#else
uint8x16_t inc = {0, 0, 0, 0, 0, 0, 0, 0, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08};
#endif
@@ -314,7 +277,7 @@ simdjson_inline int8x16_t make_int8x16_t(int8_t x1, int8_t x2, int8_t x3, int
uint8x8_t compactmask2 = vcreate_u8(thintable_epi8[mask2]);
// we increment by 0x08 the second half of the mask
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
uint8x8_t inc = make_uint8x8_t(0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08);
uint8x8_t inc = simdjson_make_uint8x8_t(0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08);
#else
uint8x8_t inc = {0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08};
#endif
@@ -369,7 +332,7 @@ simdjson_inline int8x16_t make_int8x16_t(int8_t x1, int8_t x2, int8_t x3, int
simdjson_inline simd8(
int8_t v0, int8_t v1, int8_t v2, int8_t v3, int8_t v4, int8_t v5, int8_t v6, int8_t v7,
int8_t v8, int8_t v9, int8_t v10, int8_t v11, int8_t v12, int8_t v13, int8_t v14, int8_t v15
) : simd8(make_int8x16_t(
) : simd8(simdjson_make_int8x16_t(
v0, v1, v2, v3, v4, v5, v6, v7,
v8, v9, v10,v11,v12,v13,v14,v15
)) {}
@@ -487,7 +450,7 @@ simdjson_inline int8x16_t make_int8x16_t(int8_t x1, int8_t x2, int8_t x3, int
simdjson_inline uint64_t to_bitmask() const {
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
const uint8x16_t bit_mask = make_uint8x16_t(
const uint8x16_t bit_mask = simdjson_make_uint8x16_t(
0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80,
0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80
);
@@ -528,7 +491,7 @@ simdjson_inline int8x16_t make_int8x16_t(int8_t x1, int8_t x2, int8_t x3, int
} // namespace simd
} // unnamed namespace
} // namespace SIMDJSON_IMPLEMENTATION
} // namespace arm64
} // namespace simdjson
#endif // SIMDJSON_ARM64_SIMD_H
-8
View File
@@ -1,8 +0,0 @@
#ifndef SIMDJSON_ARM64_SINGLESTAGE_H
#define SIMDJSON_ARM64_SINGLESTAGE_H
#include "simdjson/arm64/begin.h"
#include "simdjson/generic/singlestage/amalgamated.h"
#include "simdjson/arm64/end.h"
#endif // SIMDJSON_ARM64_SINGLESTAGE_H
+4 -2
View File
@@ -1,12 +1,14 @@
#ifndef SIMDJSON_ARM64_STRINGPARSING_DEFS_H
#define SIMDJSON_ARM64_STRINGPARSING_DEFS_H
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
#include "simdjson/arm64/base.h"
#include "simdjson/arm64/simd.h"
#include "simdjson/arm64/bitmanipulation.h"
#endif // SIMDJSON_CONDITIONAL_INCLUDE
namespace simdjson {
namespace SIMDJSON_IMPLEMENTATION {
namespace arm64 {
namespace {
using namespace simd;
@@ -45,7 +47,7 @@ simdjson_inline backslash_and_quote backslash_and_quote::copy_and_find(const uin
}
} // unnamed namespace
} // namespace SIMDJSON_IMPLEMENTATION
} // namespace arm64
} // namespace simdjson
#endif // SIMDJSON_ARM64_STRINGPARSING_DEFS_H
+2 -2
View File
@@ -6,7 +6,7 @@
#include "simdjson/generic/dependencies.h"
#define SIMDJSON_AMALGAMATED
#define SIMDJSON_CONDITIONAL_INCLUDE
#if SIMDJSON_BUILTIN_IMPLEMENTATION_IS(arm64)
#include "simdjson/arm64.h"
@@ -24,6 +24,6 @@
#error Unknown SIMDJSON_BUILTIN_IMPLEMENTATION
#endif
#undef SIMDJSON_AMALGAMATED
#undef SIMDJSON_CONDITIONAL_INCLUDE
#endif // SIMDJSON_BUILTIN_H
+2 -2
View File
@@ -5,7 +5,7 @@
#include "simdjson/generic/dependencies.h"
#define SIMDJSON_AMALGAMATED
#define SIMDJSON_CONDITIONAL_INCLUDE
#if SIMDJSON_BUILTIN_IMPLEMENTATION_IS(arm64)
#include "simdjson/arm64/implementation.h"
@@ -23,7 +23,7 @@
#error Unknown SIMDJSON_BUILTIN_IMPLEMENTATION
#endif
#undef SIMDJSON_AMALGAMATED
#undef SIMDJSON_CONDITIONAL_INCLUDE
namespace simdjson {
/**
+2 -2
View File
@@ -6,7 +6,7 @@
#include "simdjson/generic/ondemand/dependencies.h"
#define SIMDJSON_AMALGAMATED
#define SIMDJSON_CONDITIONAL_INCLUDE
#if SIMDJSON_BUILTIN_IMPLEMENTATION_IS(arm64)
#include "simdjson/arm64/ondemand.h"
@@ -24,7 +24,7 @@
#error Unknown SIMDJSON_BUILTIN_IMPLEMENTATION
#endif
#undef SIMDJSON_AMALGAMATED
#undef SIMDJSON_CONDITIONAL_INCLUDE
namespace simdjson {
/**
-36
View File
@@ -1,36 +0,0 @@
#ifndef SIMDJSON_BUILTIN_SINGLESTAGE_H
#define SIMDJSON_BUILTIN_SINGLESTAGE_H
#include "simdjson/builtin.h"
#include "simdjson/builtin/base.h"
#include "simdjson/generic/singlestage/dependencies.h"
#define SIMDJSON_AMALGAMATED
#if SIMDJSON_BUILTIN_IMPLEMENTATION_IS(arm64)
#include "simdjson/arm64/singlestage.h"
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(fallback)
#include "simdjson/fallback/singlestage.h"
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(haswell)
#include "simdjson/haswell/singlestage.h"
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(icelake)
#include "simdjson/icelake/singlestage.h"
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(ppc64)
#include "simdjson/ppc64/singlestage.h"
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(westmere)
#include "simdjson/westmere/singlestage.h"
#else
#error Unknown SIMDJSON_BUILTIN_IMPLEMENTATION
#endif
#undef SIMDJSON_AMALGAMATED
namespace simdjson {
/**
* @copydoc simdjson::SIMDJSON_BUILTIN_IMPLEMENTATION::singlestage
*/
namespace singlestage = SIMDJSON_BUILTIN_IMPLEMENTATION::singlestage;
} // namespace simdjson
#endif // SIMDJSON_BUILTIN_SINGLESTAGE_H
+8
View File
@@ -32,4 +32,12 @@
#error simdjson requires a compiler compliant with the C++11 standard
#endif
#ifndef SIMDJSON_IF_CONSTEXPR
#if SIMDJSON_CPLUSPLUS17
#define SIMDJSON_IF_CONSTEXPR if constexpr
#else
#define SIMDJSON_IF_CONSTEXPR if
#endif
#endif
#endif // SIMDJSON_COMPILER_CHECK_H
+3 -1
View File
@@ -5,10 +5,12 @@
#include "simdjson/dom/base.h"
#include "simdjson/dom/document.h"
#include "simdjson/dom/element.h"
#include "simdjson/dom/element-inl.h"
#include "simdjson/internal/tape_ref-inl.h"
#include "simdjson/internal/jsonformatutils.h"
#include <cstring>
namespace simdjson {
namespace dom {
+1 -2
View File
@@ -224,8 +224,7 @@ private:
* Parse the next document found in the buffer previously given to document_stream.
*
* The content should be a valid JSON document encoded as UTF-8. If there is a
* UTF-8 BOM, the caller is responsible for omitting it, UTF-8 BOM are
* discouraged.
* UTF-8 BOM, the parser skips it.
*
* You do NOT need to pre-allocate a parser. This function takes care of
* pre-allocating a capacity defined by the batch_size defined when creating the
+10
View File
@@ -7,8 +7,12 @@
#include "simdjson/dom/object.h"
#include "simdjson/internal/tape_type.h"
#include "simdjson/dom/object-inl.h"
#include "simdjson/error-inl.h"
#include <ostream>
#include <limits>
namespace simdjson {
//
@@ -406,6 +410,12 @@ inline simdjson_result<element> element::at_key(std::string_view key) const noex
inline simdjson_result<element> element::at_key_case_insensitive(std::string_view key) const noexcept {
return get<object>().at_key_case_insensitive(key);
}
inline bool element::operator<(const element &other) const noexcept {
return tape.json_index < other.tape.json_index;
}
inline bool element::operator==(const element &other) const noexcept {
return tape.json_index == other.tape.json_index;
}
inline bool element::dump_raw_tape(std::ostream &out) const noexcept {
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
+21 -1
View File
@@ -211,7 +211,11 @@ public:
inline simdjson_result<T> get() const noexcept {
// Unless the simdjson library provides an inline implementation, calling this method should
// immediately fail.
static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library.");
static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. "
"The supported types are Boolean (bool), numbers (double, uint64_t, int64_t), "
"strings (std::string_view, const char *), arrays (dom::array) and objects (dom::object). "
"We recommand you use get_double(), get_bool(), get_uint64(), get_int64(), "
"get_object(), get_array() or get_string() instead of the get template.");
}
/**
@@ -451,6 +455,22 @@ public:
*/
inline simdjson_result<element> at_key_case_insensitive(std::string_view key) const noexcept;
/**
* operator< defines a total order for element allowing to use them in
* ordered C++ STL containers
*
* @return TRUE if the key appears before the other one in the tape
*/
inline bool operator<(const element &other) const noexcept;
/**
* operator== allows to verify if two element values reference the
* same JSON item
*
* @return TRUE if the two values references the same JSON element
*/
inline bool operator==(const element &other) const noexcept;
/** @private for debugging. Prints out the root element. */
inline bool dump_raw_tape(std::ostream &out) const noexcept;
+2
View File
@@ -7,6 +7,8 @@
#include "simdjson/dom/parser.h"
#include "simdjson/dom/element.h"
#include "simdjson/dom/parser-inl.h"
namespace simdjson {
//
+5
View File
@@ -5,6 +5,11 @@
#include "simdjson/dom/object.h"
#include "simdjson/dom/document.h"
#include "simdjson/dom/element-inl.h"
#include "simdjson/error-inl.h"
#include <cstring>
namespace simdjson {
//
@@ -3,10 +3,15 @@
#include "simdjson/dom/base.h"
#include "simdjson/dom/parsedjson_iterator.h"
#include "simdjson/internal/tape_ref-inl.h"
#include "simdjson/internal/jsonformatutils.h"
#include <ostream>
#include "simdjson/dom/parser-inl.h"
#include "simdjson/internal/tape_ref-inl.h"
#include <cstring>
#include <iterator>
#include <limits>
#include <ostream>
#ifndef SIMDJSON_DISABLE_DEPRECATED_API
+13 -1
View File
@@ -8,9 +8,11 @@
#include "simdjson/error-inl.h"
#include "simdjson/padded_string-inl.h"
#include "simdjson/dom/document_stream-inl.h"
#include "simdjson/dom/element-inl.h"
#include <climits>
#include <cstring> /* memcmp */
namespace simdjson {
namespace dom {
@@ -119,8 +121,14 @@ inline simdjson_result<element> parser::parse_into_document(document& provided_d
_loaded_bytes_capacity = len;
}
std::memcpy(static_cast<void *>(loaded_bytes.get()), buf, len);
buf = reinterpret_cast<const uint8_t*>(loaded_bytes.get());
}
_error = implementation->parse(realloc_if_needed ? reinterpret_cast<const uint8_t*>(loaded_bytes.get()): buf, len, provided_doc);
if((len >= 3) && (std::memcmp(buf, "\xEF\xBB\xBF", 3) == 0)) {
buf += 3;
len -= 3;
}
_error = implementation->parse(buf, len, provided_doc);
if (_error) { return _error; }
@@ -157,6 +165,10 @@ simdjson_inline simdjson_result<element> parser::parse(const padded_string_view
inline simdjson_result<document_stream> parser::parse_many(const uint8_t *buf, size_t len, size_t batch_size) noexcept {
if(batch_size < MINIMAL_BATCH_SIZE) { batch_size = MINIMAL_BATCH_SIZE; }
if((len >= 3) && (std::memcmp(buf, "\xEF\xBB\xBF", 3) == 0)) {
buf += 3;
len -= 3;
}
return document_stream(*this, buf, len, batch_size);
}
inline simdjson_result<document_stream> parser::parse_many(const char *buf, size_t len, size_t batch_size) noexcept {
+4
View File
@@ -254,6 +254,8 @@ public:
* And, possibly, no document many have been parsed when the `parser.load_many(path)` function
* returned.
*
* If there is a UTF-8 BOM, the parser skips it.
*
* ### Format
*
* The file must contain a series of one or more JSON documents, concatenated into a single
@@ -346,6 +348,8 @@ public:
* cout << std::string(doc["title"]) << endl;
* }
*
* If there is a UTF-8 BOM, the parser skips it.
*
* ### Format
*
* The buffer must contain a series of one or more JSON documents, concatenated into a single
+42 -2
View File
@@ -7,6 +7,12 @@
#include "simdjson/dom/parser.h"
#include "simdjson/internal/tape_type.h"
#include "simdjson/dom/array-inl.h"
#include "simdjson/dom/object-inl.h"
#include "simdjson/internal/tape_ref-inl.h"
#include <cstring>
namespace simdjson {
namespace dom {
inline bool parser::print_json(std::ostream &os) const noexcept {
@@ -17,12 +23,46 @@ inline bool parser::print_json(std::ostream &os) const noexcept {
os << answer;
return true;
}
inline std::ostream& operator<<(std::ostream& out, simdjson::dom::element value) {
simdjson::internal::string_builder<> sb;
sb.append(value);
return (out << sb.str());
}
#if SIMDJSON_EXCEPTIONS
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::dom::element> x) {
if (x.error()) { throw simdjson::simdjson_error(x.error()); }
return (out << x.value());
}
#endif
inline std::ostream& operator<<(std::ostream& out, simdjson::dom::array value) {
simdjson::internal::string_builder<> sb;
sb.append(value);
return (out << sb.str());
}
#if SIMDJSON_EXCEPTIONS
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::dom::array> x) {
if (x.error()) { throw simdjson::simdjson_error(x.error()); }
return (out << x.value());
}
#endif
inline std::ostream& operator<<(std::ostream& out, simdjson::dom::object value) {
simdjson::internal::string_builder<> sb;
sb.append(value);
return (out << sb.str());
}
#if SIMDJSON_EXCEPTIONS
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::dom::object> x) {
if (x.error()) { throw simdjson::simdjson_error(x.error()); }
return (out << x.value());
}
#endif
} // namespace dom
/***
* Number utility functions
**/
namespace {
/**@private
* Escape sequence like \b or \u0001
+6 -27
View File
@@ -146,16 +146,9 @@ namespace dom {
* @param value The element.
* @throw if there is an error with the underlying output stream. simdjson itself will not throw.
*/
inline std::ostream& operator<<(std::ostream& out, simdjson::dom::element value) {
simdjson::internal::string_builder<> sb;
sb.append(value);
return (out << sb.str());
}
inline std::ostream& operator<<(std::ostream& out, simdjson::dom::element value);
#if SIMDJSON_EXCEPTIONS
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::dom::element> x) {
if (x.error()) { throw simdjson::simdjson_error(x.error()); }
return (out << x.value());
}
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::dom::element> x);
#endif
/**
* Print JSON to an output stream.
@@ -164,16 +157,9 @@ inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<sim
* @param value The array.
* @throw if there is an error with the underlying output stream. simdjson itself will not throw.
*/
inline std::ostream& operator<<(std::ostream& out, simdjson::dom::array value) {
simdjson::internal::string_builder<> sb;
sb.append(value);
return (out << sb.str());
}
inline std::ostream& operator<<(std::ostream& out, simdjson::dom::array value);
#if SIMDJSON_EXCEPTIONS
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::dom::array> x) {
if (x.error()) { throw simdjson::simdjson_error(x.error()); }
return (out << x.value());
}
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::dom::array> x);
#endif
/**
* Print JSON to an output stream.
@@ -182,16 +168,9 @@ inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<sim
* @param value The object.
* @throw if there is an error with the underlying output stream. simdjson itself will not throw.
*/
inline std::ostream& operator<<(std::ostream& out, simdjson::dom::object value) {
simdjson::internal::string_builder<> sb;
sb.append(value);
return (out << sb.str());
}
inline std::ostream& operator<<(std::ostream& out, simdjson::dom::object value);
#if SIMDJSON_EXCEPTIONS
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::dom::object> x) {
if (x.error()) { throw simdjson::simdjson_error(x.error()); }
return (out << x.value());
}
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::dom::object> x);
#endif
} // namespace dom
+2 -2
View File
@@ -1,10 +1,10 @@
#ifndef SIMDJSON_ERROR_INL_H
#define SIMDJSON_ERROR_INL_H
#include <iostream>
#include "simdjson/error.h"
#include <iostream>
namespace simdjson {
namespace internal {
// We store the error code so we can validate the error message is associated with the right code
+12 -3
View File
@@ -2,7 +2,9 @@
#define SIMDJSON_ERROR_H
#include "simdjson/base.h"
#include <string>
#include <ostream>
namespace simdjson {
@@ -40,7 +42,7 @@ enum error_code {
INVALID_URI_FRAGMENT, ///< Invalid URI fragment
UNEXPECTED_ERROR, ///< indicative of a bug in simdjson
PARSER_IN_USE, ///< parser is already in use.
OUT_OF_ORDER_ITERATION, ///< tried to iterate an array or object out of order
OUT_OF_ORDER_ITERATION, ///< tried to iterate an array or object out of order (checked when SIMDJSON_DEVELOPMENT_CHECKS=1)
INSUFFICIENT_PADDING, ///< The JSON doesn't have enough padding for simdjson to safely parse it.
INCOMPLETE_ARRAY_OR_OBJECT, ///< The document ends early.
SCALAR_DOCUMENT_AS_VALUE, ///< A scalar document is treated as a value.
@@ -49,6 +51,13 @@ enum error_code {
NUM_ERROR_CODES
};
/**
* It is the convention throughout the code that the macro SIMDJSON_DEVELOPMENT_CHECKS determines whether
* we check for OUT_OF_ORDER_ITERATION. The logic behind it is that these errors only occurs when the code
* that was written while breaking some simdjson::ondemand requirement. They should not occur in released
* code after these issues were fixed.
*/
/**
* Get the error message for the given error code.
*
@@ -208,11 +217,11 @@ struct simdjson_result : public internal::simdjson_result_base<T> {
*/
simdjson_inline simdjson_result() noexcept;
/**
* @private Create a new error result.
* @private Create a new successful result.
*/
simdjson_inline simdjson_result(T &&value) noexcept;
/**
* @private Create a new successful result.
* @private Create a new error result.
*/
simdjson_inline simdjson_result(error_code error_code) noexcept;
/**
+2 -9
View File
@@ -1,9 +1,9 @@
#ifndef SIMDJSON_FALLBACK_BASE_H
#define SIMDJSON_FALLBACK_BASE_H
#ifndef SIMDJSON_AMALGAMATED
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
#include "simdjson/base.h"
#endif // SIMDJSON_AMALGAMATED
#endif // SIMDJSON_CONDITIONAL_INCLUDE
namespace simdjson {
/**
@@ -16,11 +16,4 @@ class implementation;
} // namespace fallback
} // namespace simdjson
#ifndef SIMDJSON_AMALGAMATED
// If we're editing one of the files in this directory, begin the implementation!
#ifndef SIMDJSON_IMPLEMENTATION
#include "simdjson/fallback/begin.h"
#endif
#endif // SIMDJSON_AMALGAMATED
#endif // SIMDJSON_FALLBACK_BASE_H
+4 -2
View File
@@ -1,10 +1,12 @@
#ifndef SIMDJSON_FALLBACK_BITMANIPULATION_H
#define SIMDJSON_FALLBACK_BITMANIPULATION_H
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
#include "simdjson/fallback/base.h"
#endif // SIMDJSON_CONDITIONAL_INCLUDE
namespace simdjson {
namespace SIMDJSON_IMPLEMENTATION {
namespace fallback {
namespace {
#if defined(_MSC_VER) && !defined(_M_ARM64) && !defined(_M_X64)
@@ -40,7 +42,7 @@ simdjson_inline int leading_zeroes(uint64_t input_num) {
}
} // unnamed namespace
} // namespace SIMDJSON_IMPLEMENTATION
} // namespace fallback
} // namespace simdjson
#endif // SIMDJSON_FALLBACK_BITMANIPULATION_H
+4
View File
@@ -1 +1,5 @@
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
#include "simdjson/fallback/base.h"
#endif // SIMDJSON_CONDITIONAL_INCLUDE
#undef SIMDJSON_IMPLEMENTATION
+3 -2
View File
@@ -1,9 +1,10 @@
#ifndef SIMDJSON_FALLBACK_IMPLEMENTATION_H
#define SIMDJSON_FALLBACK_IMPLEMENTATION_H
#ifndef SIMDJSON_AMALGAMATED
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
#include "simdjson/fallback/base.h"
#include "simdjson/implementation.h"
#endif // SIMDJSON_AMALGAMATED
#endif // SIMDJSON_CONDITIONAL_INCLUDE
namespace simdjson {
namespace fallback {
@@ -1,11 +1,12 @@
#ifndef SIMDJSON_FALLBACK_NUMBERPARSING_DEFS_H
#define SIMDJSON_FALLBACK_NUMBERPARSING_DEFS_H
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
#include "simdjson/fallback/base.h"
#ifndef SIMDJSON_AMALGAMATED
#include "simdjson/internal/numberparsing_tables.h"
#endif // SIMDJSON_AMALGAMATED
#endif // SIMDJSON_CONDITIONAL_INCLUDE
#include <cstring>
#ifdef JSON_TEST_NUMBERS // for unit testing
void found_invalid_number(const uint8_t *buf);
@@ -15,7 +16,7 @@ void found_float(double result, const uint8_t *buf);
#endif
namespace simdjson {
namespace SIMDJSON_IMPLEMENTATION {
namespace fallback {
namespace numberparsing {
// credit: https://johnnylee-sde.github.io/Fast-numeric-string-to-int/
@@ -71,7 +72,7 @@ simdjson_inline internal::value128 full_multiplication(uint64_t value1, uint64_t
}
} // namespace numberparsing
} // namespace SIMDJSON_IMPLEMENTATION
} // namespace fallback
} // namespace simdjson
#define SIMDJSON_SWAR_NUMBER_PARSING 1
-8
View File
@@ -1,8 +0,0 @@
#ifndef SIMDJSON_FALLBACK_SINGLESTAGE_H
#define SIMDJSON_FALLBACK_SINGLESTAGE_H
#include "simdjson/fallback/begin.h"
#include "simdjson/generic/singlestage/amalgamated.h"
#include "simdjson/fallback/end.h"
#endif // SIMDJSON_FALLBACK_SINGLESTAGE_H
@@ -1,10 +1,12 @@
#ifndef SIMDJSON_FALLBACK_STRINGPARSING_DEFS_H
#define SIMDJSON_FALLBACK_STRINGPARSING_DEFS_H
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
#include "simdjson/fallback/base.h"
#endif // SIMDJSON_CONDITIONAL_INCLUDE
namespace simdjson {
namespace SIMDJSON_IMPLEMENTATION {
namespace fallback {
namespace {
// Holds backslashes and quotes locations.
@@ -28,7 +30,7 @@ simdjson_inline backslash_and_quote backslash_and_quote::copy_and_find(const uin
}
} // unnamed namespace
} // namespace SIMDJSON_IMPLEMENTATION
} // namespace fallback
} // namespace simdjson
#endif // SIMDJSON_FALLBACK_STRINGPARSING_DEFS_H
+1 -1
View File
@@ -1,4 +1,4 @@
#if defined(SIMDJSON_AMALGAMATED) && !defined(SIMDJSON_GENERIC_DEPENDENCIES_H)
#if defined(SIMDJSON_CONDITIONAL_INCLUDE) && !defined(SIMDJSON_GENERIC_DEPENDENCIES_H)
#error simdjson/generic/dependencies.h must be included before simdjson/generic/amalgamated.h!
#endif
+4 -2
View File
@@ -1,10 +1,12 @@
#ifndef SIMDJSON_GENERIC_ATOMPARSING_H
#ifndef SIMDJSON_AMALGAMATED
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
#define SIMDJSON_GENERIC_ATOMPARSING_H
#include "simdjson/generic/base.h"
#include "simdjson/generic/jsoncharutils.h"
#endif // SIMDJSON_AMALGAMATED
#endif // SIMDJSON_CONDITIONAL_INCLUDE
#include <cstring>
namespace simdjson {
namespace SIMDJSON_IMPLEMENTATION {
+2 -2
View File
@@ -1,6 +1,6 @@
#ifndef SIMDJSON_GENERIC_BASE_H
#ifndef SIMDJSON_AMALGAMATED
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
#define SIMDJSON_GENERIC_BASE_H
#include "simdjson/base.h"
// If we haven't got an implementation yet, we're in the editor, editing a generic file! Just
@@ -23,7 +23,7 @@
#error "All possible implementations (including fallback) have been disabled! simdjson will not run."
#endif
#endif // SIMDJSON_IMPLEMENTATION
#endif // SIMDJSON_AMALGAMATED
#endif // SIMDJSON_CONDITIONAL_INCLUDE
namespace simdjson {
namespace SIMDJSON_IMPLEMENTATION {
+3 -2
View File
@@ -1,5 +1,5 @@
#ifdef SIMDJSON_AMALGAMATED
#error simdjson/generic/dependencies.h must be included before defining SIMDJSON_AMALGAMATED!
#ifdef SIMDJSON_CONDITIONAL_INCLUDE
#error simdjson/generic/dependencies.h must be included before defining SIMDJSON_CONDITIONAL_INCLUDE!
#endif
#ifndef SIMDJSON_GENERIC_DEPENDENCIES_H
@@ -10,6 +10,7 @@
// Otherwise, amalgamation will fail.
#include "simdjson/base.h"
#include "simdjson/implementation.h"
#include "simdjson/implementation_detection.h"
#include "simdjson/internal/instruction_set.h"
#include "simdjson/internal/dom_parser_implementation.h"
#include "simdjson/internal/jsoncharutils_tables.h"
@@ -1,10 +1,10 @@
#ifndef SIMDJSON_GENERIC_DOM_PARSER_IMPLEMENTATION_H
#ifndef SIMDJSON_AMALGAMATED
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
#define SIMDJSON_GENERIC_DOM_PARSER_IMPLEMENTATION_H
#include "simdjson/generic/base.h"
#include "simdjson/internal/dom_parser_implementation.h"
#endif // SIMDJSON_AMALGAMATED
#endif // SIMDJSON_CONDITIONAL_INCLUDE
namespace simdjson {
namespace SIMDJSON_IMPLEMENTATION {
@@ -1,10 +1,10 @@
#ifndef SIMDJSON_GENERIC_IMPLEMENTATION_SIMDJSON_RESULT_BASE_INL_H
#ifndef SIMDJSON_AMALGAMATED
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
#define SIMDJSON_GENERIC_IMPLEMENTATION_SIMDJSON_RESULT_BASE_INL_H
#include "simdjson/generic/base.h"
#include "simdjson/generic/implementation_simdjson_result_base.h"
#endif // SIMDJSON_AMALGAMATED
#endif // SIMDJSON_CONDITIONAL_INCLUDE
namespace simdjson {
namespace SIMDJSON_IMPLEMENTATION {
@@ -1,9 +1,9 @@
#ifndef SIMDJSON_GENERIC_IMPLEMENTATION_SIMDJSON_RESULT_BASE_H
#ifndef SIMDJSON_AMALGAMATED
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
#define SIMDJSON_GENERIC_IMPLEMENTATION_SIMDJSON_RESULT_BASE_H
#include "simdjson/generic/base.h"
#endif // SIMDJSON_AMALGAMATED
#endif // SIMDJSON_CONDITIONAL_INCLUDE
namespace simdjson {
namespace SIMDJSON_IMPLEMENTATION {
+2 -12
View File
@@ -1,11 +1,11 @@
#ifndef SIMDJSON_GENERIC_JSONCHARUTILS_H
#ifndef SIMDJSON_AMALGAMATED
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
#define SIMDJSON_GENERIC_JSONCHARUTILS_H
#include "simdjson/generic/base.h"
#include "simdjson/internal/jsoncharutils_tables.h"
#include "simdjson/internal/numberparsing_tables.h"
#endif // SIMDJSON_AMALGAMATED
#endif // SIMDJSON_CONDITIONAL_INCLUDE
namespace simdjson {
namespace SIMDJSON_IMPLEMENTATION {
@@ -96,16 +96,6 @@ static simdjson_inline uint64_t _umul128(uint64_t ab, uint64_t cd, uint64_t *hi)
}
#endif
inline std::string_view trim(const std::string_view str) noexcept {
// We can almost surely do better by rolling our own find_first_not_of function.
size_t first = str.find_first_not_of(" \t\n\r");
// If we have the empty string (just white space), then no trimming is possible, and
// we return the empty string_view.
if (std::string_view::npos == first) { return std::string_view(); }
size_t last = str.find_last_not_of(" \t\n\r");
return str.substr(first, (last - first + 1));
}
} // namespace jsoncharutils
} // unnamed namespace
} // namespace SIMDJSON_IMPLEMENTATION
+7 -10
View File
@@ -1,14 +1,15 @@
#ifndef SIMDJSON_GENERIC_NUMBERPARSING_H
#ifndef SIMDJSON_AMALGAMATED
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
#define SIMDJSON_GENERIC_NUMBERPARSING_H
#include "simdjson/generic/base.h"
#include "simdjson/generic/jsoncharutils.h"
#include "simdjson/internal/numberparsing_tables.h"
#endif // SIMDJSON_AMALGAMATED
#endif // SIMDJSON_CONDITIONAL_INCLUDE
#include <limits>
#include <ostream>
#include <cstring>
namespace simdjson {
namespace SIMDJSON_IMPLEMENTATION {
@@ -185,8 +186,7 @@ simdjson_inline bool compute_float_64(int64_t power, uint64_t i, bool negative,
// power_of_five_128[index]. Usually, that's good enough to approximate i * 5^q
// to the desired approximation using one multiplication. Sometimes it does not suffice.
// Then we store the next most significant 64 bits in power_of_five_128[index + 1], and
// then we get a better approximation to i * 5^q. In very rare cases, even that
// will not suffice, though it is seemingly very hard to find such a scenario.
// then we get a better approximation to i * 5^q.
//
// That's for when q>=0. The logic for q<0 is somewhat similar but it is somewhat
// more complicated.
@@ -201,12 +201,9 @@ simdjson_inline bool compute_float_64(int64_t power, uint64_t i, bool negative,
simdjson::internal::value128 secondproduct = full_multiplication(i, simdjson::internal::power_of_five_128[index + 1]);
firstproduct.low += secondproduct.high;
if(secondproduct.high > firstproduct.low) { firstproduct.high++; }
// At this point, we might need to add at most one to firstproduct, but this
// can only change the value of firstproduct.high if firstproduct.low is maximal.
if(simdjson_unlikely(firstproduct.low == 0xFFFFFFFFFFFFFFFF)) {
// This is very unlikely, but if so, we need to do much more work!
return false;
}
// As it has been proven by Noble Mushtak and Daniel Lemire in "Fast Number Parsing Without
// Fallback" (https://arxiv.org/abs/2212.06644), at this point we are sure that the product
// is sufficiently accurate, and more computation is not needed.
}
uint64_t lower = firstproduct.low;
uint64_t upper = firstproduct.high;
@@ -1,4 +1,4 @@
#if defined(SIMDJSON_AMALGAMATED) && !defined(SIMDJSON_GENERIC_ONDEMAND_DEPENDENCIES_H)
#if defined(SIMDJSON_CONDITIONAL_INCLUDE) && !defined(SIMDJSON_GENERIC_ONDEMAND_DEPENDENCIES_H)
#error simdjson/generic/ondemand/dependencies.h must be included before simdjson/generic/ondemand/amalgamated.h!
#endif
@@ -1,6 +1,6 @@
#ifndef SIMDJSON_GENERIC_ONDEMAND_ARRAY_INL_H
#ifndef SIMDJSON_AMALGAMATED
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
#define SIMDJSON_GENERIC_ONDEMAND_ARRAY_INL_H
#include "simdjson/generic/ondemand/base.h"
#include "simdjson/generic/ondemand/array.h"
@@ -8,7 +8,7 @@
#include "simdjson/generic/ondemand/json_iterator.h"
#include "simdjson/generic/ondemand/value.h"
#include "simdjson/generic/ondemand/value_iterator-inl.h"
#endif // SIMDJSON_AMALGAMATED
#endif // SIMDJSON_CONDITIONAL_INCLUDE
namespace simdjson {
namespace SIMDJSON_IMPLEMENTATION {
+2 -2
View File
@@ -1,11 +1,11 @@
#ifndef SIMDJSON_GENERIC_ONDEMAND_ARRAY_H
#ifndef SIMDJSON_AMALGAMATED
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
#define SIMDJSON_GENERIC_ONDEMAND_ARRAY_H
#include "simdjson/generic/ondemand/base.h"
#include "simdjson/generic/implementation_simdjson_result_base.h"
#include "simdjson/generic/ondemand/value_iterator.h"
#endif // SIMDJSON_AMALGAMATED
#endif // SIMDJSON_CONDITIONAL_INCLUDE
namespace simdjson {
namespace SIMDJSON_IMPLEMENTATION {
@@ -1,12 +1,12 @@
#ifndef SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_INL_H
#ifndef SIMDJSON_AMALGAMATED
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
#define SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_INL_H
#include "simdjson/generic/ondemand/base.h"
#include "simdjson/generic/ondemand/array_iterator.h"
#include "simdjson/generic/ondemand/value-inl.h"
#include "simdjson/generic/ondemand/value_iterator-inl.h"
#endif // SIMDJSON_AMALGAMATED
#endif // SIMDJSON_CONDITIONAL_INCLUDE
namespace simdjson {
namespace SIMDJSON_IMPLEMENTATION {
@@ -1,11 +1,11 @@
#ifndef SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_H
#ifndef SIMDJSON_AMALGAMATED
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
#define SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_H
#include "simdjson/generic/implementation_simdjson_result_base.h"
#include "simdjson/generic/ondemand/base.h"
#include "simdjson/generic/ondemand/value_iterator.h"
#endif // SIMDJSON_AMALGAMATED
#endif // SIMDJSON_CONDITIONAL_INCLUDE
namespace simdjson {
+2 -2
View File
@@ -1,9 +1,9 @@
#ifndef SIMDJSON_GENERIC_ONDEMAND_BASE_H
#ifndef SIMDJSON_AMALGAMATED
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
#define SIMDJSON_GENERIC_ONDEMAND_BASE_H
#include "simdjson/generic/base.h"
#endif // SIMDJSON_AMALGAMATED
#endif // SIMDJSON_CONDITIONAL_INCLUDE
namespace simdjson {
namespace SIMDJSON_IMPLEMENTATION {

Some files were not shown because too many files have changed in this diff Show More