Compare commits

...

13 Commits

Author SHA1 Message Date
Daniel Lemire 88bf5cb6d9 version bump 2024-01-29 10:43:12 -05:00
Niles Salter 9b0435d864 [utf8-validator] eliminate unnecessary comparison from must_be_2_3_continuation (#2113)
* [utf8-validator] eliminate unnecessary comparison from must_be_2_3_continuation

* Fix comment in
2024-01-28 12:42:59 -05:00
Daniel Lemire ddecadde86 Update README.md 2024-01-23 09:35:12 -05:00
Bo Anderson 02bee7d1b9 Add load_into_document to simdjson::dom::parser (#2103) 2024-01-08 20:30:26 -05:00
Daniel Lemire 6ef555e6fb This PR updates the backup string_view implementation. It also adds a few comments to our README.md file. (#2105)
* This PR updates the backup string_view implementation. It also adds a few comments to our README.md file.

* removing trailing space
2024-01-08 14:52:00 -05:00
Daniel Lemire 6952f8dfce adding gcc 13 (#2101) 2024-01-04 18:57:44 -05:00
Daniel Lemire 03d0a4731a Update README.md 2024-01-03 17:49:43 -05:00
Daniel Lemire 185ff4e8fe Update basics.md 2023-12-29 09:35:35 -05:00
Daniel Lemire 5bf6d9f3f0 Update README.md 2023-12-29 09:30:01 -05:00
Daniel Lemire 2fa729922e fix for issue 2099 (#2100)
* fix for issue 2099

* avoid exceptions.

* fix for exception-less code
2023-12-19 12:15:59 -05:00
Daniel Lemire ebd09cb2a3 Update basics.md 2023-12-15 08:29:16 -05:00
Dirk Stolle 3978b9f159 update actions/checkout in GitHub Actions to v4 (#2095) 2023-12-09 23:21:28 -05:00
Dirk Stolle edc36a87ab fix a small typo (#2096) 2023-12-09 23:20:51 -05:00
53 changed files with 475 additions and 312 deletions
+1 -1
View File
@@ -9,7 +9,7 @@ jobs:
! contains(toJSON(github.event.commits.*.message), '[skip github]') ! contains(toJSON(github.event.commits.*.message), '[skip github]')
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: actions/cache@v3 - uses: actions/cache@v3
with: with:
path: dependencies/.cache path: dependencies/.cache
+1 -1
View File
@@ -16,7 +16,7 @@ jobs:
image: debian:testing image: debian:testing
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: Install dependencies - name: Install dependencies
run: | run: |
+1 -1
View File
@@ -19,7 +19,7 @@ jobs:
url: ${{ steps.deployment.outputs.page_url }} url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: Install Doxygen - name: Install Doxygen
run: sudo apt-get install doxygen graphviz -y run: sudo apt-get install doxygen graphviz -y
- run: mkdir docs - run: mkdir docs
@@ -6,7 +6,7 @@ jobs:
whitespace: whitespace:
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: Remove whitespace and check the diff - name: Remove whitespace and check the diff
run: | run: |
set -eu set -eu
+1 -1
View File
@@ -38,7 +38,7 @@ jobs:
chmod +x llvm.sh chmod +x llvm.sh
sudo ./llvm.sh $CLANGVERSION sudo ./llvm.sh $CLANGVERSION
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: actions/cache@v3 - uses: actions/cache@v3
with: with:
+1 -1
View File
@@ -9,7 +9,7 @@ jobs:
! contains(toJSON(github.event.commits.*.message), '[skip github]') ! contains(toJSON(github.event.commits.*.message), '[skip github]')
runs-on: macos-latest runs-on: macos-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: actions/cache@v3 - uses: actions/cache@v3
with: with:
path: dependencies/.cache path: dependencies/.cache
+1 -1
View File
@@ -24,7 +24,7 @@ jobs:
CMAKE_GENERATOR: Ninja CMAKE_GENERATOR: Ninja
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: actions/cache@v3 - uses: actions/cache@v3
with: with:
path: dependencies/.cache path: dependencies/.cache
+1 -1
View File
@@ -26,7 +26,7 @@ jobs:
CMAKE_GENERATOR: Ninja CMAKE_GENERATOR: Ninja
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: actions/cache@v3 - uses: actions/cache@v3
with: with:
path: dependencies/.cache path: dependencies/.cache
+1 -1
View File
@@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
name: Build on ubuntu-20.04 ppc64le name: Build on ubuntu-20.04 ppc64le
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: uraimo/run-on-arch-action@v2.0.5 - uses: uraimo/run-on-arch-action@v2.0.5
name: Run commands name: Run commands
id: runcmd id: runcmd
+1 -1
View File
@@ -12,7 +12,7 @@ jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: uraimo/run-on-arch-action@v2 - uses: uraimo/run-on-arch-action@v2
name: Test name: Test
id: runcmd id: runcmd
+1 -1
View File
@@ -12,7 +12,7 @@ jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: uraimo/run-on-arch-action@v2 - uses: uraimo/run-on-arch-action@v2
name: Test name: Test
id: runcmd id: runcmd
+1 -1
View File
@@ -12,7 +12,7 @@ jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: uraimo/run-on-arch-action@v2 - uses: uraimo/run-on-arch-action@v2
name: Test name: Test
id: runcmd id: runcmd
+1 -1
View File
@@ -15,7 +15,7 @@ jobs:
! contains(toJSON(github.event.commits.*.message), '[skip github]') ! contains(toJSON(github.event.commits.*.message), '[skip github]')
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: actions/cache@v3 - uses: actions/cache@v3
with: with:
path: dependencies/.cache path: dependencies/.cache
+1 -1
View File
@@ -12,7 +12,7 @@ jobs:
CXX: g++-8 CXX: g++-8
CC: gcc-8 CC: gcc-8
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: actions/cache@v3 - uses: actions/cache@v3
with: with:
path: dependencies/.cache path: dependencies/.cache
+1 -1
View File
@@ -9,7 +9,7 @@ jobs:
! contains(toJSON(github.event.commits.*.message), '[skip github]') ! contains(toJSON(github.event.commits.*.message), '[skip github]')
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: actions/cache@v3 - uses: actions/cache@v3
with: with:
path: dependencies/.cache path: dependencies/.cache
+1 -1
View File
@@ -9,7 +9,7 @@ jobs:
! contains(toJSON(github.event.commits.*.message), '[skip github]') ! contains(toJSON(github.event.commits.*.message), '[skip github]')
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: actions/cache@v3 - uses: actions/cache@v3
with: with:
path: dependencies/.cache path: dependencies/.cache
+2 -2
View File
@@ -9,7 +9,7 @@ jobs:
! contains(toJSON(github.event.commits.*.message), '[skip github]') ! contains(toJSON(github.event.commits.*.message), '[skip github]')
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: actions/cache@v3 - uses: actions/cache@v3
with: with:
path: dependencies/.cache path: dependencies/.cache
@@ -27,7 +27,7 @@ jobs:
! contains(toJSON(github.event.commits.*.message), '[skip github]') ! contains(toJSON(github.event.commits.*.message), '[skip github]')
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: actions/cache@v3 - uses: actions/cache@v3
with: with:
path: dependencies/.cache path: dependencies/.cache
+1 -1
View File
@@ -9,7 +9,7 @@ jobs:
! contains(toJSON(github.event.commits.*.message), '[skip github]') ! contains(toJSON(github.event.commits.*.message), '[skip github]')
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: actions/cache@v3 - uses: actions/cache@v3
with: with:
path: dependencies/.cache path: dependencies/.cache
+1 -1
View File
@@ -9,7 +9,7 @@ jobs:
! contains(toJSON(github.event.commits.*.message), '[skip github]') ! contains(toJSON(github.event.commits.*.message), '[skip github]')
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: actions/cache@v3 - uses: actions/cache@v3
with: with:
path: dependencies/.cache path: dependencies/.cache
+1 -1
View File
@@ -9,7 +9,7 @@ jobs:
! contains(toJSON(github.event.commits.*.message), '[skip github]') ! contains(toJSON(github.event.commits.*.message), '[skip github]')
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: actions/cache@v3 - uses: actions/cache@v3
with: with:
path: dependencies/.cache path: dependencies/.cache
+1 -1
View File
@@ -9,7 +9,7 @@ jobs:
! contains(toJSON(github.event.commits.*.message), '[skip github]') ! contains(toJSON(github.event.commits.*.message), '[skip github]')
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: actions/cache@v3 - uses: actions/cache@v3
with: with:
path: dependencies/.cache path: dependencies/.cache
+1 -3
View File
@@ -9,13 +9,11 @@ jobs:
! contains(toJSON(github.event.commits.*.message), '[skip github]') ! contains(toJSON(github.event.commits.*.message), '[skip github]')
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: actions/cache@v3 - uses: actions/cache@v3
with: with:
path: dependencies/.cache path: dependencies/.cache
key: ${{ hashFiles('dependencies/CMakeLists.txt') }} key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
- name: Install gcc12
run: sudo apt-get install -y g++-12
- name: Use cmake - name: Use cmake
run: | run: |
mkdir build && mkdir build &&
+23
View File
@@ -0,0 +1,23 @@
name: Ubuntu 22.04 CI (GCC 13)
on: [push, pull_request]
jobs:
ubuntu-build:
if: >-
! contains(toJSON(github.event.commits.*.message), '[skip ci]') &&
! contains(toJSON(github.event.commits.*.message), '[skip github]')
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- uses: actions/cache@v3
with:
path: dependencies/.cache
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
- name: Use cmake
run: |
mkdir build &&
cd build &&
CXX=g++-13 cmake -DSIMDJSON_DEVELOPER_MODE=ON .. &&
cmake --build . &&
ctest --output-on-failure -LE explicitonly -j
@@ -8,7 +8,7 @@ jobs:
! contains(toJSON(github.event.commits.*.message), '[skip github]') ! contains(toJSON(github.event.commits.*.message), '[skip github]')
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: actions/cache@v3 - uses: actions/cache@v3
with: with:
path: dependencies/.cache path: dependencies/.cache
+1 -1
View File
@@ -9,7 +9,7 @@ jobs:
! contains(toJSON(github.event.commits.*.message), '[skip github]') ! contains(toJSON(github.event.commits.*.message), '[skip github]')
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: actions/cache@v3 - uses: actions/cache@v3
with: with:
path: dependencies/.cache path: dependencies/.cache
+1 -1
View File
@@ -9,7 +9,7 @@ jobs:
! contains(toJSON(github.event.commits.*.message), '[skip github]') ! contains(toJSON(github.event.commits.*.message), '[skip github]')
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: actions/cache@v3 - uses: actions/cache@v3
with: with:
path: dependencies/.cache path: dependencies/.cache
+1 -1
View File
@@ -14,7 +14,7 @@ jobs:
- {arch: ARM64} - {arch: ARM64}
steps: steps:
- name: checkout - name: checkout
uses: actions/checkout@v3 uses: actions/checkout@v4
- name: Use cmake - name: Use cmake
run: | run: |
cmake -A ${{ matrix.arch }} -DCMAKE_CROSSCOMPILING=1 -DSIMDJSON_DEVELOPER_MODE=ON -D SIMDJSON_GOOGLE_BENCHMARKS=OFF -DSIMDJSON_EXCEPTIONS=OFF -B build && cmake -A ${{ matrix.arch }} -DCMAKE_CROSSCOMPILING=1 -DSIMDJSON_DEVELOPER_MODE=ON -D SIMDJSON_GOOGLE_BENCHMARKS=OFF -DSIMDJSON_EXCEPTIONS=OFF -B build &&
+1 -1
View File
@@ -19,7 +19,7 @@ jobs:
- {gen: Visual Studio 17 2022, arch: x64, shared: OFF} - {gen: Visual Studio 17 2022, arch: x64, shared: OFF}
steps: steps:
- name: checkout - name: checkout
uses: actions/checkout@v3 uses: actions/checkout@v4
- name: Configure - name: Configure
run: | run: |
cmake -DSIMDJSON_CXX_STANDARD=20 -G "${{matrix.gen}}" -A ${{matrix.arch}} -DSIMDJSON_DEVELOPER_MODE=ON -DSIMDJSON_COMPETITION=OFF -DBUILD_SHARED_LIBS=${{matrix.shared}} -B build cmake -DSIMDJSON_CXX_STANDARD=20 -G "${{matrix.gen}}" -A ${{matrix.arch}} -DSIMDJSON_DEVELOPER_MODE=ON -DSIMDJSON_COMPETITION=OFF -DBUILD_SHARED_LIBS=${{matrix.shared}} -B build
+1 -1
View File
@@ -19,7 +19,7 @@ jobs:
- {gen: Visual Studio 17 2022, arch: x64, shared: OFF} - {gen: Visual Studio 17 2022, arch: x64, shared: OFF}
steps: steps:
- name: checkout - name: checkout
uses: actions/checkout@v3 uses: actions/checkout@v4
- name: Configure - name: Configure
run: | run: |
cmake -G "${{matrix.gen}}" -A ${{matrix.arch}} -DSIMDJSON_DEVELOPER_MODE=ON -DSIMDJSON_COMPETITION=OFF -DBUILD_SHARED_LIBS=${{matrix.shared}} -B build cmake -G "${{matrix.gen}}" -A ${{matrix.arch}} -DSIMDJSON_DEVELOPER_MODE=ON -DSIMDJSON_COMPETITION=OFF -DBUILD_SHARED_LIBS=${{matrix.shared}} -B build
+1 -1
View File
@@ -16,7 +16,7 @@ jobs:
- {gen: Visual Studio 17 2022, arch: x64} - {gen: Visual Studio 17 2022, arch: x64}
steps: steps:
- name: checkout - name: checkout
uses: actions/checkout@v3 uses: actions/checkout@v4
- name: Configure - name: Configure
run: | run: |
cmake -G "${{matrix.gen}}" -A ${{matrix.arch}} -T ClangCL -DSIMDJSON_DEVELOPER_MODE=ON -DSIMDJSON_COMPETITION=OFF -B build cmake -G "${{matrix.gen}}" -A ${{matrix.arch}} -T ClangCL -DSIMDJSON_DEVELOPER_MODE=ON -DSIMDJSON_COMPETITION=OFF -B build
+1 -1
View File
@@ -7,7 +7,7 @@ jobs:
name: windows-vs17 name: windows-vs17
runs-on: windows-latest runs-on: windows-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: actions/cache@v3 - uses: actions/cache@v3
with: with:
path: dependencies/.cache path: dependencies/.cache
+1 -1
View File
@@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.14)
project( project(
simdjson simdjson
# The version number is modified by tools/release.py # The version number is modified by tools/release.py
VERSION 3.6.3 VERSION 3.6.4
DESCRIPTION "Parsing gigabytes of JSON per second" DESCRIPTION "Parsing gigabytes of JSON per second"
HOMEPAGE_URL "https://simdjson.org/" HOMEPAGE_URL "https://simdjson.org/"
LANGUAGES CXX C LANGUAGES CXX C
+1 -1
View File
@@ -38,7 +38,7 @@ PROJECT_NAME = simdjson
# could be handy for archiving the generated documentation or if some version # could be handy for archiving the generated documentation or if some version
# control system is used. # control system is used.
PROJECT_NUMBER = "3.6.3" PROJECT_NUMBER = "3.6.4"
# Using the PROJECT_BRIEF tag one can provide an optional one line description # Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a # for a project that appears at the top of each page and should give viewer a
+13 -6
View File
@@ -29,6 +29,7 @@ Table of Contents
* [Real-world usage](#real-world-usage) * [Real-world usage](#real-world-usage)
* [Quick Start](#quick-start) * [Quick Start](#quick-start)
* [Documentation](#documentation) * [Documentation](#documentation)
* [Godbolt](#godbolt)
* [Performance results](#performance-results) * [Performance results](#performance-results)
* [Bindings and Ports of simdjson](#bindings-and-ports-of-simdjson) * [Bindings and Ports of simdjson](#bindings-and-ports-of-simdjson)
* [About simdjson](#about-simdjson) * [About simdjson](#about-simdjson)
@@ -68,9 +69,9 @@ The simdjson library is easily consumable with a single .h and .cpp file.
0. Prerequisites: `g++` (version 7 or better) or `clang++` (version 6 or better), and a 64-bit 0. Prerequisites: `g++` (version 7 or better) or `clang++` (version 6 or better), and a 64-bit
system with a command-line shell (e.g., Linux, macOS, freeBSD). We also support programming system with a command-line shell (e.g., Linux, macOS, freeBSD). We also support programming
environments like Visual Studio and Xcode, but different steps are needed. environments like Visual Studio and Xcode, but different steps are needed. Users of clang++ may need to specify the C++ version (e.g., `c++ -std=c++17`) since clang++ tends to default on C++98.
1. Pull [simdjson.h](singleheader/simdjson.h) and [simdjson.cpp](singleheader/simdjson.cpp) into a 1. Pull [simdjson.h](singleheader/simdjson.h) and [simdjson.cpp](singleheader/simdjson.cpp) into a
directory, along with the sample file [twitter.json](jsonexamples/twitter.json). directory, along with the sample file [twitter.json](jsonexamples/twitter.json). You can download them with the `wget` utility:
``` ```
wget https://raw.githubusercontent.com/simdjson/simdjson/master/singleheader/simdjson.h https://raw.githubusercontent.com/simdjson/simdjson/master/singleheader/simdjson.cpp https://raw.githubusercontent.com/simdjson/simdjson/master/jsonexamples/twitter.json wget https://raw.githubusercontent.com/simdjson/simdjson/master/singleheader/simdjson.h https://raw.githubusercontent.com/simdjson/simdjson/master/singleheader/simdjson.cpp https://raw.githubusercontent.com/simdjson/simdjson/master/jsonexamples/twitter.json
@@ -95,6 +96,7 @@ int main(void) {
100 results. 100 results.
``` ```
Documentation Documentation
------------- -------------
@@ -106,11 +108,12 @@ Usage documentation is available:
how you can work with it. how you can work with it.
* [API](https://simdjson.github.io/simdjson/) contains the automatically generated API documentation. * [API](https://simdjson.github.io/simdjson/) contains the automatically generated API documentation.
Godbolt
-------------
Some users may want to browse code along with the compiled assembly. You want to check out the following lists of examples: Some users may want to browse code along with the compiled assembly. You want to check out the following lists of examples:
* [simdjson examples with errors handled through exceptions](https://godbolt.org/z/7G5qE4sr9)
* [simdjson examples with errors handled through exceptions](https://godbolt.org/z/98Kx9Kqjn) * [simdjson examples with errors without exceptions](https://godbolt.org/z/e9dWb9E4v)
* [simdjson examples with errors without exceptions](https://godbolt.org/z/PKG7GdbPo)
Performance results Performance results
------------------- -------------------
@@ -174,7 +177,11 @@ The simdjson library takes advantage of modern microarchitectures, parallelizing
instructions, reducing branch misprediction, and reducing data dependency to take advantage of each instructions, reducing branch misprediction, and reducing data dependency to take advantage of each
CPU's multiple execution cores. CPU's multiple execution cores.
Some people [enjoy reading our paper](https://arxiv.org/abs/1902.08318): A description of the design Our default front-end is called On Demand, and we wrote a paper about it:
- John Keiser, Daniel Lemire, [On-Demand JSON: A Better Way to Parse Documents?](http://arxiv.org/abs/2312.17149), Software: Practice and Experience (to appear)
Some people [enjoy reading the first (2019) simdjson paper](https://arxiv.org/abs/1902.08318): A description of the design
and implementation of simdjson is in our research article: and implementation of simdjson is in our research article:
- Geoff Langdale, Daniel Lemire, [Parsing Gigabytes of JSON per Second](https://arxiv.org/abs/1902.08318), VLDB Journal 28 (6), 2019. - Geoff Langdale, Daniel Lemire, [Parsing Gigabytes of JSON per Second](https://arxiv.org/abs/1902.08318), VLDB Journal 28 (6), 2019.
+9 -2
View File
@@ -36,6 +36,7 @@ An overview of what you need to know to use simdjson, with examples.
- [Backwards Compatibility](#backwards-compatibility) - [Backwards Compatibility](#backwards-compatibility)
- [Examples](#examples) - [Examples](#examples)
- [Performance Tips](#performance-tips) - [Performance Tips](#performance-tips)
- [Further Reading](#further-reading)
Requirements Requirements
@@ -1656,8 +1657,8 @@ JSON string to a user-provided buffer:
General Direct Access to the Raw JSON String General Direct Access to the Raw JSON String
-------------------------------- --------------------------------
If your value is a string, the `raw_json_string` you with `get_raw_json_string()` gives you direct access to the unprocessed 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 string. But the simdjson library allows you to have access to the raw underlying JSON
more generally. more generally, not just for strings.
The simdjson library makes explicit assumptions about types. For examples, numbers The simdjson library makes explicit assumptions about types. For examples, numbers
must be integers (up to 64-bit integers) or binary64 floating-point numbers. Some users must be integers (up to 64-bit integers) or binary64 floating-point numbers. Some users
@@ -2127,3 +2128,9 @@ Performance Tips
std::string_view rating = data["rating"]; 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.
Further reading
--------
- John Keiser, Daniel Lemire, [On-Demand JSON: A Better Way to Parse Documents?](http://arxiv.org/abs/2312.17149), Software: Practice and Experience (to appear)
+1 -1
View File
@@ -214,7 +214,7 @@ public:
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), " "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). " "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(), " "We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), "
"get_object(), get_array() or get_string() instead of the get template."); "get_object(), get_array() or get_string() instead of the get template.");
} }
+5 -1
View File
@@ -92,10 +92,14 @@ inline simdjson_result<size_t> parser::read_file(const std::string &path) noexce
} }
inline simdjson_result<element> parser::load(const std::string &path) & noexcept { inline simdjson_result<element> parser::load(const std::string &path) & noexcept {
return load_into_document(doc, path);
}
inline simdjson_result<element> parser::load_into_document(document& provided_doc, const std::string &path) & noexcept {
size_t len; size_t len;
auto _error = read_file(path).get(len); auto _error = read_file(path).get(len);
if (_error) { return _error; } if (_error) { return _error; }
return parse(loaded_bytes.get(), len, false); return parse_into_document(provided_doc, loaded_bytes.get(), len, false);
} }
inline simdjson_result<document_stream> parser::load_many(const std::string &path, size_t batch_size) noexcept { inline simdjson_result<document_stream> parser::load_many(const std::string &path, size_t batch_size) noexcept {
+47
View File
@@ -95,6 +95,53 @@ public:
*/ */
inline simdjson_result<element> load(const std::string &path) & noexcept; inline simdjson_result<element> load(const std::string &path) & noexcept;
inline simdjson_result<element> load(const std::string &path) && = delete ; inline simdjson_result<element> load(const std::string &path) && = delete ;
/**
* Load a JSON document from a file into a provide document instance and return a temporary reference to it.
* It is similar to the function `load` except that instead of parsing into the internal
* `document` instance associated with the parser, it allows the user to provide a document
* instance.
*
* dom::parser parser;
* dom::document doc;
* element doc_root = parser.load_into_document(doc, "jsonexamples/twitter.json");
*
* The function is eager: the file's content is loaded in memory inside the parser instance
* and immediately parsed. The file can be deleted after the `parser.load_into_document` call.
*
* ### IMPORTANT: Document Lifetime
*
* After the call to load_into_document, the parser is no longer needed.
*
* The JSON document lives in the document instance: you must keep the document
* instance alive while you navigate through it (i.e., used the returned value from
* load_into_document). You are encourage to reuse the document instance
* many times with new data to avoid reallocations:
*
* dom::document doc;
* element doc_root1 = parser.load_into_document(doc, "jsonexamples/twitter.json");
* //... doc_root1 is a pointer inside doc
* element doc_root2 = parser.load_into_document(doc, "jsonexamples/twitter.json");
* //... doc_root2 is a pointer inside doc
* // at this point doc_root1 is no longer safe
*
* Moving the document instance is safe, but it invalidates the element instances. After
* moving a document, you can recover safe access to the document root with its `root()` method.
*
* @param doc The document instance where the parsed data will be stored (on success).
* @param path The path to load.
* @return The document, or an error:
* - IO_ERROR if there was an error opening or reading the file.
* Be mindful that on some 32-bit systems,
* the file size might be limited to 2 GB.
* - MEMALLOC if the parser does not have enough capacity and memory allocation fails.
* - CAPACITY if the parser does not have enough capacity and len > max_capacity.
* - other json errors if parsing fails. You should not rely on these errors to always the same for the
* same document: they may vary under runtime dispatch (so they may vary depending on your system and hardware).
*/
inline simdjson_result<element> load_into_document(document& doc, const std::string &path) & noexcept;
inline simdjson_result<element> load_into_document(document& doc, const std::string &path) && =delete;
/** /**
* Parse a JSON document and return a temporary reference to it. * Parse a JSON document and return a temporary reference to it.
* *
+9 -12
View File
@@ -446,11 +446,8 @@ simdjson_inline size_t significant_digits(const uint8_t * start_digits, size_t d
} // unnamed namespace } // unnamed namespace
/** @private */ /** @private */
template<typename W> static error_code slow_float_parsing(simdjson_unused const uint8_t * src, double* answer) {
error_code slow_float_parsing(simdjson_unused const uint8_t * src, W writer) { if (parse_float_fallback(src, answer)) {
double d;
if (parse_float_fallback(src, &d)) {
writer.append_double(d);
return SUCCESS; return SUCCESS;
} }
return INVALID_NUMBER(src); return INVALID_NUMBER(src);
@@ -474,13 +471,13 @@ simdjson_inline error_code write_float(const uint8_t *const src, bool negative,
// 10000000000000000000000000000000000000000000e+308 // 10000000000000000000000000000000000000000000e+308
// 3.1415926535897932384626433832795028841971693993751 // 3.1415926535897932384626433832795028841971693993751
// //
// NOTE: This makes a *copy* of the writer and passes it to slow_float_parsing. This happens // NOTE: We do not pass a reference to the to slow_float_parsing. If we passed our writer
// because slow_float_parsing is a non-inlined function. If we passed our writer reference to // reference to it, it would force it to be stored in memory, preventing the compiler from
// it, it would force it to be stored in memory, preventing the compiler from picking it apart // picking it apart and putting into registers. i.e. if we pass it as reference,
// and putting into registers. i.e. if we pass it as reference, it gets slow. // it gets slow.
// This is what forces the skip_double, as well. double d;
error_code error = slow_float_parsing(src, writer); error_code error = slow_float_parsing(src, &d);
writer.skip_double(); writer.append_double(d);
return error; return error;
} }
// NOTE: it's weird that the simdjson_unlikely() only wraps half the if, but it seems to get slower any other // NOTE: it's weird that the simdjson_unlikely() only wraps half the if, but it seems to get slower any other
@@ -92,8 +92,6 @@ protected:
*/ */
friend class value_iterator; friend class value_iterator;
template<typename W> template<typename W>
friend error_code numberparsing::slow_float_parsing(simdjson_unused const uint8_t * src, W writer);
template<typename W>
friend error_code numberparsing::write_float(const uint8_t *const src, bool negative, uint64_t i, const uint8_t * start_digits, size_t digit_count, int64_t exponent, W &writer); friend error_code numberparsing::write_float(const uint8_t *const src, bool negative, uint64_t i, const uint8_t * start_digits, size_t digit_count, int64_t exponent, W &writer);
template<typename W> template<typename W>
friend error_code numberparsing::parse_number(const uint8_t *const src, W &writer); friend error_code numberparsing::parse_number(const uint8_t *const src, W &writer);
+31 -8
View File
@@ -6,7 +6,7 @@
// Distributed under the Boost Software License, Version 1.0. // Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#pragma once // #pragma once // We remove #pragma once here as it generates a warning in some cases. We rely on the include guard.
#ifndef NONSTD_SV_LITE_H_INCLUDED #ifndef NONSTD_SV_LITE_H_INCLUDED
#define NONSTD_SV_LITE_H_INCLUDED #define NONSTD_SV_LITE_H_INCLUDED
@@ -69,6 +69,10 @@
# define nssv_CONFIG_NO_STREAM_INSERTION 0 # define nssv_CONFIG_NO_STREAM_INSERTION 0
#endif #endif
#ifndef nssv_CONFIG_CONSTEXPR11_STD_SEARCH
# define nssv_CONFIG_CONSTEXPR11_STD_SEARCH 1
#endif
// Control presence of exception handling (try and auto discover): // Control presence of exception handling (try and auto discover):
#ifndef nssv_CONFIG_NO_EXCEPTIONS #ifndef nssv_CONFIG_NO_EXCEPTIONS
@@ -267,7 +271,7 @@ using std::operator<<;
# define nssv_HAS_CPP0X 0 # define nssv_HAS_CPP0X 0
#endif #endif
// Unless defined otherwise below, consider VC14 as C++11 for variant-lite: // Unless defined otherwise below, consider VC14 as C++11 for string-view-lite:
#if nssv_COMPILER_MSVC_VER >= 1900 #if nssv_COMPILER_MSVC_VER >= 1900
# undef nssv_CPP11_OR_GREATER # undef nssv_CPP11_OR_GREATER
@@ -434,9 +438,9 @@ using std::operator<<;
# pragma clang diagnostic ignored "-Wreserved-user-defined-literal" # pragma clang diagnostic ignored "-Wreserved-user-defined-literal"
# pragma clang diagnostic push # pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wuser-defined-literals" # pragma clang diagnostic ignored "-Wuser-defined-literals"
#elif defined(__GNUC__) #elif nssv_COMPILER_GNUC_VERSION >= 480
# pragma GCC diagnostic push # pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wliteral-suffix" # pragma GCC diagnostic ignored "-Wliteral-suffix"
#endif // __clang__ #endif // __clang__
#if nssv_COMPILER_MSVC_VERSION >= 140 #if nssv_COMPILER_MSVC_VERSION >= 140
@@ -451,8 +455,8 @@ using std::operator<<;
#if defined(__clang__) #if defined(__clang__)
# define nssv_RESTORE_WARNINGS() _Pragma("clang diagnostic pop") # define nssv_RESTORE_WARNINGS() _Pragma("clang diagnostic pop")
#elif defined(__GNUC__) #elif nssv_COMPILER_GNUC_VERSION >= 480
# define nssv_RESTORE_WARNINGS() _Pragma("GCC diagnostic pop") # define nssv_RESTORE_WARNINGS() _Pragma("GCC diagnostic pop")
#elif nssv_COMPILER_MSVC_VERSION >= 140 #elif nssv_COMPILER_MSVC_VERSION >= 140
# define nssv_RESTORE_WARNINGS() __pragma(warning(pop )) # define nssv_RESTORE_WARNINGS() __pragma(warning(pop ))
#else #else
@@ -567,12 +571,31 @@ constexpr const CharT* search( basic_string_view<CharT, Traits> haystack, basic_
// non-recursive: // non-recursive:
#if nssv_CONFIG_CONSTEXPR11_STD_SEARCH
template< class CharT, class Traits = std::char_traits<CharT> > template< class CharT, class Traits = std::char_traits<CharT> >
constexpr const CharT* search( basic_string_view<CharT, Traits> haystack, basic_string_view<CharT, Traits> needle ) constexpr const CharT* search( basic_string_view<CharT, Traits> haystack, basic_string_view<CharT, Traits> needle )
{ {
return std::search( haystack.begin(), haystack.end(), needle.begin(), needle.end() ); return std::search( haystack.begin(), haystack.end(), needle.begin(), needle.end() );
} }
#else // nssv_CONFIG_CONSTEXPR11_STD_SEARCH
template< class CharT, class Traits = std::char_traits<CharT> >
nssv_constexpr14 const CharT* search( basic_string_view<CharT, Traits> haystack, basic_string_view<CharT, Traits> needle )
{
while ( needle.size() <= haystack.size() )
{
if ( haystack.starts_with(needle) )
{
return haystack.cbegin();
}
haystack = basic_string_view<CharT, Traits>{ haystack.begin() + 1, haystack.size() - 1U };
}
return haystack.cend();
}
#endif // nssv_CONFIG_CONSTEXPR11_STD_SEARCH
#endif // OPTIMIZE #endif // OPTIMIZE
#endif // nssv_CPP11_OR_GREATER && ! nssv_CPP17_OR_GREATER #endif // nssv_CPP11_OR_GREATER && ! nssv_CPP17_OR_GREATER
@@ -845,7 +868,7 @@ public:
// find(), 4x: // find(), 4x:
nssv_constexpr size_type find( basic_string_view v, size_type pos = 0 ) const nssv_noexcept // (1) nssv_constexpr14 size_type find( basic_string_view v, size_type pos = 0 ) const nssv_noexcept // (1)
{ {
return assert( v.size() == 0 || v.data() != nssv_nullptr ) return assert( v.size() == 0 || v.data() != nssv_nullptr )
, pos >= size() , pos >= size()
+2 -2
View File
@@ -4,7 +4,7 @@
#define SIMDJSON_SIMDJSON_VERSION_H #define SIMDJSON_SIMDJSON_VERSION_H
/** The version of simdjson being used (major.minor.revision) */ /** The version of simdjson being used (major.minor.revision) */
#define SIMDJSON_VERSION "3.6.3" #define SIMDJSON_VERSION "3.6.4"
namespace simdjson { namespace simdjson {
enum { enum {
@@ -19,7 +19,7 @@ enum {
/** /**
* The revision (major.minor.REVISION) of simdjson being used. * The revision (major.minor.REVISION) of simdjson being used.
*/ */
SIMDJSON_VERSION_REVISION = 3 SIMDJSON_VERSION_REVISION = 4
}; };
} // namespace simdjson } // namespace simdjson
+116 -115
View File
@@ -1,4 +1,4 @@
/* auto-generated on 2023-12-07 12:42:28 -0500. Do not edit! */ /* auto-generated on 2024-01-28 12:42:59 -0500. Do not edit! */
/* including simdjson.cpp: */ /* including simdjson.cpp: */
/* begin file simdjson.cpp */ /* begin file simdjson.cpp */
#define SIMDJSON_SRC_SIMDJSON_CPP #define SIMDJSON_SRC_SIMDJSON_CPP
@@ -525,7 +525,7 @@ SIMDJSON_PUSH_DISABLE_ALL_WARNINGS
// Distributed under the Boost Software License, Version 1.0. // Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#pragma once // #pragma once // We remove #pragma once here as it generates a warning in some cases. We rely on the include guard.
#ifndef NONSTD_SV_LITE_H_INCLUDED #ifndef NONSTD_SV_LITE_H_INCLUDED
#define NONSTD_SV_LITE_H_INCLUDED #define NONSTD_SV_LITE_H_INCLUDED
@@ -588,6 +588,10 @@ SIMDJSON_PUSH_DISABLE_ALL_WARNINGS
# define nssv_CONFIG_NO_STREAM_INSERTION 0 # define nssv_CONFIG_NO_STREAM_INSERTION 0
#endif #endif
#ifndef nssv_CONFIG_CONSTEXPR11_STD_SEARCH
# define nssv_CONFIG_CONSTEXPR11_STD_SEARCH 1
#endif
// Control presence of exception handling (try and auto discover): // Control presence of exception handling (try and auto discover):
#ifndef nssv_CONFIG_NO_EXCEPTIONS #ifndef nssv_CONFIG_NO_EXCEPTIONS
@@ -786,7 +790,7 @@ using std::operator<<;
# define nssv_HAS_CPP0X 0 # define nssv_HAS_CPP0X 0
#endif #endif
// Unless defined otherwise below, consider VC14 as C++11 for variant-lite: // Unless defined otherwise below, consider VC14 as C++11 for string-view-lite:
#if nssv_COMPILER_MSVC_VER >= 1900 #if nssv_COMPILER_MSVC_VER >= 1900
# undef nssv_CPP11_OR_GREATER # undef nssv_CPP11_OR_GREATER
@@ -953,9 +957,9 @@ using std::operator<<;
# pragma clang diagnostic ignored "-Wreserved-user-defined-literal" # pragma clang diagnostic ignored "-Wreserved-user-defined-literal"
# pragma clang diagnostic push # pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wuser-defined-literals" # pragma clang diagnostic ignored "-Wuser-defined-literals"
#elif defined(__GNUC__) #elif nssv_COMPILER_GNUC_VERSION >= 480
# pragma GCC diagnostic push # pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wliteral-suffix" # pragma GCC diagnostic ignored "-Wliteral-suffix"
#endif // __clang__ #endif // __clang__
#if nssv_COMPILER_MSVC_VERSION >= 140 #if nssv_COMPILER_MSVC_VERSION >= 140
@@ -970,8 +974,8 @@ using std::operator<<;
#if defined(__clang__) #if defined(__clang__)
# define nssv_RESTORE_WARNINGS() _Pragma("clang diagnostic pop") # define nssv_RESTORE_WARNINGS() _Pragma("clang diagnostic pop")
#elif defined(__GNUC__) #elif nssv_COMPILER_GNUC_VERSION >= 480
# define nssv_RESTORE_WARNINGS() _Pragma("GCC diagnostic pop") # define nssv_RESTORE_WARNINGS() _Pragma("GCC diagnostic pop")
#elif nssv_COMPILER_MSVC_VERSION >= 140 #elif nssv_COMPILER_MSVC_VERSION >= 140
# define nssv_RESTORE_WARNINGS() __pragma(warning(pop )) # define nssv_RESTORE_WARNINGS() __pragma(warning(pop ))
#else #else
@@ -1086,12 +1090,31 @@ constexpr const CharT* search( basic_string_view<CharT, Traits> haystack, basic_
// non-recursive: // non-recursive:
#if nssv_CONFIG_CONSTEXPR11_STD_SEARCH
template< class CharT, class Traits = std::char_traits<CharT> > template< class CharT, class Traits = std::char_traits<CharT> >
constexpr const CharT* search( basic_string_view<CharT, Traits> haystack, basic_string_view<CharT, Traits> needle ) constexpr const CharT* search( basic_string_view<CharT, Traits> haystack, basic_string_view<CharT, Traits> needle )
{ {
return std::search( haystack.begin(), haystack.end(), needle.begin(), needle.end() ); return std::search( haystack.begin(), haystack.end(), needle.begin(), needle.end() );
} }
#else // nssv_CONFIG_CONSTEXPR11_STD_SEARCH
template< class CharT, class Traits = std::char_traits<CharT> >
nssv_constexpr14 const CharT* search( basic_string_view<CharT, Traits> haystack, basic_string_view<CharT, Traits> needle )
{
while ( needle.size() <= haystack.size() )
{
if ( haystack.starts_with(needle) )
{
return haystack.cbegin();
}
haystack = basic_string_view<CharT, Traits>{ haystack.begin() + 1, haystack.size() - 1U };
}
return haystack.cend();
}
#endif // nssv_CONFIG_CONSTEXPR11_STD_SEARCH
#endif // OPTIMIZE #endif // OPTIMIZE
#endif // nssv_CPP11_OR_GREATER && ! nssv_CPP17_OR_GREATER #endif // nssv_CPP11_OR_GREATER && ! nssv_CPP17_OR_GREATER
@@ -1364,7 +1387,7 @@ public:
// find(), 4x: // find(), 4x:
nssv_constexpr size_type find( basic_string_view v, size_type pos = 0 ) const nssv_noexcept // (1) nssv_constexpr14 size_type find( basic_string_view v, size_type pos = 0 ) const nssv_noexcept // (1)
{ {
return assert( v.size() == 0 || v.data() != nssv_nullptr ) return assert( v.size() == 0 || v.data() != nssv_nullptr )
, pos >= size() , pos >= size()
@@ -9025,11 +9048,8 @@ simdjson_inline size_t significant_digits(const uint8_t * start_digits, size_t d
} // unnamed namespace } // unnamed namespace
/** @private */ /** @private */
template<typename W> static error_code slow_float_parsing(simdjson_unused const uint8_t * src, double* answer) {
error_code slow_float_parsing(simdjson_unused const uint8_t * src, W writer) { if (parse_float_fallback(src, answer)) {
double d;
if (parse_float_fallback(src, &d)) {
writer.append_double(d);
return SUCCESS; return SUCCESS;
} }
return INVALID_NUMBER(src); return INVALID_NUMBER(src);
@@ -9053,13 +9073,13 @@ simdjson_inline error_code write_float(const uint8_t *const src, bool negative,
// 10000000000000000000000000000000000000000000e+308 // 10000000000000000000000000000000000000000000e+308
// 3.1415926535897932384626433832795028841971693993751 // 3.1415926535897932384626433832795028841971693993751
// //
// NOTE: This makes a *copy* of the writer and passes it to slow_float_parsing. This happens // NOTE: We do not pass a reference to the to slow_float_parsing. If we passed our writer
// because slow_float_parsing is a non-inlined function. If we passed our writer reference to // reference to it, it would force it to be stored in memory, preventing the compiler from
// it, it would force it to be stored in memory, preventing the compiler from picking it apart // picking it apart and putting into registers. i.e. if we pass it as reference,
// and putting into registers. i.e. if we pass it as reference, it gets slow. // it gets slow.
// This is what forces the skip_double, as well. double d;
error_code error = slow_float_parsing(src, writer); error_code error = slow_float_parsing(src, &d);
writer.skip_double(); writer.append_double(d);
return error; return error;
} }
// NOTE: it's weird that the simdjson_unlikely() only wraps half the if, but it seems to get slower any other // NOTE: it's weird that the simdjson_unlikely() only wraps half the if, but it seems to get slower any other
@@ -10852,7 +10872,7 @@ namespace simdjson {
namespace arm64 { namespace arm64 {
namespace { namespace {
simdjson_inline simd8<bool> must_be_2_3_continuation(const simd8<uint8_t> prev2, const simd8<uint8_t> prev3); simdjson_inline simd8<uint8_t> must_be_2_3_continuation(const simd8<uint8_t> prev2, const simd8<uint8_t> prev3);
simdjson_inline bool is_ascii(const simd8x64<uint8_t>& input); simdjson_inline bool is_ascii(const simd8x64<uint8_t>& input);
} // unnamed namespace } // unnamed namespace
@@ -11419,7 +11439,7 @@ using namespace simd;
const simd8<uint8_t> prev_input, const simd8<uint8_t> sc) { const simd8<uint8_t> prev_input, const simd8<uint8_t> sc) {
simd8<uint8_t> prev2 = input.prev<2>(prev_input); simd8<uint8_t> prev2 = input.prev<2>(prev_input);
simd8<uint8_t> prev3 = input.prev<3>(prev_input); simd8<uint8_t> prev3 = input.prev<3>(prev_input);
simd8<uint8_t> must23 = simd8<uint8_t>(must_be_2_3_continuation(prev2, prev3)); simd8<uint8_t> must23 = must_be_2_3_continuation(prev2, prev3);
simd8<uint8_t> must23_80 = must23 & uint8_t(0x80); simd8<uint8_t> must23_80 = must23 & uint8_t(0x80);
return must23_80 ^ sc; return must23_80 ^ sc;
} }
@@ -13614,10 +13634,10 @@ simdjson_unused simdjson_inline simd8<bool> must_be_continuation(const simd8<uin
return is_second_byte ^ is_third_byte ^ is_fourth_byte; return is_second_byte ^ is_third_byte ^ is_fourth_byte;
} }
simdjson_inline simd8<bool> must_be_2_3_continuation(const simd8<uint8_t> prev2, const simd8<uint8_t> prev3) { simdjson_inline simd8<uint8_t> must_be_2_3_continuation(const simd8<uint8_t> prev2, const simd8<uint8_t> prev3) {
simd8<bool> is_third_byte = prev2 >= uint8_t(0xe0u); simd8<uint8_t> is_third_byte = prev2.saturating_sub(0xe0u-0x80); // Only 111_____ will be >= 0x80
simd8<bool> is_fourth_byte = prev3 >= uint8_t(0xf0u); simd8<uint8_t> is_fourth_byte = prev3.saturating_sub(0xf0u-0x80); // Only 1111____ will be >= 0x80
return is_third_byte ^ is_fourth_byte; return is_third_byte | is_fourth_byte;
} }
} // unnamed namespace } // unnamed namespace
@@ -14823,11 +14843,8 @@ simdjson_inline size_t significant_digits(const uint8_t * start_digits, size_t d
} // unnamed namespace } // unnamed namespace
/** @private */ /** @private */
template<typename W> static error_code slow_float_parsing(simdjson_unused const uint8_t * src, double* answer) {
error_code slow_float_parsing(simdjson_unused const uint8_t * src, W writer) { if (parse_float_fallback(src, answer)) {
double d;
if (parse_float_fallback(src, &d)) {
writer.append_double(d);
return SUCCESS; return SUCCESS;
} }
return INVALID_NUMBER(src); return INVALID_NUMBER(src);
@@ -14851,13 +14868,13 @@ simdjson_inline error_code write_float(const uint8_t *const src, bool negative,
// 10000000000000000000000000000000000000000000e+308 // 10000000000000000000000000000000000000000000e+308
// 3.1415926535897932384626433832795028841971693993751 // 3.1415926535897932384626433832795028841971693993751
// //
// NOTE: This makes a *copy* of the writer and passes it to slow_float_parsing. This happens // NOTE: We do not pass a reference to the to slow_float_parsing. If we passed our writer
// because slow_float_parsing is a non-inlined function. If we passed our writer reference to // reference to it, it would force it to be stored in memory, preventing the compiler from
// it, it would force it to be stored in memory, preventing the compiler from picking it apart // picking it apart and putting into registers. i.e. if we pass it as reference,
// and putting into registers. i.e. if we pass it as reference, it gets slow. // it gets slow.
// This is what forces the skip_double, as well. double d;
error_code error = slow_float_parsing(src, writer); error_code error = slow_float_parsing(src, &d);
writer.skip_double(); writer.append_double(d);
return error; return error;
} }
// NOTE: it's weird that the simdjson_unlikely() only wraps half the if, but it seems to get slower any other // NOTE: it's weird that the simdjson_unlikely() only wraps half the if, but it seems to get slower any other
@@ -19226,11 +19243,8 @@ simdjson_inline size_t significant_digits(const uint8_t * start_digits, size_t d
} // unnamed namespace } // unnamed namespace
/** @private */ /** @private */
template<typename W> static error_code slow_float_parsing(simdjson_unused const uint8_t * src, double* answer) {
error_code slow_float_parsing(simdjson_unused const uint8_t * src, W writer) { if (parse_float_fallback(src, answer)) {
double d;
if (parse_float_fallback(src, &d)) {
writer.append_double(d);
return SUCCESS; return SUCCESS;
} }
return INVALID_NUMBER(src); return INVALID_NUMBER(src);
@@ -19254,13 +19268,13 @@ simdjson_inline error_code write_float(const uint8_t *const src, bool negative,
// 10000000000000000000000000000000000000000000e+308 // 10000000000000000000000000000000000000000000e+308
// 3.1415926535897932384626433832795028841971693993751 // 3.1415926535897932384626433832795028841971693993751
// //
// NOTE: This makes a *copy* of the writer and passes it to slow_float_parsing. This happens // NOTE: We do not pass a reference to the to slow_float_parsing. If we passed our writer
// because slow_float_parsing is a non-inlined function. If we passed our writer reference to // reference to it, it would force it to be stored in memory, preventing the compiler from
// it, it would force it to be stored in memory, preventing the compiler from picking it apart // picking it apart and putting into registers. i.e. if we pass it as reference,
// and putting into registers. i.e. if we pass it as reference, it gets slow. // it gets slow.
// This is what forces the skip_double, as well. double d;
error_code error = slow_float_parsing(src, writer); error_code error = slow_float_parsing(src, &d);
writer.skip_double(); writer.append_double(d);
return error; return error;
} }
// NOTE: it's weird that the simdjson_unlikely() only wraps half the if, but it seems to get slower any other // NOTE: it's weird that the simdjson_unlikely() only wraps half the if, but it seems to get slower any other
@@ -20930,7 +20944,7 @@ namespace simdjson {
namespace haswell { namespace haswell {
namespace { namespace {
simdjson_inline simd8<bool> must_be_2_3_continuation(const simd8<uint8_t> prev2, const simd8<uint8_t> prev3); simdjson_inline simd8<uint8_t> must_be_2_3_continuation(const simd8<uint8_t> prev2, const simd8<uint8_t> prev3);
simdjson_inline bool is_ascii(const simd8x64<uint8_t>& input); simdjson_inline bool is_ascii(const simd8x64<uint8_t>& input);
} // unnamed namespace } // unnamed namespace
@@ -21497,7 +21511,7 @@ using namespace simd;
const simd8<uint8_t> prev_input, const simd8<uint8_t> sc) { const simd8<uint8_t> prev_input, const simd8<uint8_t> sc) {
simd8<uint8_t> prev2 = input.prev<2>(prev_input); simd8<uint8_t> prev2 = input.prev<2>(prev_input);
simd8<uint8_t> prev3 = input.prev<3>(prev_input); simd8<uint8_t> prev3 = input.prev<3>(prev_input);
simd8<uint8_t> must23 = simd8<uint8_t>(must_be_2_3_continuation(prev2, prev3)); simd8<uint8_t> must23 = must_be_2_3_continuation(prev2, prev3);
simd8<uint8_t> must23_80 = must23 & uint8_t(0x80); simd8<uint8_t> must23_80 = must23 & uint8_t(0x80);
return must23_80 ^ sc; return must23_80 ^ sc;
} }
@@ -23689,11 +23703,10 @@ simdjson_unused simdjson_inline simd8<bool> must_be_continuation(const simd8<uin
return simd8<int8_t>(is_second_byte | is_third_byte | is_fourth_byte) > int8_t(0); return simd8<int8_t>(is_second_byte | is_third_byte | is_fourth_byte) > int8_t(0);
} }
simdjson_inline simd8<bool> must_be_2_3_continuation(const simd8<uint8_t> prev2, const simd8<uint8_t> prev3) { simdjson_inline simd8<uint8_t> must_be_2_3_continuation(const simd8<uint8_t> prev2, const simd8<uint8_t> prev3) {
simd8<uint8_t> is_third_byte = prev2.saturating_sub(0xe0u-1); // Only 111_____ will be > 0 simd8<uint8_t> is_third_byte = prev2.saturating_sub(0xe0u-0x80); // Only 111_____ will be >= 0x80
simd8<uint8_t> is_fourth_byte = prev3.saturating_sub(0xf0u-1); // Only 1111____ will be > 0 simd8<uint8_t> is_fourth_byte = prev3.saturating_sub(0xf0u-0x80); // Only 1111____ will be >= 0x80
// Caller requires a bool (all 1's). All values resulting from the subtraction will be <= 64, so signed comparison is fine. return is_third_byte | is_fourth_byte;
return simd8<int8_t>(is_third_byte | is_fourth_byte) > int8_t(0);
} }
} // unnamed namespace } // unnamed namespace
@@ -25390,11 +25403,8 @@ simdjson_inline size_t significant_digits(const uint8_t * start_digits, size_t d
} // unnamed namespace } // unnamed namespace
/** @private */ /** @private */
template<typename W> static error_code slow_float_parsing(simdjson_unused const uint8_t * src, double* answer) {
error_code slow_float_parsing(simdjson_unused const uint8_t * src, W writer) { if (parse_float_fallback(src, answer)) {
double d;
if (parse_float_fallback(src, &d)) {
writer.append_double(d);
return SUCCESS; return SUCCESS;
} }
return INVALID_NUMBER(src); return INVALID_NUMBER(src);
@@ -25418,13 +25428,13 @@ simdjson_inline error_code write_float(const uint8_t *const src, bool negative,
// 10000000000000000000000000000000000000000000e+308 // 10000000000000000000000000000000000000000000e+308
// 3.1415926535897932384626433832795028841971693993751 // 3.1415926535897932384626433832795028841971693993751
// //
// NOTE: This makes a *copy* of the writer and passes it to slow_float_parsing. This happens // NOTE: We do not pass a reference to the to slow_float_parsing. If we passed our writer
// because slow_float_parsing is a non-inlined function. If we passed our writer reference to // reference to it, it would force it to be stored in memory, preventing the compiler from
// it, it would force it to be stored in memory, preventing the compiler from picking it apart // picking it apart and putting into registers. i.e. if we pass it as reference,
// and putting into registers. i.e. if we pass it as reference, it gets slow. // it gets slow.
// This is what forces the skip_double, as well. double d;
error_code error = slow_float_parsing(src, writer); error_code error = slow_float_parsing(src, &d);
writer.skip_double(); writer.append_double(d);
return error; return error;
} }
// NOTE: it's weird that the simdjson_unlikely() only wraps half the if, but it seems to get slower any other // NOTE: it's weird that the simdjson_unlikely() only wraps half the if, but it seems to get slower any other
@@ -27092,7 +27102,7 @@ namespace simdjson {
namespace icelake { namespace icelake {
namespace { namespace {
simdjson_inline simd8<bool> must_be_2_3_continuation(const simd8<uint8_t> prev2, const simd8<uint8_t> prev3); simdjson_inline simd8<uint8_t> must_be_2_3_continuation(const simd8<uint8_t> prev2, const simd8<uint8_t> prev3);
simdjson_inline bool is_ascii(const simd8x64<uint8_t>& input); simdjson_inline bool is_ascii(const simd8x64<uint8_t>& input);
} // unnamed namespace } // unnamed namespace
@@ -27659,7 +27669,7 @@ using namespace simd;
const simd8<uint8_t> prev_input, const simd8<uint8_t> sc) { const simd8<uint8_t> prev_input, const simd8<uint8_t> sc) {
simd8<uint8_t> prev2 = input.prev<2>(prev_input); simd8<uint8_t> prev2 = input.prev<2>(prev_input);
simd8<uint8_t> prev3 = input.prev<3>(prev_input); simd8<uint8_t> prev3 = input.prev<3>(prev_input);
simd8<uint8_t> must23 = simd8<uint8_t>(must_be_2_3_continuation(prev2, prev3)); simd8<uint8_t> must23 = must_be_2_3_continuation(prev2, prev3);
simd8<uint8_t> must23_80 = must23 & uint8_t(0x80); simd8<uint8_t> must23_80 = must23 & uint8_t(0x80);
return must23_80 ^ sc; return must23_80 ^ sc;
} }
@@ -29850,11 +29860,10 @@ simdjson_unused simdjson_inline simd8<bool> must_be_continuation(const simd8<uin
return simd8<int8_t>(is_second_byte | is_third_byte | is_fourth_byte) > int8_t(0); return simd8<int8_t>(is_second_byte | is_third_byte | is_fourth_byte) > int8_t(0);
} }
simdjson_inline simd8<bool> must_be_2_3_continuation(const simd8<uint8_t> prev2, const simd8<uint8_t> prev3) { simdjson_inline simd8<uint8_t> must_be_2_3_continuation(const simd8<uint8_t> prev2, const simd8<uint8_t> prev3) {
simd8<uint8_t> is_third_byte = prev2.saturating_sub(0xe0u-1); // Only 111_____ will be > 0 simd8<uint8_t> is_third_byte = prev2.saturating_sub(0xe0u-0x80); // Only 111_____ will be >= 0x80
simd8<uint8_t> is_fourth_byte = prev3.saturating_sub(0xf0u-1); // Only 1111____ will be > 0 simd8<uint8_t> is_fourth_byte = prev3.saturating_sub(0xf0u-0x80); // Only 1111____ will be >= 0x80
// Caller requires a bool (all 1's). All values resulting from the subtraction will be <= 64, so signed comparison is fine. return is_third_byte | is_fourth_byte;
return simd8<int8_t>(is_third_byte | is_fourth_byte) > int8_t(0);
} }
} // unnamed namespace } // unnamed namespace
@@ -31710,11 +31719,8 @@ simdjson_inline size_t significant_digits(const uint8_t * start_digits, size_t d
} // unnamed namespace } // unnamed namespace
/** @private */ /** @private */
template<typename W> static error_code slow_float_parsing(simdjson_unused const uint8_t * src, double* answer) {
error_code slow_float_parsing(simdjson_unused const uint8_t * src, W writer) { if (parse_float_fallback(src, answer)) {
double d;
if (parse_float_fallback(src, &d)) {
writer.append_double(d);
return SUCCESS; return SUCCESS;
} }
return INVALID_NUMBER(src); return INVALID_NUMBER(src);
@@ -31738,13 +31744,13 @@ simdjson_inline error_code write_float(const uint8_t *const src, bool negative,
// 10000000000000000000000000000000000000000000e+308 // 10000000000000000000000000000000000000000000e+308
// 3.1415926535897932384626433832795028841971693993751 // 3.1415926535897932384626433832795028841971693993751
// //
// NOTE: This makes a *copy* of the writer and passes it to slow_float_parsing. This happens // NOTE: We do not pass a reference to the to slow_float_parsing. If we passed our writer
// because slow_float_parsing is a non-inlined function. If we passed our writer reference to // reference to it, it would force it to be stored in memory, preventing the compiler from
// it, it would force it to be stored in memory, preventing the compiler from picking it apart // picking it apart and putting into registers. i.e. if we pass it as reference,
// and putting into registers. i.e. if we pass it as reference, it gets slow. // it gets slow.
// This is what forces the skip_double, as well. double d;
error_code error = slow_float_parsing(src, writer); error_code error = slow_float_parsing(src, &d);
writer.skip_double(); writer.append_double(d);
return error; return error;
} }
// NOTE: it's weird that the simdjson_unlikely() only wraps half the if, but it seems to get slower any other // NOTE: it's weird that the simdjson_unlikely() only wraps half the if, but it seems to get slower any other
@@ -33525,7 +33531,7 @@ namespace simdjson {
namespace ppc64 { namespace ppc64 {
namespace { namespace {
simdjson_inline simd8<bool> must_be_2_3_continuation(const simd8<uint8_t> prev2, const simd8<uint8_t> prev3); simdjson_inline simd8<uint8_t> must_be_2_3_continuation(const simd8<uint8_t> prev2, const simd8<uint8_t> prev3);
simdjson_inline bool is_ascii(const simd8x64<uint8_t>& input); simdjson_inline bool is_ascii(const simd8x64<uint8_t>& input);
} // unnamed namespace } // unnamed namespace
@@ -34092,7 +34098,7 @@ using namespace simd;
const simd8<uint8_t> prev_input, const simd8<uint8_t> sc) { const simd8<uint8_t> prev_input, const simd8<uint8_t> sc) {
simd8<uint8_t> prev2 = input.prev<2>(prev_input); simd8<uint8_t> prev2 = input.prev<2>(prev_input);
simd8<uint8_t> prev3 = input.prev<3>(prev_input); simd8<uint8_t> prev3 = input.prev<3>(prev_input);
simd8<uint8_t> must23 = simd8<uint8_t>(must_be_2_3_continuation(prev2, prev3)); simd8<uint8_t> must23 = must_be_2_3_continuation(prev2, prev3);
simd8<uint8_t> must23_80 = must23 & uint8_t(0x80); simd8<uint8_t> must23_80 = must23 & uint8_t(0x80);
return must23_80 ^ sc; return must23_80 ^ sc;
} }
@@ -36257,11 +36263,10 @@ simdjson_unused simdjson_inline simd8<bool> must_be_continuation(const simd8<uin
return simd8<int8_t>(is_second_byte | is_third_byte | is_fourth_byte) > int8_t(0); return simd8<int8_t>(is_second_byte | is_third_byte | is_fourth_byte) > int8_t(0);
} }
simdjson_inline simd8<bool> must_be_2_3_continuation(const simd8<uint8_t> prev2, const simd8<uint8_t> prev3) { simdjson_inline simd8<uint8_t> must_be_2_3_continuation(const simd8<uint8_t> prev2, const simd8<uint8_t> prev3) {
simd8<uint8_t> is_third_byte = prev2.saturating_sub(0xe0u-1); // Only 111_____ will be > 0 simd8<uint8_t> is_third_byte = prev2.saturating_sub(0xe0u-0x80); // Only 111_____ will be >= 0x80
simd8<uint8_t> is_fourth_byte = prev3.saturating_sub(0xf0u-1); // Only 1111____ will be > 0 simd8<uint8_t> is_fourth_byte = prev3.saturating_sub(0xf0u-0x80); // Only 1111____ will be >= 0x80
// Caller requires a bool (all 1's). All values resulting from the subtraction will be <= 64, so signed comparison is fine. return is_third_byte | is_fourth_byte;
return simd8<int8_t>(is_third_byte | is_fourth_byte) > int8_t(0);
} }
} // unnamed namespace } // unnamed namespace
@@ -38396,11 +38401,8 @@ simdjson_inline size_t significant_digits(const uint8_t * start_digits, size_t d
} // unnamed namespace } // unnamed namespace
/** @private */ /** @private */
template<typename W> static error_code slow_float_parsing(simdjson_unused const uint8_t * src, double* answer) {
error_code slow_float_parsing(simdjson_unused const uint8_t * src, W writer) { if (parse_float_fallback(src, answer)) {
double d;
if (parse_float_fallback(src, &d)) {
writer.append_double(d);
return SUCCESS; return SUCCESS;
} }
return INVALID_NUMBER(src); return INVALID_NUMBER(src);
@@ -38424,13 +38426,13 @@ simdjson_inline error_code write_float(const uint8_t *const src, bool negative,
// 10000000000000000000000000000000000000000000e+308 // 10000000000000000000000000000000000000000000e+308
// 3.1415926535897932384626433832795028841971693993751 // 3.1415926535897932384626433832795028841971693993751
// //
// NOTE: This makes a *copy* of the writer and passes it to slow_float_parsing. This happens // NOTE: We do not pass a reference to the to slow_float_parsing. If we passed our writer
// because slow_float_parsing is a non-inlined function. If we passed our writer reference to // reference to it, it would force it to be stored in memory, preventing the compiler from
// it, it would force it to be stored in memory, preventing the compiler from picking it apart // picking it apart and putting into registers. i.e. if we pass it as reference,
// and putting into registers. i.e. if we pass it as reference, it gets slow. // it gets slow.
// This is what forces the skip_double, as well. double d;
error_code error = slow_float_parsing(src, writer); error_code error = slow_float_parsing(src, &d);
writer.skip_double(); writer.append_double(d);
return error; return error;
} }
// NOTE: it's weird that the simdjson_unlikely() only wraps half the if, but it seems to get slower any other // NOTE: it's weird that the simdjson_unlikely() only wraps half the if, but it seems to get slower any other
@@ -40532,7 +40534,7 @@ namespace simdjson {
namespace westmere { namespace westmere {
namespace { namespace {
simdjson_inline simd8<bool> must_be_2_3_continuation(const simd8<uint8_t> prev2, const simd8<uint8_t> prev3); simdjson_inline simd8<uint8_t> must_be_2_3_continuation(const simd8<uint8_t> prev2, const simd8<uint8_t> prev3);
simdjson_inline bool is_ascii(const simd8x64<uint8_t>& input); simdjson_inline bool is_ascii(const simd8x64<uint8_t>& input);
} // unnamed namespace } // unnamed namespace
@@ -41099,7 +41101,7 @@ using namespace simd;
const simd8<uint8_t> prev_input, const simd8<uint8_t> sc) { const simd8<uint8_t> prev_input, const simd8<uint8_t> sc) {
simd8<uint8_t> prev2 = input.prev<2>(prev_input); simd8<uint8_t> prev2 = input.prev<2>(prev_input);
simd8<uint8_t> prev3 = input.prev<3>(prev_input); simd8<uint8_t> prev3 = input.prev<3>(prev_input);
simd8<uint8_t> must23 = simd8<uint8_t>(must_be_2_3_continuation(prev2, prev3)); simd8<uint8_t> must23 = must_be_2_3_continuation(prev2, prev3);
simd8<uint8_t> must23_80 = must23 & uint8_t(0x80); simd8<uint8_t> must23_80 = must23 & uint8_t(0x80);
return must23_80 ^ sc; return must23_80 ^ sc;
} }
@@ -43295,11 +43297,10 @@ simdjson_unused simdjson_inline simd8<bool> must_be_continuation(const simd8<uin
return simd8<int8_t>(is_second_byte | is_third_byte | is_fourth_byte) > int8_t(0); return simd8<int8_t>(is_second_byte | is_third_byte | is_fourth_byte) > int8_t(0);
} }
simdjson_inline simd8<bool> must_be_2_3_continuation(const simd8<uint8_t> prev2, const simd8<uint8_t> prev3) { simdjson_inline simd8<uint8_t> must_be_2_3_continuation(const simd8<uint8_t> prev2, const simd8<uint8_t> prev3) {
simd8<uint8_t> is_third_byte = prev2.saturating_sub(0xe0u-1); // Only 111_____ will be > 0 simd8<uint8_t> is_third_byte = prev2.saturating_sub(0xe0u-0x80); // Only 111_____ will be >= 0x80
simd8<uint8_t> is_fourth_byte = prev3.saturating_sub(0xf0u-1); // Only 1111____ will be > 0 simd8<uint8_t> is_fourth_byte = prev3.saturating_sub(0xf0u-0x80); // Only 1111____ will be >= 0x80
// Caller requires a bool (all 1's). All values resulting from the subtraction will be <= 64, so signed comparison is fine. return is_third_byte | is_fourth_byte;
return simd8<int8_t>(is_third_byte | is_fourth_byte) > int8_t(0);
} }
} // unnamed namespace } // unnamed namespace
+141 -97
View File
@@ -1,4 +1,4 @@
/* auto-generated on 2023-12-07 12:42:28 -0500. Do not edit! */ /* auto-generated on 2024-01-28 12:42:59 -0500. Do not edit! */
/* including simdjson.h: */ /* including simdjson.h: */
/* begin file simdjson.h */ /* begin file simdjson.h */
#ifndef SIMDJSON_H #ifndef SIMDJSON_H
@@ -545,7 +545,7 @@ SIMDJSON_PUSH_DISABLE_ALL_WARNINGS
// Distributed under the Boost Software License, Version 1.0. // Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#pragma once // #pragma once // We remove #pragma once here as it generates a warning in some cases. We rely on the include guard.
#ifndef NONSTD_SV_LITE_H_INCLUDED #ifndef NONSTD_SV_LITE_H_INCLUDED
#define NONSTD_SV_LITE_H_INCLUDED #define NONSTD_SV_LITE_H_INCLUDED
@@ -608,6 +608,10 @@ SIMDJSON_PUSH_DISABLE_ALL_WARNINGS
# define nssv_CONFIG_NO_STREAM_INSERTION 0 # define nssv_CONFIG_NO_STREAM_INSERTION 0
#endif #endif
#ifndef nssv_CONFIG_CONSTEXPR11_STD_SEARCH
# define nssv_CONFIG_CONSTEXPR11_STD_SEARCH 1
#endif
// Control presence of exception handling (try and auto discover): // Control presence of exception handling (try and auto discover):
#ifndef nssv_CONFIG_NO_EXCEPTIONS #ifndef nssv_CONFIG_NO_EXCEPTIONS
@@ -806,7 +810,7 @@ using std::operator<<;
# define nssv_HAS_CPP0X 0 # define nssv_HAS_CPP0X 0
#endif #endif
// Unless defined otherwise below, consider VC14 as C++11 for variant-lite: // Unless defined otherwise below, consider VC14 as C++11 for string-view-lite:
#if nssv_COMPILER_MSVC_VER >= 1900 #if nssv_COMPILER_MSVC_VER >= 1900
# undef nssv_CPP11_OR_GREATER # undef nssv_CPP11_OR_GREATER
@@ -973,9 +977,9 @@ using std::operator<<;
# pragma clang diagnostic ignored "-Wreserved-user-defined-literal" # pragma clang diagnostic ignored "-Wreserved-user-defined-literal"
# pragma clang diagnostic push # pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wuser-defined-literals" # pragma clang diagnostic ignored "-Wuser-defined-literals"
#elif defined(__GNUC__) #elif nssv_COMPILER_GNUC_VERSION >= 480
# pragma GCC diagnostic push # pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wliteral-suffix" # pragma GCC diagnostic ignored "-Wliteral-suffix"
#endif // __clang__ #endif // __clang__
#if nssv_COMPILER_MSVC_VERSION >= 140 #if nssv_COMPILER_MSVC_VERSION >= 140
@@ -990,8 +994,8 @@ using std::operator<<;
#if defined(__clang__) #if defined(__clang__)
# define nssv_RESTORE_WARNINGS() _Pragma("clang diagnostic pop") # define nssv_RESTORE_WARNINGS() _Pragma("clang diagnostic pop")
#elif defined(__GNUC__) #elif nssv_COMPILER_GNUC_VERSION >= 480
# define nssv_RESTORE_WARNINGS() _Pragma("GCC diagnostic pop") # define nssv_RESTORE_WARNINGS() _Pragma("GCC diagnostic pop")
#elif nssv_COMPILER_MSVC_VERSION >= 140 #elif nssv_COMPILER_MSVC_VERSION >= 140
# define nssv_RESTORE_WARNINGS() __pragma(warning(pop )) # define nssv_RESTORE_WARNINGS() __pragma(warning(pop ))
#else #else
@@ -1106,12 +1110,31 @@ constexpr const CharT* search( basic_string_view<CharT, Traits> haystack, basic_
// non-recursive: // non-recursive:
#if nssv_CONFIG_CONSTEXPR11_STD_SEARCH
template< class CharT, class Traits = std::char_traits<CharT> > template< class CharT, class Traits = std::char_traits<CharT> >
constexpr const CharT* search( basic_string_view<CharT, Traits> haystack, basic_string_view<CharT, Traits> needle ) constexpr const CharT* search( basic_string_view<CharT, Traits> haystack, basic_string_view<CharT, Traits> needle )
{ {
return std::search( haystack.begin(), haystack.end(), needle.begin(), needle.end() ); return std::search( haystack.begin(), haystack.end(), needle.begin(), needle.end() );
} }
#else // nssv_CONFIG_CONSTEXPR11_STD_SEARCH
template< class CharT, class Traits = std::char_traits<CharT> >
nssv_constexpr14 const CharT* search( basic_string_view<CharT, Traits> haystack, basic_string_view<CharT, Traits> needle )
{
while ( needle.size() <= haystack.size() )
{
if ( haystack.starts_with(needle) )
{
return haystack.cbegin();
}
haystack = basic_string_view<CharT, Traits>{ haystack.begin() + 1, haystack.size() - 1U };
}
return haystack.cend();
}
#endif // nssv_CONFIG_CONSTEXPR11_STD_SEARCH
#endif // OPTIMIZE #endif // OPTIMIZE
#endif // nssv_CPP11_OR_GREATER && ! nssv_CPP17_OR_GREATER #endif // nssv_CPP11_OR_GREATER && ! nssv_CPP17_OR_GREATER
@@ -1384,7 +1407,7 @@ public:
// find(), 4x: // find(), 4x:
nssv_constexpr size_type find( basic_string_view v, size_type pos = 0 ) const nssv_noexcept // (1) nssv_constexpr14 size_type find( basic_string_view v, size_type pos = 0 ) const nssv_noexcept // (1)
{ {
return assert( v.size() == 0 || v.data() != nssv_nullptr ) return assert( v.size() == 0 || v.data() != nssv_nullptr )
, pos >= size() , pos >= size()
@@ -2321,7 +2344,7 @@ namespace std {
#define SIMDJSON_SIMDJSON_VERSION_H #define SIMDJSON_SIMDJSON_VERSION_H
/** The version of simdjson being used (major.minor.revision) */ /** The version of simdjson being used (major.minor.revision) */
#define SIMDJSON_VERSION "3.6.3" #define SIMDJSON_VERSION "3.6.4"
namespace simdjson { namespace simdjson {
enum { enum {
@@ -2336,7 +2359,7 @@ enum {
/** /**
* The revision (major.minor.REVISION) of simdjson being used. * The revision (major.minor.REVISION) of simdjson being used.
*/ */
SIMDJSON_VERSION_REVISION = 3 SIMDJSON_VERSION_REVISION = 4
}; };
} // namespace simdjson } // namespace simdjson
@@ -4449,6 +4472,53 @@ public:
*/ */
inline simdjson_result<element> load(const std::string &path) & noexcept; inline simdjson_result<element> load(const std::string &path) & noexcept;
inline simdjson_result<element> load(const std::string &path) && = delete ; inline simdjson_result<element> load(const std::string &path) && = delete ;
/**
* Load a JSON document from a file into a provide document instance and return a temporary reference to it.
* It is similar to the function `load` except that instead of parsing into the internal
* `document` instance associated with the parser, it allows the user to provide a document
* instance.
*
* dom::parser parser;
* dom::document doc;
* element doc_root = parser.load_into_document(doc, "jsonexamples/twitter.json");
*
* The function is eager: the file's content is loaded in memory inside the parser instance
* and immediately parsed. The file can be deleted after the `parser.load_into_document` call.
*
* ### IMPORTANT: Document Lifetime
*
* After the call to load_into_document, the parser is no longer needed.
*
* The JSON document lives in the document instance: you must keep the document
* instance alive while you navigate through it (i.e., used the returned value from
* load_into_document). You are encourage to reuse the document instance
* many times with new data to avoid reallocations:
*
* dom::document doc;
* element doc_root1 = parser.load_into_document(doc, "jsonexamples/twitter.json");
* //... doc_root1 is a pointer inside doc
* element doc_root2 = parser.load_into_document(doc, "jsonexamples/twitter.json");
* //... doc_root2 is a pointer inside doc
* // at this point doc_root1 is no longer safe
*
* Moving the document instance is safe, but it invalidates the element instances. After
* moving a document, you can recover safe access to the document root with its `root()` method.
*
* @param doc The document instance where the parsed data will be stored (on success).
* @param path The path to load.
* @return The document, or an error:
* - IO_ERROR if there was an error opening or reading the file.
* Be mindful that on some 32-bit systems,
* the file size might be limited to 2 GB.
* - MEMALLOC if the parser does not have enough capacity and memory allocation fails.
* - CAPACITY if the parser does not have enough capacity and len > max_capacity.
* - other json errors if parsing fails. You should not rely on these errors to always the same for the
* same document: they may vary under runtime dispatch (so they may vary depending on your system and hardware).
*/
inline simdjson_result<element> load_into_document(document& doc, const std::string &path) & noexcept;
inline simdjson_result<element> load_into_document(document& doc, const std::string &path) && =delete;
/** /**
* Parse a JSON document and return a temporary reference to it. * Parse a JSON document and return a temporary reference to it.
* *
@@ -5484,7 +5554,7 @@ public:
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), " "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). " "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(), " "We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), "
"get_object(), get_array() or get_string() instead of the get template."); "get_object(), get_array() or get_string() instead of the get template.");
} }
@@ -7556,10 +7626,14 @@ inline simdjson_result<size_t> parser::read_file(const std::string &path) noexce
} }
inline simdjson_result<element> parser::load(const std::string &path) & noexcept { inline simdjson_result<element> parser::load(const std::string &path) & noexcept {
return load_into_document(doc, path);
}
inline simdjson_result<element> parser::load_into_document(document& provided_doc, const std::string &path) & noexcept {
size_t len; size_t len;
auto _error = read_file(path).get(len); auto _error = read_file(path).get(len);
if (_error) { return _error; } if (_error) { return _error; }
return parse(loaded_bytes.get(), len, false); return parse_into_document(provided_doc, loaded_bytes.get(), len, false);
} }
inline simdjson_result<document_stream> parser::load_many(const std::string &path, size_t batch_size) noexcept { inline simdjson_result<document_stream> parser::load_many(const std::string &path, size_t batch_size) noexcept {
@@ -12109,11 +12183,8 @@ simdjson_inline size_t significant_digits(const uint8_t * start_digits, size_t d
} // unnamed namespace } // unnamed namespace
/** @private */ /** @private */
template<typename W> static error_code slow_float_parsing(simdjson_unused const uint8_t * src, double* answer) {
error_code slow_float_parsing(simdjson_unused const uint8_t * src, W writer) { if (parse_float_fallback(src, answer)) {
double d;
if (parse_float_fallback(src, &d)) {
writer.append_double(d);
return SUCCESS; return SUCCESS;
} }
return INVALID_NUMBER(src); return INVALID_NUMBER(src);
@@ -12137,13 +12208,13 @@ simdjson_inline error_code write_float(const uint8_t *const src, bool negative,
// 10000000000000000000000000000000000000000000e+308 // 10000000000000000000000000000000000000000000e+308
// 3.1415926535897932384626433832795028841971693993751 // 3.1415926535897932384626433832795028841971693993751
// //
// NOTE: This makes a *copy* of the writer and passes it to slow_float_parsing. This happens // NOTE: We do not pass a reference to the to slow_float_parsing. If we passed our writer
// because slow_float_parsing is a non-inlined function. If we passed our writer reference to // reference to it, it would force it to be stored in memory, preventing the compiler from
// it, it would force it to be stored in memory, preventing the compiler from picking it apart // picking it apart and putting into registers. i.e. if we pass it as reference,
// and putting into registers. i.e. if we pass it as reference, it gets slow. // it gets slow.
// This is what forces the skip_double, as well. double d;
error_code error = slow_float_parsing(src, writer); error_code error = slow_float_parsing(src, &d);
writer.skip_double(); writer.append_double(d);
return error; return error;
} }
// NOTE: it's weird that the simdjson_unlikely() only wraps half the if, but it seems to get slower any other // NOTE: it's weird that the simdjson_unlikely() only wraps half the if, but it seems to get slower any other
@@ -14161,11 +14232,8 @@ simdjson_inline size_t significant_digits(const uint8_t * start_digits, size_t d
} // unnamed namespace } // unnamed namespace
/** @private */ /** @private */
template<typename W> static error_code slow_float_parsing(simdjson_unused const uint8_t * src, double* answer) {
error_code slow_float_parsing(simdjson_unused const uint8_t * src, W writer) { if (parse_float_fallback(src, answer)) {
double d;
if (parse_float_fallback(src, &d)) {
writer.append_double(d);
return SUCCESS; return SUCCESS;
} }
return INVALID_NUMBER(src); return INVALID_NUMBER(src);
@@ -14189,13 +14257,13 @@ simdjson_inline error_code write_float(const uint8_t *const src, bool negative,
// 10000000000000000000000000000000000000000000e+308 // 10000000000000000000000000000000000000000000e+308
// 3.1415926535897932384626433832795028841971693993751 // 3.1415926535897932384626433832795028841971693993751
// //
// NOTE: This makes a *copy* of the writer and passes it to slow_float_parsing. This happens // NOTE: We do not pass a reference to the to slow_float_parsing. If we passed our writer
// because slow_float_parsing is a non-inlined function. If we passed our writer reference to // reference to it, it would force it to be stored in memory, preventing the compiler from
// it, it would force it to be stored in memory, preventing the compiler from picking it apart // picking it apart and putting into registers. i.e. if we pass it as reference,
// and putting into registers. i.e. if we pass it as reference, it gets slow. // it gets slow.
// This is what forces the skip_double, as well. double d;
error_code error = slow_float_parsing(src, writer); error_code error = slow_float_parsing(src, &d);
writer.skip_double(); writer.append_double(d);
return error; return error;
} }
// NOTE: it's weird that the simdjson_unlikely() only wraps half the if, but it seems to get slower any other // NOTE: it's weird that the simdjson_unlikely() only wraps half the if, but it seems to get slower any other
@@ -16705,11 +16773,8 @@ simdjson_inline size_t significant_digits(const uint8_t * start_digits, size_t d
} // unnamed namespace } // unnamed namespace
/** @private */ /** @private */
template<typename W> static error_code slow_float_parsing(simdjson_unused const uint8_t * src, double* answer) {
error_code slow_float_parsing(simdjson_unused const uint8_t * src, W writer) { if (parse_float_fallback(src, answer)) {
double d;
if (parse_float_fallback(src, &d)) {
writer.append_double(d);
return SUCCESS; return SUCCESS;
} }
return INVALID_NUMBER(src); return INVALID_NUMBER(src);
@@ -16733,13 +16798,13 @@ simdjson_inline error_code write_float(const uint8_t *const src, bool negative,
// 10000000000000000000000000000000000000000000e+308 // 10000000000000000000000000000000000000000000e+308
// 3.1415926535897932384626433832795028841971693993751 // 3.1415926535897932384626433832795028841971693993751
// //
// NOTE: This makes a *copy* of the writer and passes it to slow_float_parsing. This happens // NOTE: We do not pass a reference to the to slow_float_parsing. If we passed our writer
// because slow_float_parsing is a non-inlined function. If we passed our writer reference to // reference to it, it would force it to be stored in memory, preventing the compiler from
// it, it would force it to be stored in memory, preventing the compiler from picking it apart // picking it apart and putting into registers. i.e. if we pass it as reference,
// and putting into registers. i.e. if we pass it as reference, it gets slow. // it gets slow.
// This is what forces the skip_double, as well. double d;
error_code error = slow_float_parsing(src, writer); error_code error = slow_float_parsing(src, &d);
writer.skip_double(); writer.append_double(d);
return error; return error;
} }
// NOTE: it's weird that the simdjson_unlikely() only wraps half the if, but it seems to get slower any other // NOTE: it's weird that the simdjson_unlikely() only wraps half the if, but it seems to get slower any other
@@ -19248,11 +19313,8 @@ simdjson_inline size_t significant_digits(const uint8_t * start_digits, size_t d
} // unnamed namespace } // unnamed namespace
/** @private */ /** @private */
template<typename W> static error_code slow_float_parsing(simdjson_unused const uint8_t * src, double* answer) {
error_code slow_float_parsing(simdjson_unused const uint8_t * src, W writer) { if (parse_float_fallback(src, answer)) {
double d;
if (parse_float_fallback(src, &d)) {
writer.append_double(d);
return SUCCESS; return SUCCESS;
} }
return INVALID_NUMBER(src); return INVALID_NUMBER(src);
@@ -19276,13 +19338,13 @@ simdjson_inline error_code write_float(const uint8_t *const src, bool negative,
// 10000000000000000000000000000000000000000000e+308 // 10000000000000000000000000000000000000000000e+308
// 3.1415926535897932384626433832795028841971693993751 // 3.1415926535897932384626433832795028841971693993751
// //
// NOTE: This makes a *copy* of the writer and passes it to slow_float_parsing. This happens // NOTE: We do not pass a reference to the to slow_float_parsing. If we passed our writer
// because slow_float_parsing is a non-inlined function. If we passed our writer reference to // reference to it, it would force it to be stored in memory, preventing the compiler from
// it, it would force it to be stored in memory, preventing the compiler from picking it apart // picking it apart and putting into registers. i.e. if we pass it as reference,
// and putting into registers. i.e. if we pass it as reference, it gets slow. // it gets slow.
// This is what forces the skip_double, as well. double d;
error_code error = slow_float_parsing(src, writer); error_code error = slow_float_parsing(src, &d);
writer.skip_double(); writer.append_double(d);
return error; return error;
} }
// NOTE: it's weird that the simdjson_unlikely() only wraps half the if, but it seems to get slower any other // NOTE: it's weird that the simdjson_unlikely() only wraps half the if, but it seems to get slower any other
@@ -21906,11 +21968,8 @@ simdjson_inline size_t significant_digits(const uint8_t * start_digits, size_t d
} // unnamed namespace } // unnamed namespace
/** @private */ /** @private */
template<typename W> static error_code slow_float_parsing(simdjson_unused const uint8_t * src, double* answer) {
error_code slow_float_parsing(simdjson_unused const uint8_t * src, W writer) { if (parse_float_fallback(src, answer)) {
double d;
if (parse_float_fallback(src, &d)) {
writer.append_double(d);
return SUCCESS; return SUCCESS;
} }
return INVALID_NUMBER(src); return INVALID_NUMBER(src);
@@ -21934,13 +21993,13 @@ simdjson_inline error_code write_float(const uint8_t *const src, bool negative,
// 10000000000000000000000000000000000000000000e+308 // 10000000000000000000000000000000000000000000e+308
// 3.1415926535897932384626433832795028841971693993751 // 3.1415926535897932384626433832795028841971693993751
// //
// NOTE: This makes a *copy* of the writer and passes it to slow_float_parsing. This happens // NOTE: We do not pass a reference to the to slow_float_parsing. If we passed our writer
// because slow_float_parsing is a non-inlined function. If we passed our writer reference to // reference to it, it would force it to be stored in memory, preventing the compiler from
// it, it would force it to be stored in memory, preventing the compiler from picking it apart // picking it apart and putting into registers. i.e. if we pass it as reference,
// and putting into registers. i.e. if we pass it as reference, it gets slow. // it gets slow.
// This is what forces the skip_double, as well. double d;
error_code error = slow_float_parsing(src, writer); error_code error = slow_float_parsing(src, &d);
writer.skip_double(); writer.append_double(d);
return error; return error;
} }
// NOTE: it's weird that the simdjson_unlikely() only wraps half the if, but it seems to get slower any other // NOTE: it's weird that the simdjson_unlikely() only wraps half the if, but it seems to get slower any other
@@ -24887,11 +24946,8 @@ simdjson_inline size_t significant_digits(const uint8_t * start_digits, size_t d
} // unnamed namespace } // unnamed namespace
/** @private */ /** @private */
template<typename W> static error_code slow_float_parsing(simdjson_unused const uint8_t * src, double* answer) {
error_code slow_float_parsing(simdjson_unused const uint8_t * src, W writer) { if (parse_float_fallback(src, answer)) {
double d;
if (parse_float_fallback(src, &d)) {
writer.append_double(d);
return SUCCESS; return SUCCESS;
} }
return INVALID_NUMBER(src); return INVALID_NUMBER(src);
@@ -24915,13 +24971,13 @@ simdjson_inline error_code write_float(const uint8_t *const src, bool negative,
// 10000000000000000000000000000000000000000000e+308 // 10000000000000000000000000000000000000000000e+308
// 3.1415926535897932384626433832795028841971693993751 // 3.1415926535897932384626433832795028841971693993751
// //
// NOTE: This makes a *copy* of the writer and passes it to slow_float_parsing. This happens // NOTE: We do not pass a reference to the to slow_float_parsing. If we passed our writer
// because slow_float_parsing is a non-inlined function. If we passed our writer reference to // reference to it, it would force it to be stored in memory, preventing the compiler from
// it, it would force it to be stored in memory, preventing the compiler from picking it apart // picking it apart and putting into registers. i.e. if we pass it as reference,
// and putting into registers. i.e. if we pass it as reference, it gets slow. // it gets slow.
// This is what forces the skip_double, as well. double d;
error_code error = slow_float_parsing(src, writer); error_code error = slow_float_parsing(src, &d);
writer.skip_double(); writer.append_double(d);
return error; return error;
} }
// NOTE: it's weird that the simdjson_unlikely() only wraps half the if, but it seems to get slower any other // NOTE: it's weird that the simdjson_unlikely() only wraps half the if, but it seems to get slower any other
@@ -28613,8 +28669,6 @@ protected:
*/ */
friend class value_iterator; friend class value_iterator;
template<typename W> template<typename W>
friend error_code numberparsing::slow_float_parsing(simdjson_unused const uint8_t * src, W writer);
template<typename W>
friend error_code numberparsing::write_float(const uint8_t *const src, bool negative, uint64_t i, const uint8_t * start_digits, size_t digit_count, int64_t exponent, W &writer); friend error_code numberparsing::write_float(const uint8_t *const src, bool negative, uint64_t i, const uint8_t * start_digits, size_t digit_count, int64_t exponent, W &writer);
template<typename W> template<typename W>
friend error_code numberparsing::parse_number(const uint8_t *const src, W &writer); friend error_code numberparsing::parse_number(const uint8_t *const src, W &writer);
@@ -38534,8 +38588,6 @@ protected:
*/ */
friend class value_iterator; friend class value_iterator;
template<typename W> template<typename W>
friend error_code numberparsing::slow_float_parsing(simdjson_unused const uint8_t * src, W writer);
template<typename W>
friend error_code numberparsing::write_float(const uint8_t *const src, bool negative, uint64_t i, const uint8_t * start_digits, size_t digit_count, int64_t exponent, W &writer); friend error_code numberparsing::write_float(const uint8_t *const src, bool negative, uint64_t i, const uint8_t * start_digits, size_t digit_count, int64_t exponent, W &writer);
template<typename W> template<typename W>
friend error_code numberparsing::parse_number(const uint8_t *const src, W &writer); friend error_code numberparsing::parse_number(const uint8_t *const src, W &writer);
@@ -48947,8 +48999,6 @@ protected:
*/ */
friend class value_iterator; friend class value_iterator;
template<typename W> template<typename W>
friend error_code numberparsing::slow_float_parsing(simdjson_unused const uint8_t * src, W writer);
template<typename W>
friend error_code numberparsing::write_float(const uint8_t *const src, bool negative, uint64_t i, const uint8_t * start_digits, size_t digit_count, int64_t exponent, W &writer); friend error_code numberparsing::write_float(const uint8_t *const src, bool negative, uint64_t i, const uint8_t * start_digits, size_t digit_count, int64_t exponent, W &writer);
template<typename W> template<typename W>
friend error_code numberparsing::parse_number(const uint8_t *const src, W &writer); friend error_code numberparsing::parse_number(const uint8_t *const src, W &writer);
@@ -59359,8 +59409,6 @@ protected:
*/ */
friend class value_iterator; friend class value_iterator;
template<typename W> template<typename W>
friend error_code numberparsing::slow_float_parsing(simdjson_unused const uint8_t * src, W writer);
template<typename W>
friend error_code numberparsing::write_float(const uint8_t *const src, bool negative, uint64_t i, const uint8_t * start_digits, size_t digit_count, int64_t exponent, W &writer); friend error_code numberparsing::write_float(const uint8_t *const src, bool negative, uint64_t i, const uint8_t * start_digits, size_t digit_count, int64_t exponent, W &writer);
template<typename W> template<typename W>
friend error_code numberparsing::parse_number(const uint8_t *const src, W &writer); friend error_code numberparsing::parse_number(const uint8_t *const src, W &writer);
@@ -69886,8 +69934,6 @@ protected:
*/ */
friend class value_iterator; friend class value_iterator;
template<typename W> template<typename W>
friend error_code numberparsing::slow_float_parsing(simdjson_unused const uint8_t * src, W writer);
template<typename W>
friend error_code numberparsing::write_float(const uint8_t *const src, bool negative, uint64_t i, const uint8_t * start_digits, size_t digit_count, int64_t exponent, W &writer); friend error_code numberparsing::write_float(const uint8_t *const src, bool negative, uint64_t i, const uint8_t * start_digits, size_t digit_count, int64_t exponent, W &writer);
template<typename W> template<typename W>
friend error_code numberparsing::parse_number(const uint8_t *const src, W &writer); friend error_code numberparsing::parse_number(const uint8_t *const src, W &writer);
@@ -80736,8 +80782,6 @@ protected:
*/ */
friend class value_iterator; friend class value_iterator;
template<typename W> template<typename W>
friend error_code numberparsing::slow_float_parsing(simdjson_unused const uint8_t * src, W writer);
template<typename W>
friend error_code numberparsing::write_float(const uint8_t *const src, bool negative, uint64_t i, const uint8_t * start_digits, size_t digit_count, int64_t exponent, W &writer); friend error_code numberparsing::write_float(const uint8_t *const src, bool negative, uint64_t i, const uint8_t * start_digits, size_t digit_count, int64_t exponent, W &writer);
template<typename W> template<typename W>
friend error_code numberparsing::parse_number(const uint8_t *const src, W &writer); friend error_code numberparsing::parse_number(const uint8_t *const src, W &writer);
+4 -4
View File
@@ -108,10 +108,10 @@ simdjson_unused simdjson_inline simd8<bool> must_be_continuation(const simd8<uin
return is_second_byte ^ is_third_byte ^ is_fourth_byte; return is_second_byte ^ is_third_byte ^ is_fourth_byte;
} }
simdjson_inline simd8<bool> must_be_2_3_continuation(const simd8<uint8_t> prev2, const simd8<uint8_t> prev3) { simdjson_inline simd8<uint8_t> must_be_2_3_continuation(const simd8<uint8_t> prev2, const simd8<uint8_t> prev3) {
simd8<bool> is_third_byte = prev2 >= uint8_t(0xe0u); simd8<uint8_t> is_third_byte = prev2.saturating_sub(0xe0u-0x80); // Only 111_____ will be >= 0x80
simd8<bool> is_fourth_byte = prev3 >= uint8_t(0xf0u); simd8<uint8_t> is_fourth_byte = prev3.saturating_sub(0xf0u-0x80); // Only 1111____ will be >= 0x80
return is_third_byte ^ is_fourth_byte; return is_third_byte | is_fourth_byte;
} }
} // unnamed namespace } // unnamed namespace
+1 -1
View File
@@ -11,7 +11,7 @@ namespace simdjson {
namespace SIMDJSON_IMPLEMENTATION { namespace SIMDJSON_IMPLEMENTATION {
namespace { namespace {
simdjson_inline simd8<bool> must_be_2_3_continuation(const simd8<uint8_t> prev2, const simd8<uint8_t> prev3); simdjson_inline simd8<uint8_t> must_be_2_3_continuation(const simd8<uint8_t> prev2, const simd8<uint8_t> prev3);
simdjson_inline bool is_ascii(const simd8x64<uint8_t>& input); simdjson_inline bool is_ascii(const simd8x64<uint8_t>& input);
} // unnamed namespace } // unnamed namespace
+1 -1
View File
@@ -107,7 +107,7 @@ using namespace simd;
const simd8<uint8_t> prev_input, const simd8<uint8_t> sc) { const simd8<uint8_t> prev_input, const simd8<uint8_t> sc) {
simd8<uint8_t> prev2 = input.prev<2>(prev_input); simd8<uint8_t> prev2 = input.prev<2>(prev_input);
simd8<uint8_t> prev3 = input.prev<3>(prev_input); simd8<uint8_t> prev3 = input.prev<3>(prev_input);
simd8<uint8_t> must23 = simd8<uint8_t>(must_be_2_3_continuation(prev2, prev3)); simd8<uint8_t> must23 = must_be_2_3_continuation(prev2, prev3);
simd8<uint8_t> must23_80 = must23 & uint8_t(0x80); simd8<uint8_t> must23_80 = must23 & uint8_t(0x80);
return must23_80 ^ sc; return must23_80 ^ sc;
} }
+4 -5
View File
@@ -105,11 +105,10 @@ simdjson_unused simdjson_inline simd8<bool> must_be_continuation(const simd8<uin
return simd8<int8_t>(is_second_byte | is_third_byte | is_fourth_byte) > int8_t(0); return simd8<int8_t>(is_second_byte | is_third_byte | is_fourth_byte) > int8_t(0);
} }
simdjson_inline simd8<bool> must_be_2_3_continuation(const simd8<uint8_t> prev2, const simd8<uint8_t> prev3) { simdjson_inline simd8<uint8_t> must_be_2_3_continuation(const simd8<uint8_t> prev2, const simd8<uint8_t> prev3) {
simd8<uint8_t> is_third_byte = prev2.saturating_sub(0xe0u-1); // Only 111_____ will be > 0 simd8<uint8_t> is_third_byte = prev2.saturating_sub(0xe0u-0x80); // Only 111_____ will be >= 0x80
simd8<uint8_t> is_fourth_byte = prev3.saturating_sub(0xf0u-1); // Only 1111____ will be > 0 simd8<uint8_t> is_fourth_byte = prev3.saturating_sub(0xf0u-0x80); // Only 1111____ will be >= 0x80
// Caller requires a bool (all 1's). All values resulting from the subtraction will be <= 64, so signed comparison is fine. return is_third_byte | is_fourth_byte;
return simd8<int8_t>(is_third_byte | is_fourth_byte) > int8_t(0);
} }
} // unnamed namespace } // unnamed namespace
+4 -5
View File
@@ -107,11 +107,10 @@ simdjson_unused simdjson_inline simd8<bool> must_be_continuation(const simd8<uin
return simd8<int8_t>(is_second_byte | is_third_byte | is_fourth_byte) > int8_t(0); return simd8<int8_t>(is_second_byte | is_third_byte | is_fourth_byte) > int8_t(0);
} }
simdjson_inline simd8<bool> must_be_2_3_continuation(const simd8<uint8_t> prev2, const simd8<uint8_t> prev3) { simdjson_inline simd8<uint8_t> must_be_2_3_continuation(const simd8<uint8_t> prev2, const simd8<uint8_t> prev3) {
simd8<uint8_t> is_third_byte = prev2.saturating_sub(0xe0u-1); // Only 111_____ will be > 0 simd8<uint8_t> is_third_byte = prev2.saturating_sub(0xe0u-0x80); // Only 111_____ will be >= 0x80
simd8<uint8_t> is_fourth_byte = prev3.saturating_sub(0xf0u-1); // Only 1111____ will be > 0 simd8<uint8_t> is_fourth_byte = prev3.saturating_sub(0xf0u-0x80); // Only 1111____ will be >= 0x80
// Caller requires a bool (all 1's). All values resulting from the subtraction will be <= 64, so signed comparison is fine. return is_third_byte | is_fourth_byte;
return simd8<int8_t>(is_third_byte | is_fourth_byte) > int8_t(0);
} }
} // unnamed namespace } // unnamed namespace
+4 -5
View File
@@ -78,11 +78,10 @@ simdjson_unused simdjson_inline simd8<bool> must_be_continuation(const simd8<uin
return simd8<int8_t>(is_second_byte | is_third_byte | is_fourth_byte) > int8_t(0); return simd8<int8_t>(is_second_byte | is_third_byte | is_fourth_byte) > int8_t(0);
} }
simdjson_inline simd8<bool> must_be_2_3_continuation(const simd8<uint8_t> prev2, const simd8<uint8_t> prev3) { simdjson_inline simd8<uint8_t> must_be_2_3_continuation(const simd8<uint8_t> prev2, const simd8<uint8_t> prev3) {
simd8<uint8_t> is_third_byte = prev2.saturating_sub(0xe0u-1); // Only 111_____ will be > 0 simd8<uint8_t> is_third_byte = prev2.saturating_sub(0xe0u-0x80); // Only 111_____ will be >= 0x80
simd8<uint8_t> is_fourth_byte = prev3.saturating_sub(0xf0u-1); // Only 1111____ will be > 0 simd8<uint8_t> is_fourth_byte = prev3.saturating_sub(0xf0u-0x80); // Only 1111____ will be >= 0x80
// Caller requires a bool (all 1's). All values resulting from the subtraction will be <= 64, so signed comparison is fine. return is_third_byte | is_fourth_byte;
return simd8<int8_t>(is_third_byte | is_fourth_byte) > int8_t(0);
} }
} // unnamed namespace } // unnamed namespace
+4 -5
View File
@@ -109,11 +109,10 @@ simdjson_unused simdjson_inline simd8<bool> must_be_continuation(const simd8<uin
return simd8<int8_t>(is_second_byte | is_third_byte | is_fourth_byte) > int8_t(0); return simd8<int8_t>(is_second_byte | is_third_byte | is_fourth_byte) > int8_t(0);
} }
simdjson_inline simd8<bool> must_be_2_3_continuation(const simd8<uint8_t> prev2, const simd8<uint8_t> prev3) { simdjson_inline simd8<uint8_t> must_be_2_3_continuation(const simd8<uint8_t> prev2, const simd8<uint8_t> prev3) {
simd8<uint8_t> is_third_byte = prev2.saturating_sub(0xe0u-1); // Only 111_____ will be > 0 simd8<uint8_t> is_third_byte = prev2.saturating_sub(0xe0u-0x80); // Only 111_____ will be >= 0x80
simd8<uint8_t> is_fourth_byte = prev3.saturating_sub(0xf0u-1); // Only 1111____ will be > 0 simd8<uint8_t> is_fourth_byte = prev3.saturating_sub(0xf0u-0x80); // Only 1111____ will be >= 0x80
// Caller requires a bool (all 1's). All values resulting from the subtraction will be <= 64, so signed comparison is fine. return is_third_byte | is_fourth_byte;
return simd8<int8_t>(is_third_byte | is_fourth_byte) > int8_t(0);
} }
} // unnamed namespace } // unnamed namespace
+8 -4
View File
@@ -452,14 +452,18 @@ namespace parse_api_tests {
element doc_root1 = parser.parse_into_document(doc, input); element doc_root1 = parser.parse_into_document(doc, input);
if(simdjson::to_string(doc_root1) != "[1,2,3]") { return false; } if(simdjson::to_string(doc_root1) != "[1,2,3]") { return false; }
//... doc_root1 is a pointer inside doc //... doc_root1 is a pointer inside doc
element doc_root2 = parser.parse_into_document(doc, input); element doc_root2 = parser.load_into_document(doc, TWITTER_JSON);
//... doc_root2 is a pointer inside doc //... doc_root2 is a pointer inside doc
if(simdjson::to_string(doc_root2) != "[1,2,3]") { return false; } if(uint64_t(doc_root2["search_metadata"]["count"]) != 100) { return false; }
if(uint64_t(doc.root()["search_metadata"]["count"]) != 100) { return false; }
element doc_root3 = parser.parse_into_document(doc, input);
//... doc_root3 is a pointer inside doc
if(simdjson::to_string(doc_root3) != "[1,2,3]") { return false; }
// Here let us take moving the document: // Here let us take moving the document:
dom::document docm = std::move(doc); dom::document docm = std::move(doc);
element doc_root3 = docm.root(); element doc_root4 = docm.root();
if(simdjson::to_string(doc_root3) != "[1,2,3]") { return false; } if(simdjson::to_string(doc_root4) != "[1,2,3]") { return false; }
return true; return true;
} }
+15 -1
View File
@@ -278,6 +278,19 @@ namespace number_tests {
TEST_SUCCEED(); TEST_SUCCEED();
} }
bool issue2099() {
TEST_START();
ondemand::parser parser;
auto json = "1000000000.000000001"_padded;
ondemand::document doc;
ASSERT_SUCCESS(parser.iterate(json).get(doc));
ondemand::number number;
ASSERT_SUCCESS(doc.get_number().get(number));
ASSERT_EQUAL(number.get_number_type(), ondemand::number_type::floating_point_number);
ASSERT_EQUAL(number.get_double(), 1e9);
TEST_SUCCEED();
}
bool issue1878() { bool issue1878() {
TEST_START(); TEST_START();
ondemand::parser parser; ondemand::parser parser;
@@ -429,7 +442,8 @@ namespace number_tests {
} }
bool run() { bool run() {
return issue2093() && return issue2099() &&
issue2093() &&
issue2045() && issue2045() &&
issue2017() && issue2017() &&
issue_1898() && issue_1898() &&