mirror of
https://github.com/simdjson/simdjson
synced 2026-06-08 17:27:07 +00:00
Compare commits
47 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3177cd1b5d | |||
| 63d9ce3c58 | |||
| 8e8180560d | |||
| 1594af5d5d | |||
| b207338365 | |||
| 68be9c2170 | |||
| 5347771091 | |||
| 8bf8315651 | |||
| 269ae7ad6b | |||
| 2aa91f741f | |||
| 5430544bbb | |||
| 7b55f16682 | |||
| d8fec59e85 | |||
| 57b6034a0c | |||
| 7500d7bb4f | |||
| 82c9876aec | |||
| b9234be80f | |||
| 0a2563e13e | |||
| 727ec73c33 | |||
| 9a55a830ec | |||
| 8c89ae0cd9 | |||
| 8c71ca1b1d | |||
| c72b4bc0f4 | |||
| 8a26cb3c8e | |||
| bf2ba5c675 | |||
| f151300a76 | |||
| 9aa3563d99 | |||
| 9444c1a04f | |||
| 883901a81b | |||
| a2c96c9cca | |||
| c63da0ef2c | |||
| c61cefda85 | |||
| bffcbb444d | |||
| 0b2891aaab | |||
| 983fb41802 | |||
| 0d2455029d | |||
| e94f027310 | |||
| 2b766e4c09 | |||
| a5db75e1a6 | |||
| 4bd66cb891 | |||
| 960a7ebba1 | |||
| d520062f8e | |||
| db08d78ed0 | |||
| 46292b8d4b | |||
| 46241287c6 | |||
| 137cb14bcc | |||
| 5e6be3ed7a |
@@ -0,0 +1,34 @@
|
||||
name: Doxygen GitHub Pages
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
# Allows you to run this workflow manually from the Actions tab
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pages: write
|
||||
id-token: write
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
environment:
|
||||
name: github-pages
|
||||
url: ${{ steps.deployment.outputs.page_url }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Install Doxygen
|
||||
run: sudo apt-get install doxygen graphviz -y
|
||||
- run: mkdir docs
|
||||
- name: Install theme
|
||||
run: ./tools/prepare_doxygen.sh
|
||||
- name: Generate Doxygen Documentation
|
||||
run: doxygen
|
||||
- name: Deploy to GitHub Pages
|
||||
uses: peaceiris/actions-gh-pages@v3
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
publish_dir: doc/api/html
|
||||
@@ -24,7 +24,7 @@ jobs:
|
||||
implementations: haswell westmere fallback
|
||||
UBSAN_OPTIONS: halt_on_error=1
|
||||
MAXLEN: -max_len=4000
|
||||
CLANGVERSION: 11
|
||||
CLANGVERSION: 15
|
||||
# which optimization level to use for the sanitizer build (see build_fuzzer.variants.sh)
|
||||
OPTLEVEL: -O3
|
||||
|
||||
@@ -32,7 +32,7 @@ jobs:
|
||||
- name: Install packages necessary for building
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt-get install --quiet ninja-build valgrind zip unzip
|
||||
sudo apt-get install --quiet ninja-build valgrind zip unzip lsb-release wget software-properties-common gnupg
|
||||
wget https://apt.llvm.org/llvm.sh
|
||||
chmod +x llvm.sh
|
||||
sudo ./llvm.sh $CLANGVERSION
|
||||
@@ -50,12 +50,12 @@ jobs:
|
||||
path: out/
|
||||
key: corpus-${{ github.run_id }}
|
||||
restore-keys: corpus-
|
||||
|
||||
|
||||
- name: show statistics for the cached corpus
|
||||
run: |
|
||||
echo number of files in github action corpus cache:
|
||||
find out -type f |wc -l
|
||||
|
||||
|
||||
- name: Create and prepare the initial seed corpus
|
||||
run: |
|
||||
fuzz/build_corpus.sh
|
||||
@@ -92,7 +92,7 @@ jobs:
|
||||
export SIMDJSON_FORCE_IMPLEMENTATION=$implementation
|
||||
build-sanitizers$OPTLEVEL/fuzz/fuzz_$fuzzer out/$fuzzer $others seedcorpus -max_total_time=20 $MAXLEN
|
||||
done
|
||||
echo now have $(ls out/$fuzzer |wc -l) files in corpus
|
||||
echo now have $(ls out/$fuzzer |wc -l) files in corpus
|
||||
done
|
||||
|
||||
- name: Fuzz differential impl. fuzzers with sanitizer+asserts (good at detecting errors)
|
||||
@@ -119,7 +119,7 @@ jobs:
|
||||
|
||||
- name: Package the corpus into an artifact
|
||||
run: |
|
||||
for fuzzer in $defaultimplfuzzers $implfuzzers; do
|
||||
for fuzzer in $defaultimplfuzzers $implfuzzers; do
|
||||
tar rf corpus.tar out/$fuzzer
|
||||
done
|
||||
|
||||
@@ -141,7 +141,7 @@ jobs:
|
||||
run: |
|
||||
for fuzzer in $defaultimplfuzzers $implfuzzers; do
|
||||
find out/$fuzzer -type f |sort|head -n200|xargs -n40 valgrind build-replay/fuzz/fuzz_$fuzzer 2>&1|tee valgrind-$fuzzer.txt
|
||||
done
|
||||
done
|
||||
|
||||
- name: Compress the valgrind output
|
||||
run: tar cf valgrind.tar valgrind-*.txt
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
name: Macos (Xcode 11)
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
macos-build:
|
||||
if: >-
|
||||
! contains(toJSON(github.event.commits.*.message), '[skip ci]') &&
|
||||
! contains(toJSON(github.event.commits.*.message), '[skip github]')
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/cache@v3
|
||||
with:
|
||||
path: dependencies/.cache
|
||||
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
|
||||
- name: Use cmake
|
||||
run: |
|
||||
xcversion select 11.7
|
||||
mkdir builddebug &&
|
||||
cd builddebug &&
|
||||
cmake -DCMAKE_BUILD_TYPE=Debug -DSIMDJSON_GOOGLE_BENCHMARKS=OFF -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=OFF .. &&
|
||||
cmake --build . &&
|
||||
ctest -j --output-on-failure -LE explicitonly &&
|
||||
cd .. &&
|
||||
mkdir build &&
|
||||
cd build &&
|
||||
cmake -DSIMDJSON_GOOGLE_BENCHMARKS=ON -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=OFF -DCMAKE_INSTALL_PREFIX:PATH=destination .. &&
|
||||
cmake --build . &&
|
||||
ctest -j --output-on-failure -LE explicitonly &&
|
||||
cmake --install . &&
|
||||
echo -e '#include <simdjson.h>\nint main(int argc,char**argv) {simdjson::dom::parser parser;simdjson::dom::element tweets = parser.load(argv[1]); }' > tmp.cpp && c++ -Idestination/include -Ldestination/lib -std=c++17 -Wl,-rpath,destination/lib -o linkandrun tmp.cpp -lsimdjson && ./linkandrun jsonexamples/twitter.json &&
|
||||
cd ../tests/installation_tests/find &&
|
||||
mkdir build && cd build && cmake -DCMAKE_INSTALL_PREFIX:PATH=../../../build/destination .. && cmake --build .
|
||||
@@ -0,0 +1,29 @@
|
||||
name: Ubuntu s390x (GCC 11)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: uraimo/run-on-arch-action@v2
|
||||
name: Test
|
||||
id: runcmd
|
||||
with:
|
||||
arch: s390x
|
||||
distro: ubuntu_latest
|
||||
githubToken: ${{ github.token }}
|
||||
install: |
|
||||
apt-get update -q -y
|
||||
apt-get install -y cmake make g++
|
||||
run: |
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -B build
|
||||
cmake --build build -j=2
|
||||
ctest --output-on-failure --test-dir build
|
||||
@@ -0,0 +1,25 @@
|
||||
name: Ubuntu 22.04 CI (CLANG 14)
|
||||
|
||||
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@v3
|
||||
- uses: actions/cache@v3
|
||||
with:
|
||||
path: dependencies/.cache
|
||||
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
|
||||
- name: Install clang++-14
|
||||
run: sudo apt-get install -y clang++-14
|
||||
- name: Use cmake
|
||||
run: |
|
||||
mkdir build &&
|
||||
cd build &&
|
||||
CXX=clang++-14 cmake -DSIMDJSON_DEVELOPER_MODE=ON .. &&
|
||||
cmake --build . &&
|
||||
ctest -j --output-on-failure -LE explicitonly
|
||||
+7
-7
@@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.14)
|
||||
project(
|
||||
simdjson
|
||||
# The version number is modified by tools/release.py
|
||||
VERSION 2.2.3
|
||||
VERSION 3.1.1
|
||||
DESCRIPTION "Parsing gigabytes of JSON per second"
|
||||
HOMEPAGE_URL "https://simdjson.org/"
|
||||
LANGUAGES CXX C
|
||||
@@ -20,8 +20,8 @@ string(
|
||||
# ---- Options, variables ----
|
||||
|
||||
# These version numbers are modified by tools/release.py
|
||||
set(SIMDJSON_LIB_VERSION "13.0.0" CACHE STRING "simdjson library version")
|
||||
set(SIMDJSON_LIB_SOVERSION "13" CACHE STRING "simdjson library soversion")
|
||||
set(SIMDJSON_LIB_VERSION "15.0.0" CACHE STRING "simdjson library version")
|
||||
set(SIMDJSON_LIB_SOVERSION "15" CACHE STRING "simdjson library soversion")
|
||||
|
||||
option(SIMDJSON_ENABLE_THREADS "Link with thread support" ON)
|
||||
|
||||
@@ -188,11 +188,11 @@ endif()
|
||||
|
||||
# ---- Developer mode extras ----
|
||||
|
||||
if(NOT SIMDJSON_DEVELOPER_MODE)
|
||||
message(STATUS "Building only the library. Advanced users may want to turn SIMDJSON_DEVELOPER_MODE to ON, e.g., via -D SIMDJSON_DEVELOPER_MODE=ON.")
|
||||
if(is_top_project AND NOT SIMDJSON_DEVELOPER_MODE)
|
||||
message(STATUS "Building only the library. Advanced users and contributors may want to turn SIMDJSON_DEVELOPER_MODE to ON, e.g., via -D SIMDJSON_DEVELOPER_MODE=ON.")
|
||||
return()
|
||||
elseif(NOT is_top_project)
|
||||
message(AUTHOR_WARNING "Developer mode is intended for developers of simdjson")
|
||||
elseif(SIMDJSON_DEVELOPER_MODE AND NOT is_top_project)
|
||||
message(AUTHOR_WARNING "Developer mode in simdjson is intended for the developers of simdjson")
|
||||
endif()
|
||||
|
||||
simdjson_apply_props(simdjson-internal-flags)
|
||||
|
||||
@@ -38,7 +38,7 @@ PROJECT_NAME = simdjson
|
||||
# could be handy for archiving the generated documentation or if some version
|
||||
# control system is used.
|
||||
|
||||
PROJECT_NUMBER = "2.2.3"
|
||||
PROJECT_NUMBER = "3.1.1"
|
||||
|
||||
# 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
|
||||
@@ -829,7 +829,7 @@ WARN_LOGFILE =
|
||||
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
|
||||
# Note: If this tag is empty the current directory is searched.
|
||||
|
||||
INPUT = doc include
|
||||
INPUT = doc include/simdjson include/simdjson/dom include/simdjson/generic
|
||||
|
||||
# This tag can be used to specify the character encoding of the source files
|
||||
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
|
||||
@@ -1246,7 +1246,10 @@ HTML_STYLESHEET =
|
||||
# list). For an example see the documentation.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
HTML_EXTRA_STYLESHEET =
|
||||
|
||||
HTML_EXTRA_STYLESHEET = theme/doxygen-awesome.css \
|
||||
theme/doxygen-awesome-sidebar-only.css \
|
||||
theme/doxygen-awesome-sidebar-only-darkmode-toggle.css
|
||||
|
||||
# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
|
||||
# other source files which should be copied to the HTML output directory. Note
|
||||
@@ -1256,7 +1259,10 @@ HTML_EXTRA_STYLESHEET =
|
||||
# files will be copied as-is; there are no commands or markers available.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
HTML_EXTRA_FILES =
|
||||
HTML_EXTRA_FILES = theme/doxygen-awesome-darkmode-toggle.js \
|
||||
theme/doxygen-awesome-interactive-toc.js \
|
||||
theme/doxygen-awesome-fragment-copy-button.js \
|
||||
theme/doxygen-awesome-paragraph-link.js
|
||||
|
||||
# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
|
||||
# will adjust the colors in the style sheet and background images according to
|
||||
@@ -1543,7 +1549,7 @@ DISABLE_INDEX = NO
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
GENERATE_TREEVIEW = NO
|
||||
GENERATE_TREEVIEW = YES
|
||||
|
||||
# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
|
||||
# doxygen will group on one line in the generated HTML documentation.
|
||||
|
||||
@@ -186,7 +186,7 @@
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright 2018-2019 The simdjson authors
|
||||
Copyright 2018-2023 The simdjson authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
[/badge.svg)](https://simdjson.org/plots.html)
|
||||

|
||||

|
||||
[![][license img]][license] [](https://simdjson.org/api/2.0.0/index.html)
|
||||
[![][license img]][license]
|
||||
|
||||
[](https://simdjson.github.io/simdjson/)
|
||||
|
||||
simdjson : Parsing gigabytes of JSON per second
|
||||
===============================================
|
||||
@@ -116,6 +118,10 @@ Real-world usage
|
||||
- [Shopify HeapProfiler](https://github.com/Shopify/heap-profiler)
|
||||
- [StarRocks](https://github.com/StarRocks/starrocks)
|
||||
- [Microsoft FishStore](https://github.com/microsoft/FishStore)
|
||||
- [Intel PCM](https://github.com/intel/pcm)
|
||||
- [WatermelonDB](https://github.com/Nozbe/WatermelonDB)
|
||||
- [Apache Doris](https://github.com/apache/doris)
|
||||
- [Dgraph](https://github.com/dgraph-io/dgraph)
|
||||
|
||||
|
||||
If you are planning to use simdjson in a product, please work from one of our releases.
|
||||
|
||||
@@ -51,6 +51,7 @@ private:
|
||||
simdjson_inline void
|
||||
write_raw_string(simdjson::ondemand::raw_json_string rjs);
|
||||
inline void recursive_processor(simdjson::ondemand::value element);
|
||||
inline void recursive_processor_ref(simdjson::ondemand::value& element);
|
||||
|
||||
simdjson::ondemand::parser parser;
|
||||
uint8_t *buff{};
|
||||
@@ -74,17 +75,34 @@ simdjson2msgpack::to_msgpack(const simdjson::padded_string &json,
|
||||
write_byte(0xc2 + doc.get_bool());
|
||||
break;
|
||||
case simdjson::ondemand::json_type::null:
|
||||
write_byte(0xc0);
|
||||
// We check that the value is indeed null
|
||||
// otherwise: an error is thrown.
|
||||
if(doc.is_null()) {
|
||||
write_byte(0xc0);
|
||||
}
|
||||
break;
|
||||
case simdjson::ondemand::json_type::array:
|
||||
case simdjson::ondemand::json_type::object:
|
||||
default:
|
||||
// impossible
|
||||
break;
|
||||
SIMDJSON_UNREACHABLE();
|
||||
}
|
||||
} else {
|
||||
simdjson::ondemand::value val = doc;
|
||||
#define SIMDJSON_GCC_COMPILER ((__GNUC__) && !(__clang__) && !(__INTEL_COMPILER))
|
||||
#if SIMDJSON_GCC_COMPILER
|
||||
// the GCC compiler does well with by-value passing.
|
||||
// GCC has superior recursive inlining:
|
||||
// https://stackoverflow.com/questions/29186186/why-does-gcc-generate-a-faster-program-than-clang-in-this-recursive-fibonacci-co
|
||||
// https://godbolt.org/z/TeK4doE51
|
||||
recursive_processor(val);
|
||||
#else
|
||||
recursive_processor_ref(val);
|
||||
#endif
|
||||
}
|
||||
if (doc.current_location().error() == simdjson::SUCCESS) {
|
||||
// Example of error detection - this won't be reached on twitter.json in the benchmark.
|
||||
throw "There are unexpectedly tokens after the end of the json in the json2msgpack sample data";
|
||||
}
|
||||
return std::string_view(reinterpret_cast<char *>(buf), size_t(buff - buf));
|
||||
}
|
||||
@@ -156,7 +174,58 @@ void simdjson2msgpack::recursive_processor(simdjson::ondemand::value element) {
|
||||
write_byte(0xc2 + element.get_bool());
|
||||
break;
|
||||
case simdjson::ondemand::json_type::null:
|
||||
write_byte(0xc0);
|
||||
// We check that the value is indeed null
|
||||
// otherwise: an error is thrown.
|
||||
if(element.is_null()) {
|
||||
write_byte(0xc0);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
SIMDJSON_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void simdjson2msgpack::recursive_processor_ref(simdjson::ondemand::value& element) {
|
||||
switch (element.type()) {
|
||||
case simdjson::ondemand::json_type::array: {
|
||||
uint32_t counter = 0;
|
||||
write_byte(0xdd);
|
||||
uint8_t *location = skip_uint32();
|
||||
for (auto child : element.get_array()) {
|
||||
counter++;
|
||||
simdjson::ondemand::value v = child.value();
|
||||
recursive_processor_ref(v);
|
||||
}
|
||||
write_uint32_at(counter, location);
|
||||
} break;
|
||||
case simdjson::ondemand::json_type::object: {
|
||||
uint32_t counter = 0;
|
||||
write_byte(0xdf);
|
||||
uint8_t *location = skip_uint32();
|
||||
for (auto field : element.get_object()) {
|
||||
counter++;
|
||||
write_raw_string(field.key());
|
||||
simdjson::ondemand::value v = field.value();
|
||||
recursive_processor_ref(v);
|
||||
}
|
||||
write_uint32_at(counter, location);
|
||||
} break;
|
||||
case simdjson::ondemand::json_type::number:
|
||||
write_double(element.get_double());
|
||||
break;
|
||||
case simdjson::ondemand::json_type::string:
|
||||
write_raw_string(element.get_raw_json_string());
|
||||
break;
|
||||
case simdjson::ondemand::json_type::boolean:
|
||||
write_byte(0xc2 + element.get_bool());
|
||||
break;
|
||||
case simdjson::ondemand::json_type::null:
|
||||
// We check that the value is indeed null
|
||||
// otherwise: an error is thrown.
|
||||
if(element.is_null()) {
|
||||
write_byte(0xc0);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
SIMDJSON_UNREACHABLE();
|
||||
|
||||
Vendored
+1
-1
@@ -15,7 +15,7 @@ if(SIMDJSON_GOOGLE_BENCHMARKS)
|
||||
set_off(BENCHMARK_ENABLE_INSTALL)
|
||||
set_off(BENCHMARK_ENABLE_WERROR)
|
||||
|
||||
import_dependency(google_benchmarks google/benchmark f91b6b4)
|
||||
import_dependency(google_benchmarks google/benchmark d572f47)
|
||||
add_dependency(google_benchmarks)
|
||||
endif()
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -40,7 +40,7 @@ macro(add_dependency NAME)
|
||||
message(FATAL_ERROR "Missing ${NAME}_SOURCE_DIR variable")
|
||||
endif()
|
||||
|
||||
add_subdirectory("${${NAME}_SOURCE_DIR}" "${PROJECT_BINARY_DIR}/_deps/${NAME}")
|
||||
add_subdirectory("${${NAME}_SOURCE_DIR}" "${PROJECT_BINARY_DIR}/_deps/${NAME}" EXCLUDE_FROM_ALL)
|
||||
endmacro()
|
||||
|
||||
function(set_off NAME)
|
||||
|
||||
+35
-11
@@ -41,7 +41,9 @@ Requirements
|
||||
- Visual Studio 2017 or better under 64-bit Windows. Users should target a 64-bit build (x64) instead of a 32-bit build (x86). We support the LLVM clang compiler under Visual Studio (clangcl) as well as as the regular Visual Studio compiler. We also support MinGW 64-bit under Windows.
|
||||
|
||||
|
||||
Support for AVX-512 require a processor with AVX512-VBMI2 support (Ice Lake or better) under a 64-bit system and a recent compiler (LLVM clang 6 or better, GCC 8 or better, Visual Studio 2019 or better).
|
||||
Support for AVX-512 require a processor with AVX512-VBMI2 support (Ice Lake or better) under a 64-bit system and a recent compiler (LLVM clang 6 or better, GCC 8 or better, Visual Studio 2019 or better). You need a correspondingly recent assembler such as gas (2.30+) or nasm (2.14+): recent compilers usually come with recent assemblers. If you mix a recent compiler with an incompatible/old assembler (e.g., when using a recent compiler with an old Linux distribution), you may get errors at build time because the compiler produces instructions that the assembler does not recognize: you should update your assembler to match your compiler (e.g., upgrade binutils to version 2.30 or better under Linux) or use an older compiler matching the capabilities of your assembler.
|
||||
|
||||
We test the library on a big-endian system (IBM s390x with Linux) .
|
||||
|
||||
Including simdjson
|
||||
------------------
|
||||
@@ -61,7 +63,7 @@ c++ myproject.cpp simdjson.cpp
|
||||
```
|
||||
|
||||
Note:
|
||||
- Users on macOS and other platforms where default compilers do not provide C++11 compliant by default should request it with the appropriate flag (e.g., `c++ -std=c++17 myproject.cpp simdjson.cpp`).
|
||||
- Users on macOS and other platforms where default compilers do not provide C++11 compliant by default should request it with the appropriate flag (e.g., `c++ -std=c++11 myproject.cpp simdjson.cpp`).
|
||||
- The library relies on [runtime CPU detection](implementation-selection.md): avoid specifying an architecture at compile time (e.g., `-march-native`).
|
||||
|
||||
Using simdjson with package managers
|
||||
@@ -297,7 +299,8 @@ support for users who avoid exceptions. See [the simdjson error handling documen
|
||||
ondemand::object and ondemand::array. We also have explicit methods such as `get_string()`, `get_double()`,
|
||||
`get_uint64()`, `get_int64()`, `get_bool()`, `get_object()` and `get_array()`. After a cast or an explicit method,
|
||||
the number, string or boolean will be parsed, or the initial `[` or `{` will be verified. An exception is thrown if
|
||||
the cast is not possible.
|
||||
the cast is not possible. The `get_string()` returns a valid UTF-8 string, after
|
||||
unescaping characters as needed: unmatched surrogate pairs are treated as an error. When calling `get_uint64()` and `get_int64()`, if the number does not fit in a corresponding 64-bit integer type, it is also considered an error.
|
||||
|
||||
> IMPORTANT NOTE: values can only be parsed once. Since documents are *iterators*, once you have
|
||||
> parsed a value (such as by casting to double), you cannot get at it again. It is an error to call
|
||||
@@ -482,8 +485,20 @@ support for users who avoid exceptions. See [the simdjson error handling documen
|
||||
std::cout << "Number of fields: " << count << std::endl; // Prints "Number of fields: 2"
|
||||
```
|
||||
* **Tree Walking and JSON Element Types:** Sometimes you don't necessarily have a document
|
||||
with a known type, and are trying to generically inspect or walk over JSON elements. To do that, you can use iterators and the `type()` method. You can also represent arbitrary JSON values with
|
||||
`ondemand::value` instances: it can represent anything except a scalar document (lone number, string, null or Boolean). You can check for scalar documents with the method `scalar()`. You may also access [raw strings](#raw-strings).
|
||||
with a known type, and are trying to generically inspect or walk over JSON elements.
|
||||
You can also represent arbitrary JSON values with
|
||||
`ondemand::value` instances: it can represent anything except a scalar document (lone number, string, null or Boolean). You can check for scalar documents with the method `scalar()`.
|
||||
You can query the type of a document or a value with the `type()` method.
|
||||
The `type()` method does not consume or validate documents and values, but it tells you whether they are
|
||||
- arrays (`json_type::array`),
|
||||
- objects (`json_type::object`)
|
||||
- numbers (`json_type::number`),
|
||||
- strings (`json_type::string`),
|
||||
- Booleans (`json_type::boolean`),
|
||||
- null (`json_type::null`).
|
||||
|
||||
You must still validate and consume the values (e.g., call `is_null()`) after calling `type()`.
|
||||
You may also access [raw strings](#raw-strings).
|
||||
For example, the following is a quick and dirty recursive function that verbosely prints the JSON document as JSON. This example also illustrates lifecycle requirements: the `document` instance holds the iterator. The document must remain in scope while you are accessing instances of `value`, `object` and `array`.
|
||||
```c++
|
||||
void recursive_print_json(ondemand::value element) {
|
||||
@@ -532,7 +547,11 @@ support for users who avoid exceptions. See [the simdjson error handling documen
|
||||
cout << element.get_bool();
|
||||
break;
|
||||
case ondemand::json_type::null:
|
||||
cout << "null";
|
||||
// We check that the value is indeed null
|
||||
// otherwise: an error is thrown.
|
||||
if(element.is_null()) {
|
||||
cout << "null";
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -931,11 +950,11 @@ bool parse() {
|
||||
// Iterating through an array of objects
|
||||
auto error = parser.iterate(cars_json).get(doc);
|
||||
if(error) { std::cerr << error << std::endl; return false; }
|
||||
ondemand::array cars;
|
||||
ondemand::array cars; // invalid until the get() succeeds
|
||||
error = doc.get_array().get(cars);
|
||||
|
||||
for (auto car_value : cars) {
|
||||
ondemand::object car;
|
||||
ondemand::object car; // invalid until the get() succeeds
|
||||
error = car_value.get_object().get(car);
|
||||
if(error) { std::cerr << error << std::endl; return false; }
|
||||
|
||||
@@ -976,7 +995,7 @@ For safety, you should only use our ondemand instances (e.g., `ondemand::object`
|
||||
after you have initialized them and checked that there is no error:
|
||||
|
||||
```c++
|
||||
ondemand::object car;
|
||||
ondemand::object car; // invalid until the get() succeeds
|
||||
// the `car` instance should not use used before it is initialized
|
||||
error = car_value.get_object().get(car);
|
||||
if(error) {
|
||||
@@ -994,7 +1013,7 @@ having to handle exceptions.
|
||||
ondemand::document doc;
|
||||
auto error = parser.iterate(json).get(doc);
|
||||
if(error) { return false; }
|
||||
ondemand::object object;
|
||||
ondemand::object object; // invalid until the get() succeeds
|
||||
error = doc.get_object().get(object);
|
||||
if(error) { return false; }
|
||||
for(auto field : object) {
|
||||
@@ -1110,6 +1129,9 @@ for (auto val : doc) {
|
||||
std::cout << doc.current_location() << std::endl; // Throws OUT_OF_BOUNDS
|
||||
```
|
||||
|
||||
Conversely, if `doc.current_location().error() == simdjson::SUCCESS`,
|
||||
then the document has more content.
|
||||
|
||||
Finally, the `current_location()` method may also be used even when no exceptions/errors
|
||||
are thrown. This can be helpful for users that want to know the current state of iteration during parsing. For example:
|
||||
|
||||
@@ -1118,7 +1140,7 @@ auto json = R"( [[1,2,3], -23.4, {"key": "value"}, true] )"_padded;
|
||||
ondemand::parser parser;
|
||||
auto doc = parser.iterate(json);
|
||||
for (auto val : doc) {
|
||||
ondemand::object obj;
|
||||
ondemand::object obj; // invalid until the get() succeeds
|
||||
auto error = val.get_object().get(obj); // Only get objects
|
||||
if (!error) {
|
||||
std::cout << doc.current_location() << std::endl; // Prints ""key": "value"}, true] "
|
||||
@@ -1396,6 +1418,8 @@ if (error) {
|
||||
It is also important to note that when dealing an invalid number inside a string, simdjson will report a `NUMBER_ERROR` error if the string begins with a number whereas simdjson
|
||||
will report a `INCORRECT_TYPE` error otherwise.
|
||||
|
||||
The `*_in_string` methods can also be called on a single document instance:
|
||||
e.g., when your document consist solely of a quoted number.
|
||||
|
||||
Dynamic Number Types
|
||||
------------------------------
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
We take our documentation seriously. Please start reading the documentation before you attempt to use simdjson. We hope you will enjoy reading us.
|
||||
|
||||
* Basics: https://github.com/simdjson/simdjson/blob/master/doc/basics.md is an overview of how to use simdjson and its APIs.
|
||||
* parse_many: https://github.com/simdjson/simdjson/blob/master/doc/parse_many.md describes an interface providing features to work with files or streams containing multiple small JSON documents. As fast and convenient as possible.
|
||||
* iterate_many: https://github.com/simdjson/simdjson/blob/master/doc/iterate_many.md describes an interface providing features to work with files or streams containing multiple small JSON documents. As fast and convenient as possible.
|
||||
* Performance: https://github.com/simdjson/simdjson/blob/master/doc/performance.md shows some more advanced scenarios and how to tune for them.
|
||||
|
||||
+13
-12
@@ -47,7 +47,7 @@ dom::element doc = parser.parse("[1,2,3]"_padded); // parse a string, the _padde
|
||||
The parsed document resulting from the `parser.load` and `parser.parse` calls depends on the `parser` instance. Thus the `parser` instance must remain in scope. Furthermore, you must have at most one parsed document in play per `parser` instance.
|
||||
You cannot copy a `parser` instance, you may only move it.
|
||||
|
||||
If you need to keep a document around long term, you can keep or move the parser instance. Note that moving a parser instance, or keeping one in a movable data structure like vector or map, can cause any outstanding `element`, `object` or `array` instances to be invalidated. If you need to store a parser in a movable data structure, you should use a `std::unique_ptr` to avoid this invalidation(e.g., `std::unique_ptr<dom::parser> parser(new dom::parser{})`).
|
||||
If you need to keep a document around long term, you can keep or move the parser instance. Note that moving a parser instance, or keeping one in a movable data structure like vector or map, can cause any outstanding `element`, `object` or `array` instances to be invalidated. The `element`, `object` or `array` instances are mere thin wrappers akin to an `std::vector<int>::iterator`: they are invalid when default constructed, they must be tied to a valid document instance. If you need to store a parser in a movable data structure, you should use a `std::unique_ptr` to avoid this invalidation(e.g., `std::unique_ptr<dom::parser> parser(new dom::parser{})`).
|
||||
|
||||
During the`load` or `parse` calls, neither the input file nor the input string are ever modified. After calling `load` or `parse`, the source (either a file or a string) can be safely discarded. All of the JSON data is stored in the `parser` instance. The parsed document is also immutable in simdjson: you do not modify it by accessing it.
|
||||
|
||||
@@ -65,7 +65,7 @@ Once you have an element, you can navigate it with idiomatic C++ iterators, oper
|
||||
* **Extracting Values (with exceptions):** You can cast a JSON element to a native type: `double(element)` or
|
||||
`double x = json_element`. This works for double, uint64_t, int64_t, bool,
|
||||
dom::object and dom::array. An exception (`simdjson::simdjson_error`) is thrown if the cast is not possible.
|
||||
* **Extracting Values (without exceptions):** You can use a variant usage of `get()` with error codes to avoid exceptions. You first declare the variable of the appropriate type (`double`, `uint64_t`, `int64_t`, `bool`,
|
||||
* **Extracting Values (without exceptions):** You can use a variant usage of `get()` with error codes to avoid exceptions. You first declare the variable of the appropriate type (`double`, `uint64_t`, `int64_t`, `bool`, `std::string_view`,
|
||||
`dom::object` and `dom::array`) and pass it by reference to `get()` which gives you back an error code: e.g.,
|
||||
```c++
|
||||
simdjson::error_code error;
|
||||
@@ -76,6 +76,7 @@ Once you have an element, you can navigate it with idiomatic C++ iterators, oper
|
||||
if (error) { std::cerr << error << std::endl; return EXIT_FAILURE; }
|
||||
std::cout << "I parsed " << value << " from " << numberstring.data() << std::endl;
|
||||
```
|
||||
The strings contain unescaped valid UTF-8 strings: no unmatched surrogate is allowed.
|
||||
* **Field Access:** To get the value of the "foo" field in an object, use `object["foo"]`.
|
||||
* **Array Iteration:** To iterate through an array, use `for (auto value : array) { ... }`. If you
|
||||
know the type of the value, you can cast it right there, too! `for (double value : array) { ... }`
|
||||
@@ -88,7 +89,7 @@ Once you have an element, you can navigate it with idiomatic C++ iterators, oper
|
||||
* **Array and Object size** Given an array or an object, you can get its size (number of elements or keys)
|
||||
with the `size()` method.
|
||||
* **Checking an Element Type:** You can check an element's type with `element.type()`. It
|
||||
returns an `element_type` with values such as `simdjson::dom::element_type::ARRAY`, `simdjson::dom::element_type::OBJECT`, `simdjson::dom::element_type::INT64`, `simdjson::dom::element_type::UINT64`,`simdjson::dom::element_type::DOUBLE`, `simdjson::dom::element_type::BOOL` or, `simdjson::dom::element_type::NULL_VALUE`.
|
||||
returns an `element_type` with values such as `simdjson::dom::element_type::ARRAY`, `simdjson::dom::element_type::OBJECT`, `simdjson::dom::element_type::INT64`, `simdjson::dom::element_type::UINT64`,`simdjson::dom::element_type::DOUBLE`, `simdjson::dom::element_type::STRING`, `simdjson::dom::element_type::BOOL` or, `simdjson::dom::element_type::NULL_VALUE`.
|
||||
* **Output to streams and strings:** Given a document or an element (or node) out of a JSON document, you can output a minified string version using the C++ stream idiom (`out << element`). You can also request the construction of a minified string version (`simdjson::minify(element)`). Numbers are serialized as 64-bit floating-point numbers (`double`).
|
||||
|
||||
### Examples
|
||||
@@ -167,7 +168,7 @@ While the simdjson library can be used in any project using C++ 11 and above, fi
|
||||
```c++
|
||||
padded_string json = R"( { "foo": 1, "bar": 2 } )"_padded;
|
||||
dom::parser parser;
|
||||
dom::object object;
|
||||
dom::object object; // invalid until the get() succeeds
|
||||
auto error = parser.parse(json).get(object);
|
||||
if (error) { cerr << error << endl; return; }
|
||||
for (auto [key, value] : object) {
|
||||
@@ -181,7 +182,7 @@ For comparison, here is the C++ 11 version of the same code:
|
||||
// C++ 11 version for comparison
|
||||
padded_string json = R"( { "foo": 1, "bar": 2 } )"_padded;
|
||||
dom::parser parser;
|
||||
dom::object object;
|
||||
dom::object object; // invalid until the get() succeeds
|
||||
auto error = parser.parse(json).get(object);
|
||||
if (error) { cerr << error << endl; return; }
|
||||
for (dom::key_value_pair field : object) {
|
||||
@@ -227,7 +228,7 @@ dom::parser parser;
|
||||
dom::element cars = parser.parse(cars_json);
|
||||
cout << cars.at_pointer("/0/tire_pressure/1") << endl; // Prints 39.9
|
||||
for (dom::element car_element : cars) {
|
||||
dom::object car;
|
||||
dom::object car; // invalid until the get() succeeds
|
||||
simdjson::error_code error;
|
||||
if ((error = car_element.get(car))) { std::cerr << error << std::endl; return; }
|
||||
double x = car.at_pointer("/tire_pressure/1");
|
||||
@@ -283,11 +284,11 @@ it selects the key "count" within that object.
|
||||
|
||||
int main(void) {
|
||||
simdjson::dom::parser parser;
|
||||
simdjson::dom::element tweets;
|
||||
simdjson::dom::element tweets; // invalid until the get() succeeds
|
||||
auto error = parser.load("twitter.json").get(tweets);
|
||||
if (error) { std::cerr << error << std::endl; return EXIT_FAILURE; }
|
||||
|
||||
simdjson::dom::element res;
|
||||
simdjson::dom::element res; // invalid until the get() succeeds
|
||||
if ((error = tweets["search_metadata"]["count"].get(res))) {
|
||||
std::cerr << "could not access keys" << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
@@ -311,7 +312,7 @@ Observe how we use the `at` method when querying an index into an array, and not
|
||||
|
||||
int main(void) {
|
||||
simdjson::dom::parser parser;
|
||||
simdjson::dom::element tweets;
|
||||
simdjson::dom::element tweets; // invalid until the get() succeeds
|
||||
auto error = parser.load("twitter.json").get(tweets);
|
||||
if(error) { std::cerr << error << std::endl; return EXIT_FAILURE; }
|
||||
uint64_t identifier;
|
||||
@@ -336,7 +337,7 @@ auto cars_json = R"( [
|
||||
{ "make": "Toyota", "model": "Tercel", "year": 1999, "tire_pressure": [ 29.8, 30.0, 30.2, 30.5 ] }
|
||||
] )"_padded;
|
||||
dom::parser parser;
|
||||
dom::array cars;
|
||||
dom::array cars; // invalid until the get() succeeds
|
||||
auto error = parser.parse(cars_json).get(cars);
|
||||
if (error) { cerr << error << endl; exit(1); }
|
||||
|
||||
@@ -382,7 +383,7 @@ auto abstract_json = R"( [
|
||||
{ "12545" : {"a":11.44, "b":12.78, "c": 11111111} }
|
||||
] )"_padded;
|
||||
dom::parser parser;
|
||||
dom::array array;
|
||||
dom::array array; // invalid until after the next line
|
||||
auto error = parser.parse(abstract_json).get(array);
|
||||
if (error) { cerr << error << endl; exit(1); }
|
||||
// Iterate through an array of objects
|
||||
@@ -436,7 +437,7 @@ bool parse_double(const char *j, double &d) {
|
||||
|
||||
bool parse_string(const char *j, std::string &s) {
|
||||
std::string_view answer;
|
||||
auto error = parser.parse(j,strlen(j))
|
||||
auto error = parser.parse(j, strlen(j))
|
||||
.at(0)
|
||||
.get(answer, error);
|
||||
if (error) { return false; }
|
||||
|
||||
@@ -21,7 +21,7 @@ The current implementations are:
|
||||
* haswell: AVX2 (2013 Intel Haswell or later)
|
||||
* westmere: SSE4.2 (2010 Westmere or later).
|
||||
* arm64: 64-bit ARMv8-A NEON
|
||||
* ppc64: 64-bit POWER8 and POWER9 with VSX and ALTIVEC extensions. Both big endian and little endian are implemented, depends on the compiler you are using.
|
||||
* ppc64: 64-bit POWER8 and POWER9 with VSX and ALTIVEC extensions. Both big endian and little endian are implemented, depends on the compiler you are using. The library is tested on recent, little-endian, POWER systems.
|
||||
* fallback: A generic implementation that runs on any 64-bit processor.
|
||||
|
||||
In many cases, you don't know where your compiled binary is going to run, so simdjson automatically
|
||||
@@ -51,7 +51,7 @@ Inspecting the Detected Implementation
|
||||
You can check what implementation is running with `active_implementation`:
|
||||
|
||||
```c++
|
||||
cout << "simdjson v" << SIMDJSON_STRINGIFY(SIMDJSON_VERSION) << endl;
|
||||
cout << "simdjson v" << SIMDJSON_VERSION << endl;
|
||||
cout << "Detected the best implementation for your machine: " << simdjson::get_active_implementation()->name();
|
||||
cout << "(" << simdjson::get_active_implementation()->description() << ")" << endl;
|
||||
```
|
||||
|
||||
@@ -12,6 +12,9 @@ using namespace simdjson;
|
||||
using namespace simdjson::dom;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
class implementation final : public simdjson::implementation {
|
||||
public:
|
||||
simdjson_inline implementation() : simdjson::implementation("arm64", "ARM NEON", internal::instruction_set::NEON) {}
|
||||
|
||||
@@ -70,7 +70,7 @@ constexpr size_t DEFAULT_MAX_DEPTH = 1024;
|
||||
|
||||
#define SIMDJSON_ISALIGNED_N(ptr, n) (((uintptr_t)(ptr) & ((n)-1)) == 0)
|
||||
|
||||
#if defined(SIMDJSON_REGULAR_VISUAL_STUDIO)
|
||||
#if SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||
|
||||
#define simdjson_really_inline __forceinline
|
||||
#define simdjson_never_inline __declspec(noinline)
|
||||
@@ -155,7 +155,7 @@ constexpr size_t DEFAULT_MAX_DEPTH = 1024;
|
||||
|
||||
#define SIMDJSON_PRAGMA(P) _Pragma(#P)
|
||||
#define SIMDJSON_DISABLE_GCC_WARNING(WARNING) SIMDJSON_PRAGMA(GCC diagnostic ignored #WARNING)
|
||||
#if defined(SIMDJSON_CLANG_VISUAL_STUDIO)
|
||||
#if SIMDJSON_CLANG_VISUAL_STUDIO
|
||||
#define SIMDJSON_DISABLE_UNDESIRED_WARNINGS SIMDJSON_DISABLE_GCC_WARNING(-Wmicrosoft-include)
|
||||
#else
|
||||
#define SIMDJSON_DISABLE_UNDESIRED_WARNINGS
|
||||
@@ -180,7 +180,7 @@ constexpr size_t DEFAULT_MAX_DEPTH = 1024;
|
||||
#define simdjson_inline simdjson_really_inline
|
||||
#endif
|
||||
|
||||
#if defined(SIMDJSON_VISUAL_STUDIO)
|
||||
#if SIMDJSON_VISUAL_STUDIO
|
||||
/**
|
||||
* Windows users need to do some extra work when building
|
||||
* or using a dynamic library (DLL). When building, we need
|
||||
@@ -322,4 +322,11 @@ namespace std {
|
||||
# define simdjson_fallthrough do {} while (0) /* fallthrough */
|
||||
#endif // simdjson_fallthrough
|
||||
|
||||
|
||||
#if SIMDJSON_DEVELOPMENT_CHECKS
|
||||
#define SIMDJSON_DEVELOPMENT_ASSERT(expr) do { assert ((expr)); } while (0)
|
||||
#else
|
||||
#define SIMDJSON_DEVELOPMENT_ASSERT(expr) do { } while (0)
|
||||
#endif
|
||||
|
||||
#endif // SIMDJSON_COMMON_DEFS_H
|
||||
|
||||
@@ -53,18 +53,23 @@ namespace dom {
|
||||
simdjson_inline array::array() noexcept : tape{} {}
|
||||
simdjson_inline array::array(const internal::tape_ref &_tape) noexcept : tape{_tape} {}
|
||||
inline array::iterator array::begin() const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
return internal::tape_ref(tape.doc, tape.json_index + 1);
|
||||
}
|
||||
inline array::iterator array::end() const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
return internal::tape_ref(tape.doc, tape.after_element() - 1);
|
||||
}
|
||||
inline size_t array::size() const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
return tape.scope_count();
|
||||
}
|
||||
inline size_t array::number_of_slots() const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
return tape.matching_brace_index() - tape.json_index;
|
||||
}
|
||||
inline simdjson_result<element> array::at_pointer(std::string_view json_pointer) const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
if(json_pointer.empty()) { // an empty string means that we return the current node
|
||||
return element(this->tape); // copy the current node
|
||||
} else if(json_pointer[0] != '/') { // otherwise there is an error
|
||||
@@ -105,6 +110,7 @@ inline simdjson_result<element> array::at_pointer(std::string_view json_pointer)
|
||||
}
|
||||
|
||||
inline simdjson_result<element> array::at(size_t index) const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
size_t i=0;
|
||||
for (auto element : *this) {
|
||||
if (i == index) { return element; }
|
||||
|
||||
@@ -186,11 +186,13 @@ simdjson_inline element::element() noexcept : tape{} {}
|
||||
simdjson_inline element::element(const internal::tape_ref &_tape) noexcept : tape{_tape} { }
|
||||
|
||||
inline element_type element::type() const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
auto tape_type = tape.tape_ref_type();
|
||||
return tape_type == internal::tape_type::FALSE_VALUE ? element_type::BOOL : static_cast<element_type>(tape_type);
|
||||
}
|
||||
|
||||
inline simdjson_result<bool> element::get_bool() const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
if(tape.is_true()) {
|
||||
return true;
|
||||
} else if(tape.is_false()) {
|
||||
@@ -199,6 +201,7 @@ inline simdjson_result<bool> element::get_bool() const noexcept {
|
||||
return INCORRECT_TYPE;
|
||||
}
|
||||
inline simdjson_result<const char *> element::get_c_str() const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
switch (tape.tape_ref_type()) {
|
||||
case internal::tape_type::STRING: {
|
||||
return tape.get_c_str();
|
||||
@@ -208,6 +211,7 @@ inline simdjson_result<const char *> element::get_c_str() const noexcept {
|
||||
}
|
||||
}
|
||||
inline simdjson_result<size_t> element::get_string_length() const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
switch (tape.tape_ref_type()) {
|
||||
case internal::tape_type::STRING: {
|
||||
return tape.get_string_length();
|
||||
@@ -217,6 +221,7 @@ inline simdjson_result<size_t> element::get_string_length() const noexcept {
|
||||
}
|
||||
}
|
||||
inline simdjson_result<std::string_view> element::get_string() const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
switch (tape.tape_ref_type()) {
|
||||
case internal::tape_type::STRING:
|
||||
return tape.get_string_view();
|
||||
@@ -225,6 +230,7 @@ inline simdjson_result<std::string_view> element::get_string() const noexcept {
|
||||
}
|
||||
}
|
||||
inline simdjson_result<uint64_t> element::get_uint64() const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
if(simdjson_unlikely(!tape.is_uint64())) { // branch rarely taken
|
||||
if(tape.is_int64()) {
|
||||
int64_t result = tape.next_tape_value<int64_t>();
|
||||
@@ -238,6 +244,7 @@ inline simdjson_result<uint64_t> element::get_uint64() const noexcept {
|
||||
return tape.next_tape_value<int64_t>();
|
||||
}
|
||||
inline simdjson_result<int64_t> element::get_int64() const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
if(simdjson_unlikely(!tape.is_int64())) { // branch rarely taken
|
||||
if(tape.is_uint64()) {
|
||||
uint64_t result = tape.next_tape_value<uint64_t>();
|
||||
@@ -252,6 +259,7 @@ inline simdjson_result<int64_t> element::get_int64() const noexcept {
|
||||
return tape.next_tape_value<int64_t>();
|
||||
}
|
||||
inline simdjson_result<double> element::get_double() const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
// Performance considerations:
|
||||
// 1. Querying tape_ref_type() implies doing a shift, it is fast to just do a straight
|
||||
// comparison.
|
||||
@@ -273,6 +281,7 @@ inline simdjson_result<double> element::get_double() const noexcept {
|
||||
return tape.next_tape_value<double>();
|
||||
}
|
||||
inline simdjson_result<array> element::get_array() const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
switch (tape.tape_ref_type()) {
|
||||
case internal::tape_type::START_ARRAY:
|
||||
return array(tape);
|
||||
@@ -281,6 +290,7 @@ inline simdjson_result<array> element::get_array() const noexcept {
|
||||
}
|
||||
}
|
||||
inline simdjson_result<object> element::get_object() const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
switch (tape.tape_ref_type()) {
|
||||
case internal::tape_type::START_OBJECT:
|
||||
return object(tape);
|
||||
@@ -360,6 +370,7 @@ inline simdjson_result<element> element::operator[](const char *key) const noexc
|
||||
}
|
||||
|
||||
inline simdjson_result<element> element::at_pointer(std::string_view json_pointer) const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
switch (tape.tape_ref_type()) {
|
||||
case internal::tape_type::START_OBJECT:
|
||||
return object(tape).at_pointer(json_pointer);
|
||||
@@ -395,6 +406,7 @@ inline simdjson_result<element> element::at_key_case_insensitive(std::string_vie
|
||||
}
|
||||
|
||||
inline bool element::dump_raw_tape(std::ostream &out) const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
return tape.doc->dump_raw_tape(out);
|
||||
}
|
||||
|
||||
|
||||
@@ -65,12 +65,15 @@ namespace dom {
|
||||
simdjson_inline object::object() noexcept : tape{} {}
|
||||
simdjson_inline object::object(const internal::tape_ref &_tape) noexcept : tape{_tape} { }
|
||||
inline object::iterator object::begin() const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
return internal::tape_ref(tape.doc, tape.json_index + 1);
|
||||
}
|
||||
inline object::iterator object::end() const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
return internal::tape_ref(tape.doc, tape.after_element() - 1);
|
||||
}
|
||||
inline size_t object::size() const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
return tape.scope_count();
|
||||
}
|
||||
|
||||
@@ -81,6 +84,7 @@ inline simdjson_result<element> object::operator[](const char *key) const noexce
|
||||
return at_key(key);
|
||||
}
|
||||
inline simdjson_result<element> object::at_pointer(std::string_view json_pointer) const noexcept {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
if(json_pointer.empty()) { // an empty string means that we return the current node
|
||||
return element(this->tape); // copy the current node
|
||||
} else if(json_pointer[0] != '/') { // otherwise there is an error
|
||||
|
||||
@@ -43,7 +43,7 @@ inline simdjson_result<size_t> parser::read_file(const std::string &path) noexce
|
||||
|
||||
// Get the file size
|
||||
int ret;
|
||||
#if defined(SIMDJSON_VISUAL_STUDIO) && !SIMDJSON_IS_32BITS
|
||||
#if SIMDJSON_VISUAL_STUDIO && !SIMDJSON_IS_32BITS
|
||||
ret = _fseeki64(fp, 0, SEEK_END);
|
||||
#else
|
||||
ret = std::fseek(fp, 0, SEEK_END);
|
||||
@@ -52,7 +52,7 @@ inline simdjson_result<size_t> parser::read_file(const std::string &path) noexce
|
||||
std::fclose(fp);
|
||||
return IO_ERROR;
|
||||
}
|
||||
#if defined(SIMDJSON_VISUAL_STUDIO) && !SIMDJSON_IS_32BITS
|
||||
#if SIMDJSON_VISUAL_STUDIO && !SIMDJSON_IS_32BITS
|
||||
__int64 len = _ftelli64(fp);
|
||||
if(len == -1L) {
|
||||
std::fclose(fp);
|
||||
@@ -148,6 +148,9 @@ simdjson_inline simdjson_result<element> parser::parse(const std::string &s) & n
|
||||
simdjson_inline simdjson_result<element> parser::parse(const padded_string &s) & noexcept {
|
||||
return parse(s.data(), s.length(), false);
|
||||
}
|
||||
simdjson_inline simdjson_result<element> parser::parse(const padded_string_view &v) & noexcept {
|
||||
return parse(v.data(), v.length(), false);
|
||||
}
|
||||
|
||||
inline simdjson_result<document_stream> parser::parse_many(const uint8_t *buf, size_t len, size_t batch_size) noexcept {
|
||||
if(batch_size < MINIMAL_BATCH_SIZE) { batch_size = MINIMAL_BATCH_SIZE; }
|
||||
|
||||
@@ -199,6 +199,9 @@ public:
|
||||
/** @overload parse(const uint8_t *buf, size_t len, bool realloc_if_needed) */
|
||||
simdjson_inline simdjson_result<element> parse(const padded_string &s) & noexcept;
|
||||
simdjson_inline simdjson_result<element> parse(const padded_string &s) && =delete;
|
||||
/** @overload parse(const uint8_t *buf, size_t len, bool realloc_if_needed) */
|
||||
simdjson_inline simdjson_result<element> parse(const padded_string_view &v) & noexcept;
|
||||
simdjson_inline simdjson_result<element> parse(const padded_string_view &v) && =delete;
|
||||
|
||||
/** @private We do not want to allow implicit conversion from C string to std::string. */
|
||||
simdjson_inline simdjson_result<element> parse(const char *buf) noexcept = delete;
|
||||
|
||||
@@ -11,6 +11,9 @@ using namespace simdjson;
|
||||
using namespace simdjson::dom;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
class implementation final : public simdjson::implementation {
|
||||
public:
|
||||
simdjson_inline implementation() : simdjson::implementation(
|
||||
|
||||
@@ -72,7 +72,7 @@ simdjson_inline size_t codepoint_to_utf8(uint32_t cp, uint8_t *c) {
|
||||
return 0; // bad r
|
||||
}
|
||||
|
||||
#ifdef SIMDJSON_IS_32BITS // _umul128 for x86, arm
|
||||
#if SIMDJSON_IS_32BITS // _umul128 for x86, arm
|
||||
// this is a slow emulation routine for 32-bit
|
||||
//
|
||||
static simdjson_inline uint64_t __emulu(uint32_t x, uint32_t y) {
|
||||
@@ -94,7 +94,7 @@ using internal::value128;
|
||||
|
||||
simdjson_inline value128 full_multiplication(uint64_t value1, uint64_t value2) {
|
||||
value128 answer;
|
||||
#if defined(SIMDJSON_REGULAR_VISUAL_STUDIO) || defined(SIMDJSON_IS_32BITS)
|
||||
#if SIMDJSON_REGULAR_VISUAL_STUDIO || SIMDJSON_IS_32BITS
|
||||
#ifdef _M_ARM64
|
||||
// ARM64 has native support for 64-bit multiplications, no need to emultate
|
||||
answer.high = __umulh(value1, value2);
|
||||
@@ -102,7 +102,7 @@ simdjson_inline value128 full_multiplication(uint64_t value1, uint64_t value2) {
|
||||
#else
|
||||
answer.low = _umul128(value1, value2, &answer.high); // _umul128 not available on ARM64
|
||||
#endif // _M_ARM64
|
||||
#else // defined(SIMDJSON_REGULAR_VISUAL_STUDIO) || defined(SIMDJSON_IS_32BITS)
|
||||
#else // SIMDJSON_REGULAR_VISUAL_STUDIO || SIMDJSON_IS_32BITS
|
||||
__uint128_t r = (static_cast<__uint128_t>(value1)) * value2;
|
||||
answer.low = uint64_t(r);
|
||||
answer.high = uint64_t(r >> 64);
|
||||
|
||||
@@ -67,35 +67,44 @@ simdjson_inline simdjson_result<object> document::get_object() & noexcept {
|
||||
auto value = get_root_value_iterator();
|
||||
return object::start_root(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* We decided that calling 'get_double()' on the JSON document '1.233 blabla' should
|
||||
* give an error, so we check for trailing content. We want to disallow trailing
|
||||
* content.
|
||||
* Thus, in several implementations below, we pass a 'true' parameter value to
|
||||
* a get_root_value_iterator() method: this indicates that we disallow trailing content.
|
||||
*/
|
||||
|
||||
simdjson_inline simdjson_result<uint64_t> document::get_uint64() noexcept {
|
||||
return get_root_value_iterator().get_root_uint64();
|
||||
return get_root_value_iterator().get_root_uint64(true);
|
||||
}
|
||||
simdjson_inline simdjson_result<uint64_t> document::get_uint64_in_string() noexcept {
|
||||
return get_root_value_iterator().get_root_uint64_in_string();
|
||||
return get_root_value_iterator().get_root_uint64_in_string(true);
|
||||
}
|
||||
simdjson_inline simdjson_result<int64_t> document::get_int64() noexcept {
|
||||
return get_root_value_iterator().get_root_int64();
|
||||
return get_root_value_iterator().get_root_int64(true);
|
||||
}
|
||||
simdjson_inline simdjson_result<int64_t> document::get_int64_in_string() noexcept {
|
||||
return get_root_value_iterator().get_root_int64_in_string();
|
||||
return get_root_value_iterator().get_root_int64_in_string(true);
|
||||
}
|
||||
simdjson_inline simdjson_result<double> document::get_double() noexcept {
|
||||
return get_root_value_iterator().get_root_double();
|
||||
return get_root_value_iterator().get_root_double(true);
|
||||
}
|
||||
simdjson_inline simdjson_result<double> document::get_double_in_string() noexcept {
|
||||
return get_root_value_iterator().get_root_double_in_string();
|
||||
return get_root_value_iterator().get_root_double_in_string(true);
|
||||
}
|
||||
simdjson_inline simdjson_result<std::string_view> document::get_string() noexcept {
|
||||
return get_root_value_iterator().get_root_string();
|
||||
return get_root_value_iterator().get_root_string(true);
|
||||
}
|
||||
simdjson_inline simdjson_result<raw_json_string> document::get_raw_json_string() noexcept {
|
||||
return get_root_value_iterator().get_root_raw_json_string();
|
||||
return get_root_value_iterator().get_root_raw_json_string(true);
|
||||
}
|
||||
simdjson_inline simdjson_result<bool> document::get_bool() noexcept {
|
||||
return get_root_value_iterator().get_root_bool();
|
||||
return get_root_value_iterator().get_root_bool(true);
|
||||
}
|
||||
simdjson_inline bool document::is_null() noexcept {
|
||||
return get_root_value_iterator().is_root_null();
|
||||
simdjson_inline simdjson_result<bool> document::is_null() noexcept {
|
||||
return get_root_value_iterator().is_root_null(true);
|
||||
}
|
||||
|
||||
template<> simdjson_inline simdjson_result<array> document::get() & noexcept { return get_array(); }
|
||||
@@ -213,15 +222,15 @@ simdjson_inline bool document::is_negative() noexcept {
|
||||
}
|
||||
|
||||
simdjson_inline simdjson_result<bool> document::is_integer() noexcept {
|
||||
return get_root_value_iterator().is_root_integer();
|
||||
return get_root_value_iterator().is_root_integer(true);
|
||||
}
|
||||
|
||||
simdjson_inline simdjson_result<number_type> document::get_number_type() noexcept {
|
||||
return get_root_value_iterator().get_root_number_type();
|
||||
return get_root_value_iterator().get_root_number_type(true);
|
||||
}
|
||||
|
||||
simdjson_inline simdjson_result<number> document::get_number() noexcept {
|
||||
return get_root_value_iterator().get_root_number();
|
||||
return get_root_value_iterator().get_root_number(true);
|
||||
}
|
||||
|
||||
|
||||
@@ -330,14 +339,26 @@ simdjson_inline simdjson_result<uint64_t> simdjson_result<SIMDJSON_IMPLEMENTATIO
|
||||
if (error()) { return error(); }
|
||||
return first.get_uint64();
|
||||
}
|
||||
simdjson_inline simdjson_result<uint64_t> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::get_uint64_in_string() noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first.get_uint64_in_string();
|
||||
}
|
||||
simdjson_inline simdjson_result<int64_t> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::get_int64() noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first.get_int64();
|
||||
}
|
||||
simdjson_inline simdjson_result<int64_t> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::get_int64_in_string() noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first.get_int64_in_string();
|
||||
}
|
||||
simdjson_inline simdjson_result<double> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::get_double() noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first.get_double();
|
||||
}
|
||||
simdjson_inline simdjson_result<double> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::get_double_in_string() noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first.get_double_in_string();
|
||||
}
|
||||
simdjson_inline simdjson_result<std::string_view> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::get_string() noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first.get_string();
|
||||
@@ -354,7 +375,7 @@ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjs
|
||||
if (error()) { return error(); }
|
||||
return first.get_value();
|
||||
}
|
||||
simdjson_inline bool simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::is_null() noexcept {
|
||||
simdjson_inline simdjson_result<bool> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::is_null() noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first.is_null();
|
||||
}
|
||||
@@ -497,24 +518,41 @@ simdjson_inline document_reference::document_reference(document &d) noexcept : d
|
||||
simdjson_inline void document_reference::rewind() noexcept { doc->rewind(); }
|
||||
simdjson_inline simdjson_result<array> document_reference::get_array() & noexcept { return doc->get_array(); }
|
||||
simdjson_inline simdjson_result<object> document_reference::get_object() & noexcept { return doc->get_object(); }
|
||||
simdjson_inline simdjson_result<uint64_t> document_reference::get_uint64() noexcept { return doc->get_uint64(); }
|
||||
simdjson_inline simdjson_result<int64_t> document_reference::get_int64() noexcept { return doc->get_int64(); }
|
||||
simdjson_inline simdjson_result<double> document_reference::get_double() noexcept { return doc->get_double(); }
|
||||
simdjson_inline simdjson_result<std::string_view> document_reference::get_string() noexcept { return doc->get_string(); }
|
||||
simdjson_inline simdjson_result<raw_json_string> document_reference::get_raw_json_string() noexcept { return doc->get_raw_json_string(); }
|
||||
simdjson_inline simdjson_result<bool> document_reference::get_bool() noexcept { return doc->get_bool(); }
|
||||
/**
|
||||
* The document_reference instances are used primarily/solely for streams of JSON
|
||||
* documents.
|
||||
* We decided that calling 'get_double()' on the JSON document '1.233 blabla' should
|
||||
* give an error, so we check for trailing content.
|
||||
*
|
||||
* However, for streams of JSON documents, we want to be able to start from
|
||||
* "321" "321" "321"
|
||||
* and parse it successfully as a stream of JSON documents, calling get_uint64_in_string()
|
||||
* successfully each time.
|
||||
*
|
||||
* To achieve this result, we pass a 'false' to a get_root_value_iterator() method:
|
||||
* this indicates that we allow trailing content.
|
||||
*/
|
||||
simdjson_inline simdjson_result<uint64_t> document_reference::get_uint64() noexcept { return doc->get_root_value_iterator().get_root_uint64(false); }
|
||||
simdjson_inline simdjson_result<uint64_t> document_reference::get_uint64_in_string() noexcept { return doc->get_root_value_iterator().get_root_uint64_in_string(false); }
|
||||
simdjson_inline simdjson_result<int64_t> document_reference::get_int64() noexcept { return doc->get_root_value_iterator().get_root_int64(false); }
|
||||
simdjson_inline simdjson_result<int64_t> document_reference::get_int64_in_string() noexcept { return doc->get_root_value_iterator().get_root_int64_in_string(false); }
|
||||
simdjson_inline simdjson_result<double> document_reference::get_double() noexcept { return doc->get_root_value_iterator().get_root_double(false); }
|
||||
simdjson_inline simdjson_result<double> document_reference::get_double_in_string() noexcept { return doc->get_root_value_iterator().get_root_double(false); }
|
||||
simdjson_inline simdjson_result<std::string_view> document_reference::get_string() noexcept { return doc->get_root_value_iterator().get_root_string(false); }
|
||||
simdjson_inline simdjson_result<raw_json_string> document_reference::get_raw_json_string() noexcept { return doc->get_root_value_iterator().get_root_raw_json_string(false); }
|
||||
simdjson_inline simdjson_result<bool> document_reference::get_bool() noexcept { return doc->get_root_value_iterator().get_root_bool(false); }
|
||||
simdjson_inline simdjson_result<value> document_reference::get_value() noexcept { return doc->get_value(); }
|
||||
simdjson_inline bool document_reference::is_null() noexcept { return doc->is_null(); }
|
||||
simdjson_inline simdjson_result<bool> document_reference::is_null() noexcept { return doc->get_root_value_iterator().is_root_null(false); }
|
||||
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
simdjson_inline document_reference::operator array() & noexcept(false) { return array(*doc); }
|
||||
simdjson_inline document_reference::operator object() & noexcept(false) { return object(*doc); }
|
||||
simdjson_inline document_reference::operator uint64_t() noexcept(false) { return uint64_t(*doc); }
|
||||
simdjson_inline document_reference::operator int64_t() noexcept(false) { return int64_t(*doc); }
|
||||
simdjson_inline document_reference::operator double() noexcept(false) { return double(*doc); }
|
||||
simdjson_inline document_reference::operator uint64_t() noexcept(false) { return get_uint64(); }
|
||||
simdjson_inline document_reference::operator int64_t() noexcept(false) { return get_int64(); }
|
||||
simdjson_inline document_reference::operator double() noexcept(false) { return get_double(); }
|
||||
simdjson_inline document_reference::operator std::string_view() noexcept(false) { return std::string_view(*doc); }
|
||||
simdjson_inline document_reference::operator raw_json_string() noexcept(false) { return raw_json_string(*doc); }
|
||||
simdjson_inline document_reference::operator bool() noexcept(false) { return bool(*doc); }
|
||||
simdjson_inline document_reference::operator bool() noexcept(false) { return get_bool(); }
|
||||
simdjson_inline document_reference::operator value() noexcept(false) { return value(*doc); }
|
||||
#endif
|
||||
simdjson_inline simdjson_result<size_t> document_reference::count_elements() & noexcept { return doc->count_elements(); }
|
||||
@@ -533,9 +571,9 @@ simdjson_inline simdjson_result<bool> document_reference::is_scalar() noexcept {
|
||||
simdjson_inline simdjson_result<const char *> document_reference::current_location() noexcept { return doc->current_location(); }
|
||||
simdjson_inline int32_t document_reference::current_depth() const noexcept { return doc->current_depth(); }
|
||||
simdjson_inline bool document_reference::is_negative() noexcept { return doc->is_negative(); }
|
||||
simdjson_inline simdjson_result<bool> document_reference::is_integer() noexcept { return doc->is_integer(); }
|
||||
simdjson_inline simdjson_result<number_type> document_reference::get_number_type() noexcept { return doc->get_number_type(); }
|
||||
simdjson_inline simdjson_result<number> document_reference::get_number() noexcept { return doc->get_number(); }
|
||||
simdjson_inline simdjson_result<bool> document_reference::is_integer() noexcept { return doc->get_root_value_iterator().is_root_integer(false); }
|
||||
simdjson_inline simdjson_result<number_type> document_reference::get_number_type() noexcept { return doc->get_root_value_iterator().get_root_number_type(false); }
|
||||
simdjson_inline simdjson_result<number> document_reference::get_number() noexcept { return doc->get_root_value_iterator().get_root_number(false); }
|
||||
simdjson_inline simdjson_result<std::string_view> document_reference::raw_json_token() noexcept { return doc->raw_json_token(); }
|
||||
simdjson_inline simdjson_result<value> document_reference::at_pointer(std::string_view json_pointer) noexcept { return doc->at_pointer(json_pointer); }
|
||||
simdjson_inline simdjson_result<std::string_view> document_reference::raw_json() noexcept { return doc->raw_json();}
|
||||
@@ -612,14 +650,26 @@ simdjson_inline simdjson_result<uint64_t> simdjson_result<SIMDJSON_IMPLEMENTATIO
|
||||
if (error()) { return error(); }
|
||||
return first.get_uint64();
|
||||
}
|
||||
simdjson_inline simdjson_result<uint64_t> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::get_uint64_in_string() noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first.get_uint64_in_string();
|
||||
}
|
||||
simdjson_inline simdjson_result<int64_t> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::get_int64() noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first.get_int64();
|
||||
}
|
||||
simdjson_inline simdjson_result<int64_t> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::get_int64_in_string() noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first.get_int64_in_string();
|
||||
}
|
||||
simdjson_inline simdjson_result<double> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::get_double() noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first.get_double();
|
||||
}
|
||||
simdjson_inline simdjson_result<double> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::get_double_in_string() noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first.get_double_in_string();
|
||||
}
|
||||
simdjson_inline simdjson_result<std::string_view> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::get_string() noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first.get_string();
|
||||
@@ -636,7 +686,7 @@ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjs
|
||||
if (error()) { return error(); }
|
||||
return first.get_value();
|
||||
}
|
||||
simdjson_inline bool simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::is_null() noexcept {
|
||||
simdjson_inline simdjson_result<bool> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::is_null() noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first.is_null();
|
||||
}
|
||||
@@ -648,7 +698,7 @@ simdjson_inline simdjson_result<bool> simdjson_result<SIMDJSON_IMPLEMENTATION::o
|
||||
if (error()) { return error(); }
|
||||
return first.is_scalar();
|
||||
}
|
||||
simdjson_inline bool simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::is_negative() noexcept {
|
||||
simdjson_inline simdjson_result<bool> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::is_negative() noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first.is_negative();
|
||||
}
|
||||
|
||||
@@ -126,11 +126,14 @@ public:
|
||||
simdjson_inline simdjson_result<value> get_value() noexcept;
|
||||
|
||||
/**
|
||||
* Checks if this JSON value is null.
|
||||
* Checks if this JSON value is null. If and only if the value is
|
||||
* null, then it is consumed (we advance). If we find a token that
|
||||
* begins with 'n' but is not 'null', then an error is returned.
|
||||
*
|
||||
* @returns Whether the value is null.
|
||||
* @returns INCORRECT_TYPE If the JSON value begins with 'n' and is not 'null'.
|
||||
*/
|
||||
simdjson_inline bool is_null() noexcept;
|
||||
simdjson_inline simdjson_result<bool> is_null() noexcept;
|
||||
|
||||
/**
|
||||
* Get this value as the given type.
|
||||
@@ -363,7 +366,9 @@ public:
|
||||
simdjson_inline simdjson_result<value> operator[](const char *key) & noexcept;
|
||||
|
||||
/**
|
||||
* Get the type of this JSON value.
|
||||
* Get the type of this JSON value. It does not validate or consume the value.
|
||||
* E.g., you must still call "is_null()" to check that a value is null even if
|
||||
* "type()" returns json_type::null.
|
||||
*
|
||||
* NOTE: If you're only expecting a value to be one type (a typical case), it's generally
|
||||
* better to just call .get_double, .get_string, etc. and check for INCORRECT_TYPE (or just
|
||||
@@ -572,6 +577,7 @@ protected:
|
||||
friend class field;
|
||||
friend class token;
|
||||
friend class document_stream;
|
||||
friend class document_reference;
|
||||
};
|
||||
|
||||
|
||||
@@ -588,14 +594,17 @@ public:
|
||||
simdjson_inline simdjson_result<array> get_array() & noexcept;
|
||||
simdjson_inline simdjson_result<object> get_object() & noexcept;
|
||||
simdjson_inline simdjson_result<uint64_t> get_uint64() noexcept;
|
||||
simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
|
||||
simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
|
||||
simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
|
||||
simdjson_inline simdjson_result<double> get_double() noexcept;
|
||||
simdjson_inline simdjson_result<double> get_double_in_string() noexcept;
|
||||
simdjson_inline simdjson_result<std::string_view> get_string() noexcept;
|
||||
simdjson_inline simdjson_result<raw_json_string> get_raw_json_string() noexcept;
|
||||
simdjson_inline simdjson_result<bool> get_bool() noexcept;
|
||||
simdjson_inline simdjson_result<value> get_value() noexcept;
|
||||
|
||||
simdjson_inline bool is_null() noexcept;
|
||||
simdjson_inline simdjson_result<bool> is_null() noexcept;
|
||||
simdjson_inline simdjson_result<std::string_view> raw_json() noexcept;
|
||||
simdjson_inline operator document&() const noexcept;
|
||||
|
||||
@@ -653,14 +662,16 @@ public:
|
||||
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array> get_array() & noexcept;
|
||||
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object> get_object() & noexcept;
|
||||
simdjson_inline simdjson_result<uint64_t> get_uint64() noexcept;
|
||||
simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
|
||||
simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
|
||||
simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
|
||||
simdjson_inline simdjson_result<double> get_double() noexcept;
|
||||
simdjson_inline simdjson_result<double> get_double_from_string() noexcept;
|
||||
simdjson_inline simdjson_result<double> get_double_in_string() noexcept;
|
||||
simdjson_inline simdjson_result<std::string_view> get_string() noexcept;
|
||||
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string> get_raw_json_string() noexcept;
|
||||
simdjson_inline simdjson_result<bool> get_bool() noexcept;
|
||||
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> get_value() noexcept;
|
||||
simdjson_inline bool is_null() noexcept;
|
||||
simdjson_inline simdjson_result<bool> is_null() noexcept;
|
||||
|
||||
template<typename T> simdjson_inline simdjson_result<T> get() & noexcept;
|
||||
template<typename T> simdjson_inline simdjson_result<T> get() && noexcept;
|
||||
@@ -721,13 +732,16 @@ public:
|
||||
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array> get_array() & noexcept;
|
||||
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object> get_object() & noexcept;
|
||||
simdjson_inline simdjson_result<uint64_t> get_uint64() noexcept;
|
||||
simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
|
||||
simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
|
||||
simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
|
||||
simdjson_inline simdjson_result<double> get_double() noexcept;
|
||||
simdjson_inline simdjson_result<double> get_double_in_string() noexcept;
|
||||
simdjson_inline simdjson_result<std::string_view> get_string() noexcept;
|
||||
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string> get_raw_json_string() noexcept;
|
||||
simdjson_inline simdjson_result<bool> get_bool() noexcept;
|
||||
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> get_value() noexcept;
|
||||
simdjson_inline bool is_null() noexcept;
|
||||
simdjson_inline simdjson_result<bool> is_null() noexcept;
|
||||
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
simdjson_inline operator SIMDJSON_IMPLEMENTATION::ondemand::array() & noexcept(false);
|
||||
@@ -754,8 +768,8 @@ public:
|
||||
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::json_type> type() noexcept;
|
||||
simdjson_inline simdjson_result<bool> is_scalar() noexcept;
|
||||
simdjson_inline simdjson_result<const char *> current_location() noexcept;
|
||||
simdjson_inline int32_t current_depth() const noexcept;
|
||||
simdjson_inline bool is_negative() noexcept;
|
||||
simdjson_inline simdjson_result<int32_t> current_depth() const noexcept;
|
||||
simdjson_inline simdjson_result<bool> is_negative() noexcept;
|
||||
simdjson_inline simdjson_result<bool> is_integer() noexcept;
|
||||
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::number_type> get_number_type() noexcept;
|
||||
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::number> get_number() noexcept;
|
||||
|
||||
@@ -325,6 +325,7 @@ simdjson_inline void json_iterator::reenter_child(token_position position, depth
|
||||
SIMDJSON_ASSUME(_depth == child_depth - 1);
|
||||
#if SIMDJSON_DEVELOPMENT_CHECKS
|
||||
#ifndef SIMDJSON_CLANG_VISUAL_STUDIO
|
||||
SIMDJSON_ASSUME(size_t(child_depth) < parser->max_depth());
|
||||
SIMDJSON_ASSUME(position >= parser->start_positions[child_depth]);
|
||||
#endif
|
||||
#endif
|
||||
@@ -335,11 +336,13 @@ simdjson_inline void json_iterator::reenter_child(token_position position, depth
|
||||
#if SIMDJSON_DEVELOPMENT_CHECKS
|
||||
|
||||
simdjson_inline token_position json_iterator::start_position(depth_t depth) const noexcept {
|
||||
return parser->start_positions[depth];
|
||||
SIMDJSON_ASSUME(size_t(depth) < parser->max_depth());
|
||||
return size_t(depth) < parser->max_depth() ? parser->start_positions[depth] : 0;
|
||||
}
|
||||
|
||||
simdjson_inline void json_iterator::set_start_position(depth_t depth, token_position position) noexcept {
|
||||
parser->start_positions[depth] = position;
|
||||
SIMDJSON_ASSUME(size_t(depth) < parser->max_depth());
|
||||
if(size_t(depth) < parser->max_depth()) { parser->start_positions[depth] = position; }
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -136,9 +136,15 @@ inline void log_line(const json_iterator &iter, token_position index, depth_t de
|
||||
{
|
||||
// Print the current structural.
|
||||
printf("| ");
|
||||
auto current_structural = &buf[*index];
|
||||
for (int i=0;i<LOG_BUFFER_LEN;i++) {
|
||||
printf("%c", printable_char(current_structural[i]));
|
||||
// Before we begin, the index might point right before the document.
|
||||
// This could be unsafe, see https://github.com/simdjson/simdjson/discussions/1938
|
||||
if(index < iter._root) {
|
||||
printf("%*s", LOG_BUFFER_LEN, "");
|
||||
} else {
|
||||
auto current_structural = &buf[*index];
|
||||
for (int i=0;i<LOG_BUFFER_LEN;i++) {
|
||||
printf("%c", printable_char(current_structural[i]));
|
||||
}
|
||||
}
|
||||
printf(" ");
|
||||
}
|
||||
@@ -153,7 +159,7 @@ inline void log_line(const json_iterator &iter, token_position index, depth_t de
|
||||
}
|
||||
// printf("| %5u ", *(index+1));
|
||||
printf("| %5i ", depth);
|
||||
printf("| %.*s ", int(detail.size()), detail.data());
|
||||
printf("| %6.*s ", int(detail.size()) , detail.data());
|
||||
printf("|\n");
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
@@ -230,13 +230,22 @@ public:
|
||||
/** The maximum capacity of this parser (the largest document it is allowed to process). */
|
||||
simdjson_inline size_t max_capacity() const noexcept;
|
||||
simdjson_inline void set_max_capacity(size_t max_capacity) noexcept;
|
||||
/** The maximum depth of this parser (the most deeply nested objects and arrays it can process). */
|
||||
/**
|
||||
* The maximum depth of this parser (the most deeply nested objects and arrays it can process).
|
||||
* This parameter is only relevant when the macro SIMDJSON_DEVELOPMENT_CHECKS is set to true.
|
||||
* The document's instance current_depth() method should be used to monitor the parsing
|
||||
* depth and limit it if desired.
|
||||
*/
|
||||
simdjson_inline size_t max_depth() const noexcept;
|
||||
|
||||
/**
|
||||
* Ensure this parser has enough memory to process JSON documents up to `capacity` bytes in length
|
||||
* and `max_depth` depth.
|
||||
*
|
||||
* The max_depth parameter is only relevant when the macro SIMDJSON_DEVELOPMENT_CHECKS is set to true.
|
||||
* The document's instance current_depth() method should be used to monitor the parsing
|
||||
* depth and limit it if desired.
|
||||
*
|
||||
* @param capacity The new capacity.
|
||||
* @param max_depth The new max_depth. Defaults to DEFAULT_MAX_DEPTH.
|
||||
* @return The error, if there is one.
|
||||
|
||||
@@ -4,23 +4,27 @@
|
||||
namespace simdjson {
|
||||
/**
|
||||
* Create a string-view instance out of a document instance. The string-view instance
|
||||
* contains JSON text that is suitable to be parsed as JSON again.
|
||||
* contains JSON text that is suitable to be parsed as JSON again. It does not
|
||||
* validate the content.
|
||||
*/
|
||||
inline simdjson_result<std::string_view> to_json_string(SIMDJSON_IMPLEMENTATION::ondemand::document& x) noexcept;
|
||||
/**
|
||||
* Create a string-view instance out of a value instance. The string-view instance
|
||||
* contains JSON text that is suitable to be parsed as JSON again. The value must
|
||||
* not have been accessed previously.
|
||||
* not have been accessed previously. It does not
|
||||
* validate the content.
|
||||
*/
|
||||
inline simdjson_result<std::string_view> to_json_string(SIMDJSON_IMPLEMENTATION::ondemand::value& x) noexcept;
|
||||
/**
|
||||
* Create a string-view instance out of an object instance. The string-view instance
|
||||
* contains JSON text that is suitable to be parsed as JSON again.
|
||||
* contains JSON text that is suitable to be parsed as JSON again. It does not
|
||||
* validate the content.
|
||||
*/
|
||||
inline simdjson_result<std::string_view> to_json_string(SIMDJSON_IMPLEMENTATION::ondemand::object& x) noexcept;
|
||||
/**
|
||||
* Create a string-view instance out of an array instance. The string-view instance
|
||||
* contains JSON text that is suitable to be parsed as JSON again.
|
||||
* contains JSON text that is suitable to be parsed as JSON again. It does not
|
||||
* validate the content.
|
||||
*/
|
||||
inline simdjson_result<std::string_view> to_json_string(SIMDJSON_IMPLEMENTATION::ondemand::array& x) noexcept;
|
||||
inline simdjson_result<std::string_view> to_json_string(simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document> x);
|
||||
@@ -39,7 +43,8 @@ inline simdjson_result<std::string_view> to_json_string(simdjson_result<SIMDJSON
|
||||
namespace simdjson { namespace SIMDJSON_IMPLEMENTATION { namespace ondemand {
|
||||
|
||||
/**
|
||||
* Print JSON to an output stream.
|
||||
* Print JSON to an output stream. It does not
|
||||
* validate the content.
|
||||
*
|
||||
* @param out The output stream.
|
||||
* @param value The element.
|
||||
@@ -50,7 +55,8 @@ inline std::ostream& operator<<(std::ostream& out, simdjson::SIMDJSON_IMPLEMENTA
|
||||
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::SIMDJSON_IMPLEMENTATION::ondemand::value> x);
|
||||
#endif
|
||||
/**
|
||||
* Print JSON to an output stream.
|
||||
* Print JSON to an output stream. It does not
|
||||
* validate the content.
|
||||
*
|
||||
* @param out The output stream.
|
||||
* @param value The array.
|
||||
@@ -61,7 +67,8 @@ inline std::ostream& operator<<(std::ostream& out, simdjson::SIMDJSON_IMPLEMENTA
|
||||
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::SIMDJSON_IMPLEMENTATION::ondemand::array> x);
|
||||
#endif
|
||||
/**
|
||||
* Print JSON to an output stream.
|
||||
* Print JSON to an output stream. It does not
|
||||
* validate the content.
|
||||
*
|
||||
* @param out The output stream.
|
||||
* @param value The array.
|
||||
@@ -76,7 +83,8 @@ inline std::ostream& operator<<(std::ostream& out, simdjson::SIMDJSON_IMPLEMENTA
|
||||
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::SIMDJSON_IMPLEMENTATION::ondemand::document_reference>&& x);
|
||||
#endif
|
||||
/**
|
||||
* Print JSON to an output stream.
|
||||
* Print JSON to an output stream. It does not
|
||||
* validate the content.
|
||||
*
|
||||
* @param out The output stream.
|
||||
* @param value The object.
|
||||
|
||||
@@ -54,10 +54,9 @@ simdjson_inline simdjson_result<int64_t> value::get_int64_in_string() noexcept {
|
||||
simdjson_inline simdjson_result<bool> value::get_bool() noexcept {
|
||||
return iter.get_bool();
|
||||
}
|
||||
simdjson_inline bool value::is_null() noexcept {
|
||||
simdjson_inline simdjson_result<bool> value::is_null() noexcept {
|
||||
return iter.is_null();
|
||||
}
|
||||
|
||||
template<> simdjson_inline simdjson_result<array> value::get() noexcept { return get_array(); }
|
||||
template<> simdjson_inline simdjson_result<object> value::get() noexcept { return get_object(); }
|
||||
template<> simdjson_inline simdjson_result<raw_json_string> value::get() noexcept { return get_raw_json_string(); }
|
||||
@@ -311,8 +310,8 @@ simdjson_inline simdjson_result<bool> simdjson_result<SIMDJSON_IMPLEMENTATION::o
|
||||
if (error()) { return error(); }
|
||||
return first.get_bool();
|
||||
}
|
||||
simdjson_inline bool simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::is_null() noexcept {
|
||||
if (error()) { return false; }
|
||||
simdjson_inline simdjson_result<bool> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::is_null() noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first.is_null();
|
||||
}
|
||||
|
||||
@@ -404,7 +403,7 @@ simdjson_inline simdjson_result<const char *> simdjson_result<SIMDJSON_IMPLEMENT
|
||||
return first.current_location();
|
||||
}
|
||||
|
||||
simdjson_inline int32_t simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::current_depth() const noexcept {
|
||||
simdjson_inline simdjson_result<int32_t> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::current_depth() const noexcept {
|
||||
if (error()) { return error(); }
|
||||
return first.current_depth();
|
||||
}
|
||||
|
||||
@@ -150,11 +150,14 @@ public:
|
||||
simdjson_inline simdjson_result<bool> get_bool() noexcept;
|
||||
|
||||
/**
|
||||
* Checks if this JSON value is null.
|
||||
* Checks if this JSON value is null. If and only if the value is
|
||||
* null, then it is consumed (we advance). If we find a token that
|
||||
* begins with 'n' but is not 'null', then an error is returned.
|
||||
*
|
||||
* @returns Whether the value is null.
|
||||
* @returns INCORRECT_TYPE If the JSON value begins with 'n' and is not 'null'.
|
||||
*/
|
||||
simdjson_inline bool is_null() noexcept;
|
||||
simdjson_inline simdjson_result<bool> is_null() noexcept;
|
||||
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
/**
|
||||
@@ -334,7 +337,9 @@ public:
|
||||
simdjson_inline simdjson_result<value> operator[](const char *key) noexcept;
|
||||
|
||||
/**
|
||||
* Get the type of this JSON value.
|
||||
* Get the type of this JSON value. It does not validate or consume the value.
|
||||
* E.g., you must still call "is_null()" to check that a value is null even if
|
||||
* "type()" returns json_type::null.
|
||||
*
|
||||
* NOTE: If you're only expecting a value to be one type (a typical case), it's generally
|
||||
* better to just call .get_double, .get_string, etc. and check for INCORRECT_TYPE (or just
|
||||
@@ -583,7 +588,7 @@ public:
|
||||
simdjson_inline simdjson_result<std::string_view> get_string() noexcept;
|
||||
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string> get_raw_json_string() noexcept;
|
||||
simdjson_inline simdjson_result<bool> get_bool() noexcept;
|
||||
simdjson_inline bool is_null() noexcept;
|
||||
simdjson_inline simdjson_result<bool> is_null() noexcept;
|
||||
|
||||
template<typename T> simdjson_inline simdjson_result<T> get() noexcept;
|
||||
|
||||
@@ -676,7 +681,7 @@ public:
|
||||
/** @copydoc simdjson_inline simdjson_result<const char *> current_location() noexcept */
|
||||
simdjson_inline simdjson_result<const char *> current_location() noexcept;
|
||||
/** @copydoc simdjson_inline int32_t current_depth() const noexcept */
|
||||
simdjson_inline int32_t current_depth() const noexcept;
|
||||
simdjson_inline simdjson_result<int32_t> current_depth() const noexcept;
|
||||
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> at_pointer(std::string_view json_pointer) noexcept;
|
||||
};
|
||||
|
||||
|
||||
@@ -468,8 +468,11 @@ simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::parse
|
||||
if (error) { return incorrect_type_error("Not a boolean"); }
|
||||
return simdjson_result<bool>(!not_true);
|
||||
}
|
||||
simdjson_inline bool value_iterator::parse_null(const uint8_t *json) const noexcept {
|
||||
return !atomparsing::str4ncmp(json, "null") && jsoncharutils::is_structural_or_whitespace(json[4]);
|
||||
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::parse_null(const uint8_t *json) const noexcept {
|
||||
bool is_null_string = !atomparsing::str4ncmp(json, "null") && jsoncharutils::is_structural_or_whitespace(json[4]);
|
||||
// if we start with 'n', we must be a null
|
||||
if(!is_null_string && json[0]=='n') { return incorrect_type_error("Not a null but starts with n"); }
|
||||
return is_null_string;
|
||||
}
|
||||
|
||||
simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> value_iterator::get_string() noexcept {
|
||||
@@ -516,10 +519,11 @@ simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::get_b
|
||||
if(result.error() == SUCCESS) { advance_non_root_scalar("bool"); }
|
||||
return result;
|
||||
}
|
||||
simdjson_inline bool value_iterator::is_null() noexcept {
|
||||
auto result = parse_null(peek_non_root_scalar("null"));
|
||||
if(result) { advance_non_root_scalar("null"); }
|
||||
return result;
|
||||
simdjson_inline simdjson_result<bool> value_iterator::is_null() noexcept {
|
||||
bool is_null_value;
|
||||
SIMDJSON_TRY(parse_null(peek_non_root_scalar("null")).get(is_null_value));
|
||||
if(is_null_value) { advance_non_root_scalar("null"); }
|
||||
return is_null_value;
|
||||
}
|
||||
simdjson_inline bool value_iterator::is_negative() noexcept {
|
||||
return numberparsing::is_negative(peek_non_root_scalar("numbersign"));
|
||||
@@ -540,7 +544,7 @@ simdjson_inline simdjson_result<number> value_iterator::get_number() noexcept {
|
||||
return num;
|
||||
}
|
||||
|
||||
simdjson_inline simdjson_result<bool> value_iterator::is_root_integer() noexcept {
|
||||
simdjson_inline simdjson_result<bool> value_iterator::is_root_integer(bool check_trailing) noexcept {
|
||||
auto max_len = peek_start_length();
|
||||
auto json = peek_root_scalar("is_root_integer");
|
||||
uint8_t tmpbuf[20+1]; // <20 digits> is the longest possible unsigned integer
|
||||
@@ -551,12 +555,11 @@ simdjson_inline simdjson_result<bool> value_iterator::is_root_integer() noexcept
|
||||
// If the parsing was a success, we must still check that it is
|
||||
// a single scalar. Note that we parse first because of cases like '[]' where
|
||||
// getting TRAILING_CONTENT is wrong.
|
||||
if((answer.error() == SUCCESS) && (!_json_iter->is_single_token())) { return TRAILING_CONTENT; }
|
||||
if(check_trailing && (answer.error() == SUCCESS) && (!_json_iter->is_single_token())) { return TRAILING_CONTENT; }
|
||||
return answer;
|
||||
}
|
||||
|
||||
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::number_type> value_iterator::get_root_number_type() noexcept {
|
||||
if (!_json_iter->is_single_token()) { return TRAILING_CONTENT; }
|
||||
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::number_type> value_iterator::get_root_number_type(bool check_trailing) noexcept {
|
||||
auto max_len = peek_start_length();
|
||||
auto json = peek_root_scalar("number");
|
||||
// Per https://www.exploringbinary.com/maximum-number-of-decimal-digits-in-binary-floating-point-numbers/,
|
||||
@@ -567,14 +570,11 @@ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::number_type>
|
||||
logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 1082 characters");
|
||||
return NUMBER_ERROR;
|
||||
}
|
||||
// If the parsing was a success, we must still check that it is
|
||||
// a single scalar. Note that we parse first because of cases like '[]' where
|
||||
// getting TRAILING_CONTENT is wrong.
|
||||
auto answer = numberparsing::get_number_type(tmpbuf);
|
||||
if((answer.error() == SUCCESS) && (!_json_iter->is_single_token())) { return TRAILING_CONTENT; }
|
||||
if (check_trailing && (answer.error() == SUCCESS) && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
|
||||
return answer;
|
||||
}
|
||||
simdjson_inline simdjson_result<number> value_iterator::get_root_number() noexcept {
|
||||
simdjson_inline simdjson_result<number> value_iterator::get_root_number(bool check_trailing) noexcept {
|
||||
auto max_len = peek_start_length();
|
||||
auto json = peek_root_scalar("number");
|
||||
// Per https://www.exploringbinary.com/maximum-number-of-decimal-digits-in-binary-floating-point-numbers/,
|
||||
@@ -588,18 +588,21 @@ simdjson_inline simdjson_result<number> value_iterator::get_root_number() noexce
|
||||
number num;
|
||||
error_code error = numberparsing::parse_number(tmpbuf, num);
|
||||
if(error) { return error; }
|
||||
if (!_json_iter->is_single_token()) { return TRAILING_CONTENT; }
|
||||
if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
|
||||
advance_root_scalar("number");
|
||||
return num;
|
||||
}
|
||||
|
||||
simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> value_iterator::get_root_string() noexcept {
|
||||
return get_string();
|
||||
simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> value_iterator::get_root_string(bool check_trailing) noexcept {
|
||||
return get_root_raw_json_string(check_trailing).unescape(json_iter());
|
||||
}
|
||||
simdjson_warn_unused simdjson_inline simdjson_result<raw_json_string> value_iterator::get_root_raw_json_string() noexcept {
|
||||
return get_raw_json_string();
|
||||
simdjson_warn_unused simdjson_inline simdjson_result<raw_json_string> value_iterator::get_root_raw_json_string(bool check_trailing) noexcept {
|
||||
auto json = peek_scalar("string");
|
||||
if (*json != '"') { return incorrect_type_error("Not a string"); }
|
||||
if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
|
||||
advance_scalar("string");
|
||||
return raw_json_string(json+1);
|
||||
}
|
||||
simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> value_iterator::get_root_uint64() noexcept {
|
||||
simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> value_iterator::get_root_uint64(bool check_trailing) noexcept {
|
||||
auto max_len = peek_start_length();
|
||||
auto json = peek_root_scalar("uint64");
|
||||
uint8_t tmpbuf[20+1]; // <20 digits> is the longest possible unsigned integer
|
||||
@@ -609,12 +612,12 @@ simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> value_iterator::g
|
||||
}
|
||||
auto result = numberparsing::parse_unsigned(tmpbuf);
|
||||
if(result.error() == SUCCESS) {
|
||||
if (!_json_iter->is_single_token()) { return TRAILING_CONTENT; }
|
||||
if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
|
||||
advance_root_scalar("uint64");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> value_iterator::get_root_uint64_in_string() noexcept {
|
||||
simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> value_iterator::get_root_uint64_in_string(bool check_trailing) noexcept {
|
||||
auto max_len = peek_start_length();
|
||||
auto json = peek_root_scalar("uint64");
|
||||
uint8_t tmpbuf[20+1]; // <20 digits> is the longest possible unsigned integer
|
||||
@@ -624,12 +627,12 @@ simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> value_iterator::g
|
||||
}
|
||||
auto result = numberparsing::parse_unsigned_in_string(tmpbuf);
|
||||
if(result.error() == SUCCESS) {
|
||||
if (!_json_iter->is_single_token()) { return TRAILING_CONTENT; }
|
||||
if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
|
||||
advance_root_scalar("uint64");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
simdjson_warn_unused simdjson_inline simdjson_result<int64_t> value_iterator::get_root_int64() noexcept {
|
||||
simdjson_warn_unused simdjson_inline simdjson_result<int64_t> value_iterator::get_root_int64(bool check_trailing) noexcept {
|
||||
auto max_len = peek_start_length();
|
||||
auto json = peek_root_scalar("int64");
|
||||
uint8_t tmpbuf[20+1]; // -<19 digits> is the longest possible integer
|
||||
@@ -640,12 +643,12 @@ simdjson_warn_unused simdjson_inline simdjson_result<int64_t> value_iterator::ge
|
||||
|
||||
auto result = numberparsing::parse_integer(tmpbuf);
|
||||
if(result.error() == SUCCESS) {
|
||||
if (!_json_iter->is_single_token()) { return TRAILING_CONTENT; }
|
||||
if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
|
||||
advance_root_scalar("int64");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
simdjson_warn_unused simdjson_inline simdjson_result<int64_t> value_iterator::get_root_int64_in_string() noexcept {
|
||||
simdjson_warn_unused simdjson_inline simdjson_result<int64_t> value_iterator::get_root_int64_in_string(bool check_trailing) noexcept {
|
||||
auto max_len = peek_start_length();
|
||||
auto json = peek_root_scalar("int64");
|
||||
uint8_t tmpbuf[20+1]; // -<19 digits> is the longest possible integer
|
||||
@@ -656,12 +659,12 @@ simdjson_warn_unused simdjson_inline simdjson_result<int64_t> value_iterator::ge
|
||||
|
||||
auto result = numberparsing::parse_integer_in_string(tmpbuf);
|
||||
if(result.error() == SUCCESS) {
|
||||
if (!_json_iter->is_single_token()) { return TRAILING_CONTENT; }
|
||||
if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
|
||||
advance_root_scalar("int64");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
simdjson_warn_unused simdjson_inline simdjson_result<double> value_iterator::get_root_double() noexcept {
|
||||
simdjson_warn_unused simdjson_inline simdjson_result<double> value_iterator::get_root_double(bool check_trailing) noexcept {
|
||||
auto max_len = peek_start_length();
|
||||
auto json = peek_root_scalar("double");
|
||||
// Per https://www.exploringbinary.com/maximum-number-of-decimal-digits-in-binary-floating-point-numbers/,
|
||||
@@ -674,13 +677,13 @@ simdjson_warn_unused simdjson_inline simdjson_result<double> value_iterator::get
|
||||
}
|
||||
auto result = numberparsing::parse_double(tmpbuf);
|
||||
if(result.error() == SUCCESS) {
|
||||
if (!_json_iter->is_single_token()) { return TRAILING_CONTENT; }
|
||||
if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
|
||||
advance_root_scalar("double");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
simdjson_warn_unused simdjson_inline simdjson_result<double> value_iterator::get_root_double_in_string() noexcept {
|
||||
simdjson_warn_unused simdjson_inline simdjson_result<double> value_iterator::get_root_double_in_string(bool check_trailing) noexcept {
|
||||
auto max_len = peek_start_length();
|
||||
auto json = peek_root_scalar("double");
|
||||
// Per https://www.exploringbinary.com/maximum-number-of-decimal-digits-in-binary-floating-point-numbers/,
|
||||
@@ -693,31 +696,32 @@ simdjson_warn_unused simdjson_inline simdjson_result<double> value_iterator::get
|
||||
}
|
||||
auto result = numberparsing::parse_double_in_string(tmpbuf);
|
||||
if(result.error() == SUCCESS) {
|
||||
if (!_json_iter->is_single_token()) { return TRAILING_CONTENT; }
|
||||
if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
|
||||
advance_root_scalar("double");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::get_root_bool() noexcept {
|
||||
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::get_root_bool(bool check_trailing) noexcept {
|
||||
auto max_len = peek_start_length();
|
||||
auto json = peek_root_scalar("bool");
|
||||
uint8_t tmpbuf[5+1];
|
||||
if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf)) { return incorrect_type_error("Not a boolean"); }
|
||||
auto result = parse_bool(tmpbuf);
|
||||
if(result.error() == SUCCESS) {
|
||||
if (!_json_iter->is_single_token()) { return TRAILING_CONTENT; }
|
||||
if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
|
||||
advance_root_scalar("bool");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
simdjson_inline bool value_iterator::is_root_null() noexcept {
|
||||
// If there is trailing content, then the document is not null.
|
||||
if (!_json_iter->is_single_token()) { return false; }
|
||||
simdjson_inline simdjson_result<bool> value_iterator::is_root_null(bool check_trailing) noexcept {
|
||||
auto max_len = peek_start_length();
|
||||
auto json = peek_root_scalar("null");
|
||||
bool result = (max_len >= 4 && !atomparsing::str4ncmp(json, "null") &&
|
||||
(max_len == 4 || jsoncharutils::is_structural_or_whitespace(json[5])));
|
||||
if(result) { advance_root_scalar("null"); }
|
||||
(max_len == 4 || jsoncharutils::is_structural_or_whitespace(json[4])));
|
||||
if(result) { // we have something that looks like a null.
|
||||
if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
|
||||
advance_root_scalar("null");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -289,26 +289,26 @@ public:
|
||||
simdjson_warn_unused simdjson_inline simdjson_result<double> get_double() noexcept;
|
||||
simdjson_warn_unused simdjson_inline simdjson_result<double> get_double_in_string() noexcept;
|
||||
simdjson_warn_unused simdjson_inline simdjson_result<bool> get_bool() noexcept;
|
||||
simdjson_inline bool is_null() noexcept;
|
||||
simdjson_warn_unused simdjson_inline simdjson_result<bool> is_null() noexcept;
|
||||
simdjson_warn_unused simdjson_inline bool is_negative() noexcept;
|
||||
simdjson_warn_unused simdjson_inline simdjson_result<bool> is_integer() noexcept;
|
||||
simdjson_warn_unused simdjson_inline simdjson_result<number_type> get_number_type() noexcept;
|
||||
simdjson_warn_unused simdjson_inline simdjson_result<number> get_number() noexcept;
|
||||
|
||||
simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> get_root_string() noexcept;
|
||||
simdjson_warn_unused simdjson_inline simdjson_result<raw_json_string> get_root_raw_json_string() noexcept;
|
||||
simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> get_root_uint64() noexcept;
|
||||
simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> get_root_uint64_in_string() noexcept;
|
||||
simdjson_warn_unused simdjson_inline simdjson_result<int64_t> get_root_int64() noexcept;
|
||||
simdjson_warn_unused simdjson_inline simdjson_result<int64_t> get_root_int64_in_string() noexcept;
|
||||
simdjson_warn_unused simdjson_inline simdjson_result<double> get_root_double() noexcept;
|
||||
simdjson_warn_unused simdjson_inline simdjson_result<double> get_root_double_in_string() noexcept;
|
||||
simdjson_warn_unused simdjson_inline simdjson_result<bool> get_root_bool() noexcept;
|
||||
simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> get_root_string(bool check_trailing) noexcept;
|
||||
simdjson_warn_unused simdjson_inline simdjson_result<raw_json_string> get_root_raw_json_string(bool check_trailing) noexcept;
|
||||
simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> get_root_uint64(bool check_trailing) noexcept;
|
||||
simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> get_root_uint64_in_string(bool check_trailing) noexcept;
|
||||
simdjson_warn_unused simdjson_inline simdjson_result<int64_t> get_root_int64(bool check_trailing) noexcept;
|
||||
simdjson_warn_unused simdjson_inline simdjson_result<int64_t> get_root_int64_in_string(bool check_trailing) noexcept;
|
||||
simdjson_warn_unused simdjson_inline simdjson_result<double> get_root_double(bool check_trailing) noexcept;
|
||||
simdjson_warn_unused simdjson_inline simdjson_result<double> get_root_double_in_string(bool check_trailing) noexcept;
|
||||
simdjson_warn_unused simdjson_inline simdjson_result<bool> get_root_bool(bool check_trailing) noexcept;
|
||||
simdjson_warn_unused simdjson_inline bool is_root_negative() noexcept;
|
||||
simdjson_warn_unused simdjson_inline simdjson_result<bool> is_root_integer() noexcept;
|
||||
simdjson_warn_unused simdjson_inline simdjson_result<number_type> get_root_number_type() noexcept;
|
||||
simdjson_warn_unused simdjson_inline simdjson_result<number> get_root_number() noexcept;
|
||||
simdjson_inline bool is_root_null() noexcept;
|
||||
simdjson_warn_unused simdjson_inline simdjson_result<bool> is_root_integer(bool check_trailing) noexcept;
|
||||
simdjson_warn_unused simdjson_inline simdjson_result<number_type> get_root_number_type(bool check_trailing) noexcept;
|
||||
simdjson_warn_unused simdjson_inline simdjson_result<number> get_root_number(bool check_trailing) noexcept;
|
||||
simdjson_warn_unused simdjson_inline simdjson_result<bool> is_root_null(bool check_trailing) noexcept;
|
||||
|
||||
simdjson_inline error_code error() const noexcept;
|
||||
simdjson_inline uint8_t *&string_buf_loc() noexcept;
|
||||
@@ -350,7 +350,7 @@ protected:
|
||||
inline std::string to_string() const noexcept;
|
||||
simdjson_inline value_iterator(json_iterator *json_iter, depth_t depth, token_position start_index) noexcept;
|
||||
|
||||
simdjson_inline bool parse_null(const uint8_t *json) const noexcept;
|
||||
simdjson_inline simdjson_result<bool> parse_null(const uint8_t *json) const noexcept;
|
||||
simdjson_inline simdjson_result<bool> parse_bool(const uint8_t *json) const noexcept;
|
||||
simdjson_inline const uint8_t *peek_start() const noexcept;
|
||||
simdjson_inline uint32_t peek_start_length() const noexcept;
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace {
|
||||
// Sadly, sanitizers are not smart enough to figure it out.
|
||||
SIMDJSON_NO_SANITIZE_UNDEFINED
|
||||
simdjson_inline int trailing_zeroes(uint64_t input_num) {
|
||||
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||
#if SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||
return (int)_tzcnt_u64(input_num);
|
||||
#else // SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||
////////
|
||||
@@ -32,7 +32,7 @@ simdjson_inline int leading_zeroes(uint64_t input_num) {
|
||||
return int(_lzcnt_u64(input_num));
|
||||
}
|
||||
|
||||
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||
#if SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||
simdjson_inline unsigned __int64 count_ones(uint64_t input_num) {
|
||||
// note: we do not support legacy 32-bit Windows
|
||||
return __popcnt64(input_num);// Visual Studio wants two underscores
|
||||
@@ -45,7 +45,7 @@ simdjson_inline long long int count_ones(uint64_t input_num) {
|
||||
|
||||
simdjson_inline bool add_overflow(uint64_t value1, uint64_t value2,
|
||||
uint64_t *result) {
|
||||
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||
#if SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||
return _addcarry_u64(0, value1, value2,
|
||||
reinterpret_cast<unsigned __int64 *>(result));
|
||||
#else
|
||||
|
||||
@@ -9,6 +9,9 @@ namespace haswell {
|
||||
|
||||
using namespace simdjson;
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
class implementation final : public simdjson::implementation {
|
||||
public:
|
||||
simdjson_inline implementation() : simdjson::implementation(
|
||||
|
||||
@@ -3,14 +3,14 @@
|
||||
|
||||
#include "simdjson/base.h"
|
||||
|
||||
#ifdef SIMDJSON_VISUAL_STUDIO
|
||||
#if SIMDJSON_VISUAL_STUDIO
|
||||
// under clang within visual studio, this will include <x86intrin.h>
|
||||
#include <intrin.h> // visual studio or clang
|
||||
#else
|
||||
#include <x86intrin.h> // elsewhere
|
||||
#endif // SIMDJSON_VISUAL_STUDIO
|
||||
|
||||
#ifdef SIMDJSON_CLANG_VISUAL_STUDIO
|
||||
#if SIMDJSON_CLANG_VISUAL_STUDIO
|
||||
/**
|
||||
* You are not supposed, normally, to include these
|
||||
* headers directly. Instead you should either include intrin.h
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace {
|
||||
// Sadly, sanitizers are not smart enough to figure it out.
|
||||
SIMDJSON_NO_SANITIZE_UNDEFINED
|
||||
simdjson_inline int trailing_zeroes(uint64_t input_num) {
|
||||
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||
#if SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||
return (int)_tzcnt_u64(input_num);
|
||||
#else // SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||
////////
|
||||
@@ -32,7 +32,7 @@ simdjson_inline int leading_zeroes(uint64_t input_num) {
|
||||
return int(_lzcnt_u64(input_num));
|
||||
}
|
||||
|
||||
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||
#if SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||
simdjson_inline unsigned __int64 count_ones(uint64_t input_num) {
|
||||
// note: we do not support legacy 32-bit Windows
|
||||
return __popcnt64(input_num);// Visual Studio wants two underscores
|
||||
@@ -45,7 +45,7 @@ simdjson_inline long long int count_ones(uint64_t input_num) {
|
||||
|
||||
simdjson_inline bool add_overflow(uint64_t value1, uint64_t value2,
|
||||
uint64_t *result) {
|
||||
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||
#if SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||
return _addcarry_u64(0, value1, value2,
|
||||
reinterpret_cast<unsigned __int64 *>(result));
|
||||
#else
|
||||
|
||||
@@ -9,6 +9,9 @@ namespace icelake {
|
||||
|
||||
using namespace simdjson;
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
class implementation final : public simdjson::implementation {
|
||||
public:
|
||||
simdjson_inline implementation() : simdjson::implementation(
|
||||
|
||||
@@ -3,14 +3,14 @@
|
||||
|
||||
#include "simdjson/base.h"
|
||||
|
||||
#ifdef SIMDJSON_VISUAL_STUDIO
|
||||
#if SIMDJSON_VISUAL_STUDIO
|
||||
// under clang within visual studio, this will include <x86intrin.h>
|
||||
#include <intrin.h> // visual studio or clang
|
||||
#else
|
||||
#include <x86intrin.h> // elsewhere
|
||||
#endif // SIMDJSON_VISUAL_STUDIO
|
||||
|
||||
#ifdef SIMDJSON_CLANG_VISUAL_STUDIO
|
||||
#if SIMDJSON_CLANG_VISUAL_STUDIO
|
||||
/**
|
||||
* You are not supposed, normally, to include these
|
||||
* headers directly. Instead you should either include intrin.h
|
||||
|
||||
@@ -79,13 +79,9 @@ namespace simd {
|
||||
|
||||
template<int N=1>
|
||||
simdjson_inline simd8<T> prev(const simd8<T> prev_chunk) const {
|
||||
#if SIMDJSON_GCC8
|
||||
// workaround for compilers unable to figure out that 16 - N is a constant (GCC 8)
|
||||
constexpr int shift = 16 - N;
|
||||
return _mm512_alignr_epi8(*this, _mm512_permutex2var_epi64(prev_chunk, _mm512_set_epi64(13, 12, 11, 10, 9, 8, 7, 6), *this), shift);
|
||||
#else
|
||||
return _mm512_alignr_epi8(*this, _mm512_permutex2var_epi64(prev_chunk, _mm512_set_epi64(13, 12, 11, 10, 9, 8, 7, 6), *this), 16 - N);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -87,7 +87,7 @@ public:
|
||||
*
|
||||
* @return a mask of all required `internal::instruction_set::` values.
|
||||
*/
|
||||
virtual uint32_t required_instruction_sets() const { return _required_instruction_sets; };
|
||||
virtual uint32_t required_instruction_sets() const { return _required_instruction_sets; }
|
||||
|
||||
/**
|
||||
* @private For internal implementation use
|
||||
|
||||
@@ -51,8 +51,13 @@
|
||||
// Default Haswell to on if this is x86-64. Even if we're not compiled for it, it could be selected
|
||||
// at runtime.
|
||||
#ifndef SIMDJSON_IMPLEMENTATION_HASWELL
|
||||
#if SIMDJSON_CAN_ALWAYS_RUN_ICELAKE
|
||||
// if icelake is always available, never enable haswell.
|
||||
#define SIMDJSON_IMPLEMENTATION_HASWELL 0
|
||||
#else
|
||||
#define SIMDJSON_IMPLEMENTATION_HASWELL SIMDJSON_IS_X86_64
|
||||
#endif
|
||||
#endif
|
||||
#ifdef _MSC_VER
|
||||
// To see why (__BMI__) && (__PCLMUL__) && (__LZCNT__) are not part of this next line, see
|
||||
// https://github.com/simdjson/simdjson/issues/1247
|
||||
@@ -61,9 +66,14 @@
|
||||
#define SIMDJSON_CAN_ALWAYS_RUN_HASWELL ((SIMDJSON_IMPLEMENTATION_HASWELL) && (SIMDJSON_IS_X86_64) && (__AVX2__) && (__BMI__) && (__PCLMUL__) && (__LZCNT__))
|
||||
#endif
|
||||
|
||||
// Default Westmere to on if this is x86-64. Note that the macro SIMDJSON_REQUIRES_HASWELL appears unused.
|
||||
// Default Westmere to on if this is x86-64.
|
||||
#ifndef SIMDJSON_IMPLEMENTATION_WESTMERE
|
||||
#define SIMDJSON_IMPLEMENTATION_WESTMERE (SIMDJSON_IS_X86_64 && !SIMDJSON_REQUIRES_HASWELL)
|
||||
#if SIMDJSON_CAN_ALWAYS_RUN_ICELAKE || SIMDJSON_CAN_ALWAYS_RUN_HASWELL
|
||||
// if icelake or haswell are always available, never enable westmere.
|
||||
#define SIMDJSON_IMPLEMENTATION_WESTMERE 0
|
||||
#else
|
||||
#define SIMDJSON_IMPLEMENTATION_WESTMERE SIMDJSON_IS_X86_64
|
||||
#endif
|
||||
#endif
|
||||
#define SIMDJSON_CAN_ALWAYS_RUN_WESTMERE (SIMDJSON_IMPLEMENTATION_WESTMERE && SIMDJSON_IS_X86_64 && __SSE4_2__ && __PCLMUL__)
|
||||
|
||||
@@ -74,7 +84,12 @@
|
||||
|
||||
// Default Fallback to on unless a builtin implementation has already been selected.
|
||||
#ifndef SIMDJSON_IMPLEMENTATION_FALLBACK
|
||||
#define SIMDJSON_IMPLEMENTATION_FALLBACK 1 // (!SIMDJSON_CAN_ALWAYS_RUN_ARM64 && !SIMDJSON_CAN_ALWAYS_RUN_HASWELL && !SIMDJSON_CAN_ALWAYS_RUN_WESTMERE && !SIMDJSON_CAN_ALWAYS_RUN_PPC64)
|
||||
#if SIMDJSON_CAN_ALWAYS_RUN_ARM64 || SIMDJSON_CAN_ALWAYS_RUN_ICELAKE || SIMDJSON_CAN_ALWAYS_RUN_HASWELL || SIMDJSON_CAN_ALWAYS_RUN_WESTMERE || SIMDJSON_CAN_ALWAYS_RUN_PPC64
|
||||
// if anything at all except fallback can always run, then disable fallback.
|
||||
#define SIMDJSON_IMPLEMENTATION_FALLBACK 0
|
||||
#else
|
||||
#define SIMDJSON_IMPLEMENTATION_FALLBACK 1
|
||||
#endif
|
||||
#endif
|
||||
#define SIMDJSON_CAN_ALWAYS_RUN_FALLBACK SIMDJSON_IMPLEMENTATION_FALLBACK
|
||||
|
||||
|
||||
@@ -17,7 +17,9 @@ simdjson_inline tape_ref::tape_ref(const dom::document *_doc, size_t _json_index
|
||||
simdjson_inline bool tape_ref::is_document_root() const noexcept {
|
||||
return json_index == 1; // should we ever change the structure of the tape, this should get updated.
|
||||
}
|
||||
|
||||
simdjson_inline bool tape_ref::usable() const noexcept {
|
||||
return doc != nullptr; // when the document pointer is null, this tape_ref is uninitialized (should not be accessed).
|
||||
}
|
||||
// Some value types have a specific on-tape word value. It can be faster
|
||||
// to check the type by doing a word-to-word comparison instead of extracting the
|
||||
// most significant 8 bits.
|
||||
|
||||
@@ -38,6 +38,7 @@ public:
|
||||
simdjson_inline const char * get_c_str() const noexcept;
|
||||
inline std::string_view get_string_view() const noexcept;
|
||||
simdjson_inline bool is_document_root() const noexcept;
|
||||
simdjson_inline bool usable() const noexcept;
|
||||
|
||||
/** The document this element references. */
|
||||
const dom::document *doc;
|
||||
|
||||
@@ -128,7 +128,7 @@ inline simdjson_result<padded_string> padded_string::load(std::string_view filen
|
||||
|
||||
// Get the file size
|
||||
int ret;
|
||||
#if defined(SIMDJSON_VISUAL_STUDIO) && !SIMDJSON_IS_32BITS
|
||||
#if SIMDJSON_VISUAL_STUDIO && !SIMDJSON_IS_32BITS
|
||||
ret = _fseeki64(fp, 0, SEEK_END);
|
||||
#else
|
||||
ret = std::fseek(fp, 0, SEEK_END);
|
||||
@@ -137,7 +137,7 @@ inline simdjson_result<padded_string> padded_string::load(std::string_view filen
|
||||
std::fclose(fp);
|
||||
return IO_ERROR;
|
||||
}
|
||||
#if defined(SIMDJSON_VISUAL_STUDIO) && !SIMDJSON_IS_32BITS
|
||||
#if SIMDJSON_VISUAL_STUDIO && !SIMDJSON_IS_32BITS
|
||||
__int64 llen = _ftelli64(fp);
|
||||
if(llen == -1L) {
|
||||
std::fclose(fp);
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
#endif // __clang__
|
||||
#endif // _MSC_VER
|
||||
|
||||
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||
#if SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||
// https://en.wikipedia.org/wiki/C_alternative_tokens
|
||||
// This header should have no effect, except maybe
|
||||
// under Visual Studio.
|
||||
@@ -59,8 +59,11 @@
|
||||
#endif
|
||||
|
||||
#endif // defined(__x86_64__) || defined(_M_AMD64)
|
||||
#ifndef SIMDJSON_IS_32BITS
|
||||
#define SIMDJSON_IS_32BITS 0
|
||||
#endif
|
||||
|
||||
#ifdef SIMDJSON_IS_32BITS
|
||||
#if SIMDJSON_IS_32BITS
|
||||
#ifndef SIMDJSON_NO_PORTABILITY_WARNING
|
||||
#pragma message("The simdjson library is designed \
|
||||
for 64-bit processors and it seems that you are not \
|
||||
@@ -91,7 +94,7 @@ use a 64-bit target such as x64, 64-bit ARM or 64-bit PPC.")
|
||||
//
|
||||
|
||||
// We are going to use runtime dispatch.
|
||||
#ifdef SIMDJSON_IS_X86_64
|
||||
#if SIMDJSON_IS_X86_64
|
||||
#ifdef __clang__
|
||||
// clang does not have GCC push pop
|
||||
// warning: clang attribute push can't be used within a namespace in clang up
|
||||
@@ -145,7 +148,7 @@ use a 64-bit target such as x64, 64-bit ARM or 64-bit PPC.")
|
||||
#define SIMDJSON_NO_SANITIZE_UNDEFINED
|
||||
#endif
|
||||
|
||||
#ifdef SIMDJSON_VISUAL_STUDIO
|
||||
#if SIMDJSON_VISUAL_STUDIO
|
||||
// This is one case where we do not distinguish between
|
||||
// regular visual studio and clang under visual studio.
|
||||
// clang under Windows has _stricmp (like visual studio) but not strcasecmp (as clang normally has)
|
||||
@@ -161,7 +164,7 @@ use a 64-bit target such as x64, 64-bit ARM or 64-bit PPC.")
|
||||
|
||||
#ifdef NDEBUG
|
||||
|
||||
#ifdef SIMDJSON_VISUAL_STUDIO
|
||||
#if SIMDJSON_VISUAL_STUDIO
|
||||
#define SIMDJSON_UNREACHABLE() __assume(0)
|
||||
#define SIMDJSON_ASSUME(COND) __assume(COND)
|
||||
#else
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace {
|
||||
// Sadly, sanitizers are not smart enough to figure it out.
|
||||
SIMDJSON_NO_SANITIZE_UNDEFINED
|
||||
simdjson_inline int trailing_zeroes(uint64_t input_num) {
|
||||
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||
#if SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||
unsigned long ret;
|
||||
// Search the mask data from least significant bit (LSB)
|
||||
// to the most significant bit (MSB) for a set bit (1).
|
||||
@@ -28,7 +28,7 @@ simdjson_inline uint64_t clear_lowest_bit(uint64_t input_num) {
|
||||
|
||||
/* result might be undefined when input_num is zero */
|
||||
simdjson_inline int leading_zeroes(uint64_t input_num) {
|
||||
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||
#if SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||
unsigned long leading_zero = 0;
|
||||
// Search the mask data from most significant bit (MSB)
|
||||
// to least significant bit (LSB) for a set bit (1).
|
||||
@@ -41,7 +41,7 @@ simdjson_inline int leading_zeroes(uint64_t input_num) {
|
||||
#endif // SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||
}
|
||||
|
||||
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||
#if SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||
simdjson_inline int count_ones(uint64_t input_num) {
|
||||
// note: we do not support legacy 32-bit Windows
|
||||
return __popcnt64(input_num); // Visual Studio wants two underscores
|
||||
@@ -54,7 +54,7 @@ simdjson_inline int count_ones(uint64_t input_num) {
|
||||
|
||||
simdjson_inline bool add_overflow(uint64_t value1, uint64_t value2,
|
||||
uint64_t *result) {
|
||||
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||
#if SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||
*result = value1 + value2;
|
||||
return *result < value1;
|
||||
#else
|
||||
|
||||
@@ -12,6 +12,9 @@ using namespace simdjson;
|
||||
using namespace simdjson::dom;
|
||||
} // namespace
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
class implementation final : public simdjson::implementation {
|
||||
public:
|
||||
simdjson_inline implementation()
|
||||
|
||||
@@ -4,22 +4,22 @@
|
||||
#define SIMDJSON_SIMDJSON_VERSION_H
|
||||
|
||||
/** The version of simdjson being used (major.minor.revision) */
|
||||
#define SIMDJSON_VERSION 2.2.3
|
||||
#define SIMDJSON_VERSION "3.1.1"
|
||||
|
||||
namespace simdjson {
|
||||
enum {
|
||||
/**
|
||||
* The major version (MAJOR.minor.revision) of simdjson being used.
|
||||
*/
|
||||
SIMDJSON_VERSION_MAJOR = 2,
|
||||
SIMDJSON_VERSION_MAJOR = 3,
|
||||
/**
|
||||
* The minor version (major.MINOR.revision) of simdjson being used.
|
||||
*/
|
||||
SIMDJSON_VERSION_MINOR = 2,
|
||||
SIMDJSON_VERSION_MINOR = 1,
|
||||
/**
|
||||
* The revision (major.minor.REVISION) of simdjson being used.
|
||||
*/
|
||||
SIMDJSON_VERSION_REVISION = 3
|
||||
SIMDJSON_VERSION_REVISION = 1
|
||||
};
|
||||
} // namespace simdjson
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace {
|
||||
// Sadly, sanitizers are not smart enough to figure it out.
|
||||
SIMDJSON_NO_SANITIZE_UNDEFINED
|
||||
simdjson_inline int trailing_zeroes(uint64_t input_num) {
|
||||
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||
#if SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||
unsigned long ret;
|
||||
// Search the mask data from least significant bit (LSB)
|
||||
// to the most significant bit (MSB) for a set bit (1).
|
||||
@@ -28,7 +28,7 @@ simdjson_inline uint64_t clear_lowest_bit(uint64_t input_num) {
|
||||
|
||||
/* result might be undefined when input_num is zero */
|
||||
simdjson_inline int leading_zeroes(uint64_t input_num) {
|
||||
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||
#if SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||
unsigned long leading_zero = 0;
|
||||
// Search the mask data from most significant bit (MSB)
|
||||
// to least significant bit (LSB) for a set bit (1).
|
||||
@@ -41,7 +41,7 @@ simdjson_inline int leading_zeroes(uint64_t input_num) {
|
||||
#endif// SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||
}
|
||||
|
||||
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||
#if SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||
simdjson_inline unsigned __int64 count_ones(uint64_t input_num) {
|
||||
// note: we do not support legacy 32-bit Windows
|
||||
return __popcnt64(input_num);// Visual Studio wants two underscores
|
||||
@@ -54,7 +54,7 @@ simdjson_inline long long int count_ones(uint64_t input_num) {
|
||||
|
||||
simdjson_inline bool add_overflow(uint64_t value1, uint64_t value2,
|
||||
uint64_t *result) {
|
||||
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||
#if SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||
return _addcarry_u64(0, value1, value2,
|
||||
reinterpret_cast<unsigned __int64 *>(result));
|
||||
#else
|
||||
|
||||
@@ -12,6 +12,9 @@ using namespace simdjson;
|
||||
using namespace simdjson::dom;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
class implementation final : public simdjson::implementation {
|
||||
public:
|
||||
simdjson_inline implementation() : simdjson::implementation("westmere", "Intel/AMD SSE4.2", internal::instruction_set::SSE42 | internal::instruction_set::PCLMULQDQ) {}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef SIMDJSON_WESTMERE_INTRINSICS_H
|
||||
#define SIMDJSON_WESTMERE_INTRINSICS_H
|
||||
|
||||
#ifdef SIMDJSON_VISUAL_STUDIO
|
||||
#if SIMDJSON_VISUAL_STUDIO
|
||||
// under clang within visual studio, this will include <x86intrin.h>
|
||||
#include <intrin.h> // visual studio or clang
|
||||
#else
|
||||
@@ -9,7 +9,7 @@
|
||||
#endif // SIMDJSON_VISUAL_STUDIO
|
||||
|
||||
|
||||
#ifdef SIMDJSON_CLANG_VISUAL_STUDIO
|
||||
#if SIMDJSON_CLANG_VISUAL_STUDIO
|
||||
/**
|
||||
* You are not supposed, normally, to include these
|
||||
* headers directly. Instead you should either include intrin.h
|
||||
|
||||
+11
-14
@@ -1,4 +1,4 @@
|
||||
/* auto-generated on 2022-10-02 16:25:39 -0400. Do not edit! */
|
||||
/* auto-generated on 2023-02-06 18:28:54 -0500. Do not edit! */
|
||||
/* begin file src/simdjson.cpp */
|
||||
#include "simdjson.h"
|
||||
|
||||
@@ -868,9 +868,9 @@ inline char *format_buffer(char *buf, int len, int decimal_exponent,
|
||||
|
||||
std::memset(buf + k, '0', static_cast<size_t>(n) - static_cast<size_t>(k));
|
||||
// Make it look like a floating-point number (#362, #378)
|
||||
// buf[n + 0] = '.';
|
||||
// buf[n + 1] = '0';
|
||||
return buf + (static_cast<size_t>(n));
|
||||
buf[n + 0] = '.';
|
||||
buf[n + 1] = '0';
|
||||
return buf + (static_cast<size_t>(n)) + 2;
|
||||
}
|
||||
|
||||
if (0 < n && n <= max_exp) {
|
||||
@@ -933,10 +933,8 @@ char *to_chars(char *first, const char *last, double value) {
|
||||
{
|
||||
*first++ = '0';
|
||||
// Make it look like a floating-point number (#362, #378)
|
||||
if(negative) {
|
||||
*first++ = '.';
|
||||
*first++ = '0';
|
||||
}
|
||||
*first++ = '.';
|
||||
*first++ = '0';
|
||||
return first;
|
||||
}
|
||||
// Compute v = buffer * 10^decimal_exponent.
|
||||
@@ -3785,7 +3783,7 @@ public:
|
||||
// it helps tremendously.
|
||||
if (bits == 0)
|
||||
return;
|
||||
#if defined(SIMDJSON_PREFER_REVERSE_BITS)
|
||||
#if SIMDJSON_PREFER_REVERSE_BITS
|
||||
/**
|
||||
* ARM lacks a fast trailing zero instruction, but it has a fast
|
||||
* bit reversal instruction and a fast leading zero instruction.
|
||||
@@ -5149,7 +5147,6 @@ simdjson_warn_unused error_code dom_parser_implementation::parse(const uint8_t *
|
||||
// redefining SIMDJSON_IMPLEMENTATION to "fallback"
|
||||
// #define SIMDJSON_IMPLEMENTATION fallback
|
||||
/* end file include/simdjson/fallback/begin.h */
|
||||
|
||||
namespace simdjson {
|
||||
namespace fallback {
|
||||
|
||||
@@ -7579,7 +7576,7 @@ public:
|
||||
// it helps tremendously.
|
||||
if (bits == 0)
|
||||
return;
|
||||
#if defined(SIMDJSON_PREFER_REVERSE_BITS)
|
||||
#if SIMDJSON_PREFER_REVERSE_BITS
|
||||
/**
|
||||
* ARM lacks a fast trailing zero instruction, but it has a fast
|
||||
* bit reversal instruction and a fast leading zero instruction.
|
||||
@@ -9971,7 +9968,7 @@ public:
|
||||
// it helps tremendously.
|
||||
if (bits == 0)
|
||||
return;
|
||||
#if defined(SIMDJSON_PREFER_REVERSE_BITS)
|
||||
#if SIMDJSON_PREFER_REVERSE_BITS
|
||||
/**
|
||||
* ARM lacks a fast trailing zero instruction, but it has a fast
|
||||
* bit reversal instruction and a fast leading zero instruction.
|
||||
@@ -12279,7 +12276,7 @@ public:
|
||||
// it helps tremendously.
|
||||
if (bits == 0)
|
||||
return;
|
||||
#if defined(SIMDJSON_PREFER_REVERSE_BITS)
|
||||
#if SIMDJSON_PREFER_REVERSE_BITS
|
||||
/**
|
||||
* ARM lacks a fast trailing zero instruction, but it has a fast
|
||||
* bit reversal instruction and a fast leading zero instruction.
|
||||
@@ -14622,7 +14619,7 @@ public:
|
||||
// it helps tremendously.
|
||||
if (bits == 0)
|
||||
return;
|
||||
#if defined(SIMDJSON_PREFER_REVERSE_BITS)
|
||||
#if SIMDJSON_PREFER_REVERSE_BITS
|
||||
/**
|
||||
* ARM lacks a fast trailing zero instruction, but it has a fast
|
||||
* bit reversal instruction and a fast leading zero instruction.
|
||||
|
||||
+352
-184
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,4 @@
|
||||
#include "simdjson/fallback/begin.h"
|
||||
|
||||
namespace simdjson {
|
||||
namespace SIMDJSON_IMPLEMENTATION {
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ public:
|
||||
// it helps tremendously.
|
||||
if (bits == 0)
|
||||
return;
|
||||
#if defined(SIMDJSON_PREFER_REVERSE_BITS)
|
||||
#if SIMDJSON_PREFER_REVERSE_BITS
|
||||
/**
|
||||
* ARM lacks a fast trailing zero instruction, but it has a fast
|
||||
* bit reversal instruction and a fast leading zero instruction.
|
||||
|
||||
+5
-7
@@ -860,9 +860,9 @@ inline char *format_buffer(char *buf, int len, int decimal_exponent,
|
||||
|
||||
std::memset(buf + k, '0', static_cast<size_t>(n) - static_cast<size_t>(k));
|
||||
// Make it look like a floating-point number (#362, #378)
|
||||
// buf[n + 0] = '.';
|
||||
// buf[n + 1] = '0';
|
||||
return buf + (static_cast<size_t>(n));
|
||||
buf[n + 0] = '.';
|
||||
buf[n + 1] = '0';
|
||||
return buf + (static_cast<size_t>(n)) + 2;
|
||||
}
|
||||
|
||||
if (0 < n && n <= max_exp) {
|
||||
@@ -925,10 +925,8 @@ char *to_chars(char *first, const char *last, double value) {
|
||||
{
|
||||
*first++ = '0';
|
||||
// Make it look like a floating-point number (#362, #378)
|
||||
if(negative) {
|
||||
*first++ = '.';
|
||||
*first++ = '0';
|
||||
}
|
||||
*first++ = '.';
|
||||
*first++ = '0';
|
||||
return first;
|
||||
}
|
||||
// Compute v = buffer * 10^decimal_exponent.
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include <cstring>
|
||||
|
||||
int main(int argc, const char *argv[]) {
|
||||
std::cout << "simdjson v" << SIMDJSON_STRINGIFY(SIMDJSON_VERSION) << " is running the " << simdjson::get_active_implementation()->name() << " implementation." << std::endl;
|
||||
std::cout << "simdjson v" << SIMDJSON_VERSION << " is running the " << simdjson::get_active_implementation()->name() << " implementation." << std::endl;
|
||||
const char *expected_implementation = nullptr;
|
||||
if (argc > 1) {
|
||||
expected_implementation = argv[1];
|
||||
|
||||
@@ -21,7 +21,9 @@
|
||||
*/
|
||||
#if defined(SIMDJSON_REGULAR_VISUAL_STUDIO) || defined (__linux__) || defined (__APPLE__) || defined(__FreeBSD__)
|
||||
// Finally, we want to exclude legacy 32-bit systems.
|
||||
#ifndef SIMDJSON_IS_32BITS
|
||||
#if SIMDJSON_IS_32BITS
|
||||
// floating-point tests are omitted under 32-bit systems
|
||||
#else
|
||||
// So we only run some of the floating-point tests under 64-bit linux, apple, regular visual studio, freebsd.
|
||||
#define TEST_FLOATS
|
||||
#endif
|
||||
|
||||
@@ -33,7 +33,9 @@ void found_unsigned_integer(uint64_t result, const uint8_t *buf);
|
||||
// or cygwin.
|
||||
//
|
||||
// Finally, we want to exclude legacy 32-bit systems.
|
||||
#ifndef SIMDJSON_IS_32BITS
|
||||
#if SIMDJSON_IS_32BITS
|
||||
// we omit 32-bit tests
|
||||
#else
|
||||
// So we only run some of the floating-point tests under 64-bit linux, apple, regular visual studio, freebsd.
|
||||
#define TEST_FLOATS
|
||||
// Apple and freebsd need a special header, typically.
|
||||
|
||||
@@ -21,7 +21,9 @@
|
||||
// or cygwin.
|
||||
//
|
||||
// Finally, we want to exclude legacy 32-bit systems.
|
||||
#ifndef SIMDJSON_IS_32BITS
|
||||
#if SIMDJSON_IS_32BITS
|
||||
// we omit 32-bit tests
|
||||
#else
|
||||
// So we only run some of the floating-point tests under 64-bit linux, apple, regular visual studio, freebsd.
|
||||
#define TEST_FLOATS
|
||||
// Apple and freebsd need a special header, typically.
|
||||
|
||||
@@ -160,7 +160,11 @@ namespace ondemand_treewalk {
|
||||
cout << element.get_bool();
|
||||
break;
|
||||
case ondemand::json_type::null:
|
||||
cout << "null";
|
||||
// We check that the value is indeed null
|
||||
// otherwise: an error is thrown.
|
||||
if(element.is_null()) {
|
||||
cout << "null";
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -263,7 +267,7 @@ void basics_ndjson_parse_many() {
|
||||
}
|
||||
}
|
||||
void implementation_selection_1() {
|
||||
cout << "simdjson v" << SIMDJSON_STRINGIFY(SIMDJSON_VERSION) << endl;
|
||||
cout << "simdjson v" << SIMDJSON_VERSION << endl;
|
||||
cout << "Detected the best implementation for your machine: " << simdjson::get_active_implementation()->name();
|
||||
cout << "(" << simdjson::get_active_implementation()->description() << ")" << endl;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
link_libraries(simdjson)
|
||||
include_directories(..)
|
||||
add_subdirectory(compilation_failure_tests)
|
||||
add_cpp_test(ondemand_log_tests LABELS ondemand acceptance per_implementation)
|
||||
add_cpp_test(ondemand_tostring_tests LABELS ondemand acceptance per_implementation)
|
||||
add_cpp_test(ondemand_active_tests LABELS ondemand acceptance per_implementation)
|
||||
add_cpp_test(ondemand_array_tests LABELS ondemand acceptance per_implementation)
|
||||
|
||||
@@ -714,8 +714,86 @@ namespace document_stream_tests {
|
||||
return (bool_count == 0) && (total_count == 1);
|
||||
}
|
||||
|
||||
bool string_with_trailing() {
|
||||
TEST_START();
|
||||
auto json = R"( "a string" badstuff )"_padded;
|
||||
ondemand::parser parser;
|
||||
ondemand::document_stream doc;
|
||||
ASSERT_SUCCESS(parser.iterate_many(json).get(doc));
|
||||
std::string_view view;
|
||||
ASSERT_SUCCESS((*doc.begin()).get_string().get(view));
|
||||
ASSERT_EQUAL(view,"a string");
|
||||
TEST_SUCCEED();
|
||||
}
|
||||
|
||||
bool uint64_with_trailing() {
|
||||
TEST_START();
|
||||
auto json = R"( 133 badstuff )"_padded;
|
||||
ondemand::parser parser;
|
||||
ondemand::document_stream doc;
|
||||
ASSERT_SUCCESS(parser.iterate_many(json).get(doc));
|
||||
uint64_t x;
|
||||
ASSERT_SUCCESS((*doc.begin()).get_uint64().get(x));
|
||||
ASSERT_EQUAL(x,133);
|
||||
TEST_SUCCEED();
|
||||
}
|
||||
|
||||
bool int64_with_trailing() {
|
||||
TEST_START();
|
||||
auto json = R"( 133 badstuff )"_padded;
|
||||
ondemand::parser parser;
|
||||
ondemand::document_stream doc;
|
||||
ASSERT_SUCCESS(parser.iterate_many(json).get(doc));
|
||||
int64_t x;
|
||||
ASSERT_SUCCESS((*doc.begin()).get_int64().get(x));
|
||||
ASSERT_EQUAL(x,133);
|
||||
TEST_SUCCEED();
|
||||
}
|
||||
|
||||
bool double_with_trailing() {
|
||||
TEST_START();
|
||||
auto json = R"( 133 badstuff )"_padded;
|
||||
ondemand::parser parser;
|
||||
ondemand::document_stream doc;
|
||||
ASSERT_SUCCESS(parser.iterate_many(json).get(doc));
|
||||
double x;
|
||||
ASSERT_SUCCESS((*doc.begin()).get_double().get(x));
|
||||
ASSERT_EQUAL(x,133);
|
||||
TEST_SUCCEED();
|
||||
}
|
||||
|
||||
|
||||
bool bool_with_trailing() {
|
||||
TEST_START();
|
||||
auto json = R"( true badstuff )"_padded;
|
||||
ondemand::parser parser;
|
||||
ondemand::document_stream doc;
|
||||
ASSERT_SUCCESS(parser.iterate_many(json).get(doc));
|
||||
bool x;
|
||||
ASSERT_SUCCESS((*doc.begin()).get_bool().get(x));
|
||||
ASSERT_EQUAL(x,true);
|
||||
TEST_SUCCEED();
|
||||
}
|
||||
|
||||
bool null_with_trailing() {
|
||||
TEST_START();
|
||||
auto json = R"( null badstuff )"_padded;
|
||||
ondemand::parser parser;
|
||||
ondemand::document_stream doc;
|
||||
ASSERT_SUCCESS(parser.iterate_many(json).get(doc));
|
||||
bool n;
|
||||
ASSERT_SUCCESS((*doc.begin()).is_null().get(n));
|
||||
ASSERT_EQUAL(n,true);
|
||||
TEST_SUCCEED();
|
||||
}
|
||||
|
||||
bool run() {
|
||||
return
|
||||
string_with_trailing() &&
|
||||
uint64_with_trailing() &&
|
||||
int64_with_trailing() &&
|
||||
bool_with_trailing() &&
|
||||
null_with_trailing() &&
|
||||
truncated_utf8() &&
|
||||
issue1729() &&
|
||||
fuzzaccess() &&
|
||||
|
||||
@@ -119,7 +119,9 @@ namespace error_tests {
|
||||
SUBTEST("simdjson_result<ondemand::value>", test_ondemand_doc(json, [&](auto doc) {
|
||||
simdjson_result<ondemand::value> val = doc["val"];
|
||||
// Get everything that can fail in both forward and backwards order
|
||||
ASSERT_EQUAL( val.is_null(), false );
|
||||
bool is_null_value;
|
||||
ASSERT_SUCCESS( val.is_null().get(is_null_value) );
|
||||
ASSERT_EQUAL( is_null_value, false );
|
||||
ASSERT_ERROR( val.get_array(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_string(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_double(), INCORRECT_TYPE );
|
||||
@@ -131,15 +133,18 @@ namespace error_tests {
|
||||
ASSERT_ERROR( val.get_double(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_string(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_array(), INCORRECT_TYPE );
|
||||
ASSERT_EQUAL( val.is_null(), false );
|
||||
ASSERT_SUCCESS( val.get_bool() );
|
||||
ASSERT_SUCCESS( val.is_null().get(is_null_value) );
|
||||
ASSERT_EQUAL( is_null_value, false );
|
||||
TEST_SUCCEED();
|
||||
}));
|
||||
SUBTEST("ondemand::value", test_ondemand_doc(json, [&](auto doc) {
|
||||
ondemand::value val;
|
||||
ASSERT_SUCCESS( doc["val"].get(val) );
|
||||
// Get everything that can fail in both forward and backwards order
|
||||
ASSERT_EQUAL( val.is_null(), false );
|
||||
bool is_null_value;
|
||||
ASSERT_SUCCESS( val.is_null().get(is_null_value) );
|
||||
ASSERT_EQUAL( is_null_value, false );
|
||||
ASSERT_ERROR( val.get_array(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_string(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_double(), INCORRECT_TYPE );
|
||||
@@ -151,14 +156,17 @@ namespace error_tests {
|
||||
ASSERT_ERROR( val.get_double(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_string(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_array(), INCORRECT_TYPE );
|
||||
ASSERT_EQUAL( val.is_null(), false );
|
||||
ASSERT_SUCCESS( val.get_bool() );
|
||||
ASSERT_SUCCESS( val.is_null().get(is_null_value) );
|
||||
ASSERT_EQUAL( is_null_value, false );
|
||||
TEST_SUCCEED();
|
||||
}));
|
||||
json = R"(true)"_padded;
|
||||
SUBTEST("simdjson_result<ondemand::document>", test_ondemand_doc(json, [&](simdjson_result<ondemand::document> val) {
|
||||
// Get everything that can fail in both forward and backwards order
|
||||
ASSERT_EQUAL( val.is_null(), false );
|
||||
bool is_null_value;
|
||||
ASSERT_SUCCESS( val.is_null().get(is_null_value) );
|
||||
ASSERT_EQUAL( is_null_value, false );
|
||||
ASSERT_ERROR( val.get_array(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_string(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_double(), INCORRECT_TYPE );
|
||||
@@ -170,14 +178,17 @@ namespace error_tests {
|
||||
ASSERT_ERROR( val.get_double(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_string(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_array(), INCORRECT_TYPE );
|
||||
ASSERT_EQUAL( val.is_null(), false );
|
||||
ASSERT_SUCCESS( val.get_bool());
|
||||
ASSERT_SUCCESS( val.is_null().get(is_null_value) );
|
||||
ASSERT_EQUAL( is_null_value, false );
|
||||
TEST_SUCCEED();
|
||||
}));
|
||||
SUBTEST("ondemand::document", test_ondemand_doc(json, [&](auto doc) {
|
||||
ondemand::document val;
|
||||
ASSERT_SUCCESS( std::move(doc).get(val) ); // Get everything that can fail in both forward and backwards order
|
||||
ASSERT_EQUAL( val.is_null(), false );
|
||||
bool is_null_value;
|
||||
ASSERT_SUCCESS( val.is_null().get(is_null_value) );
|
||||
ASSERT_EQUAL( is_null_value, false );
|
||||
ASSERT_ERROR( val.get_array(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_string(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_double(), INCORRECT_TYPE );
|
||||
@@ -189,8 +200,9 @@ namespace error_tests {
|
||||
ASSERT_ERROR( val.get_double(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_string(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_array(), INCORRECT_TYPE );
|
||||
ASSERT_EQUAL( val.is_null(), false );
|
||||
ASSERT_SUCCESS( val.get_bool() );
|
||||
ASSERT_SUCCESS( val.is_null().get(is_null_value) );
|
||||
ASSERT_EQUAL( is_null_value, false );
|
||||
TEST_SUCCEED();
|
||||
}));
|
||||
|
||||
@@ -216,13 +228,16 @@ namespace error_tests {
|
||||
ASSERT_ERROR( val.get_string(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_array(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_bool(), INCORRECT_TYPE );
|
||||
ASSERT_EQUAL( val.is_null(), true );
|
||||
bool is_null_value;
|
||||
ASSERT_SUCCESS( val.is_null().get(is_null_value) );
|
||||
ASSERT_EQUAL( is_null_value, true );
|
||||
TEST_SUCCEED();
|
||||
}));
|
||||
SUBTEST("ondemand::value", test_ondemand_doc(json, [&](auto doc) {
|
||||
ondemand::value val;
|
||||
ASSERT_SUCCESS( doc["val"].get(val) );
|
||||
// Get everything that can fail in both forward and backwards order
|
||||
|
||||
ASSERT_ERROR( val.get_bool(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_array(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_string(), INCORRECT_TYPE );
|
||||
@@ -236,7 +251,9 @@ namespace error_tests {
|
||||
ASSERT_ERROR( val.get_string(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_array(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_bool(), INCORRECT_TYPE );
|
||||
ASSERT_EQUAL( val.is_null(), true );
|
||||
bool is_null_value;
|
||||
ASSERT_SUCCESS( val.is_null().get(is_null_value) );
|
||||
ASSERT_EQUAL( is_null_value, true );
|
||||
TEST_SUCCEED();
|
||||
}));
|
||||
json = R"(null)"_padded;
|
||||
@@ -255,7 +272,9 @@ namespace error_tests {
|
||||
ASSERT_ERROR( val.get_string(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_array(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_bool(), INCORRECT_TYPE );
|
||||
ASSERT_EQUAL( val.is_null(), true );
|
||||
bool is_null_value;
|
||||
ASSERT_SUCCESS( val.is_null().get(is_null_value) );
|
||||
ASSERT_EQUAL( is_null_value, true );
|
||||
TEST_SUCCEED();
|
||||
}));
|
||||
SUBTEST("ondemand::document", test_ondemand_doc(json, [&](auto doc) {
|
||||
@@ -274,7 +293,9 @@ namespace error_tests {
|
||||
ASSERT_ERROR( val.get_string(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_array(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_bool(), INCORRECT_TYPE );
|
||||
ASSERT_EQUAL( val.is_null(), true );
|
||||
bool is_null_value;
|
||||
ASSERT_SUCCESS( val.is_null().get(is_null_value) );
|
||||
ASSERT_EQUAL( is_null_value, true );
|
||||
TEST_SUCCEED();
|
||||
}));
|
||||
TEST_SUCCEED();
|
||||
|
||||
@@ -71,7 +71,7 @@ namespace json_pointer_tests {
|
||||
ASSERT_SUCCESS(val.get_bool().error());
|
||||
break;
|
||||
case ondemand::json_type::null:
|
||||
ASSERT_TRUE(val.is_null());
|
||||
ASSERT_SUCCESS(val.is_null().error());
|
||||
break;
|
||||
default:
|
||||
TEST_FAIL("unexpected type");
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
#define SIMDJSON_VERBOSE_LOGGING 1
|
||||
#include "simdjson.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
using namespace simdjson;
|
||||
|
||||
|
||||
int main() {
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
auto cars_json = R"( [
|
||||
{ "make": "Toyota", "model": "Camry", "year": 2018, "tire_pressure": [ 40.1, 39.9, 37.7, 40.4 ] },
|
||||
{ "make": "Kia", "model": "Soul", "year": 2012, "tire_pressure": [ 30.1, 31.0, 28.6, 28.7 ] },
|
||||
{ "make": "Toyota", "model": "Tercel", "year": 1999, "tire_pressure": [ 29.8, 30.0, 30.2, 30.5 ] }
|
||||
] )"_padded;
|
||||
ondemand::parser parser;
|
||||
ondemand::document doc = parser.iterate(cars_json);
|
||||
std::vector<std::string> container;
|
||||
for(ondemand::object o : doc) {
|
||||
container.emplace_back(std::string_view(o["make"]));
|
||||
}
|
||||
std::cout << "---" << std::endl;
|
||||
for(std::string& m : container) {
|
||||
std::cout << m << std::endl;
|
||||
}
|
||||
#endif // #if SIMDJSON_EXCEPTIONS
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@@ -52,6 +52,30 @@ namespace misc_tests {
|
||||
TEST_SUCCEED();
|
||||
}
|
||||
|
||||
bool issue_uffff() {
|
||||
TEST_START();
|
||||
ondemand::parser parser;
|
||||
auto json = R"( "wow:\uFFFF" )"_padded;
|
||||
ondemand::document doc;
|
||||
ASSERT_SUCCESS(parser.iterate(json).get(doc));
|
||||
std::string_view view;
|
||||
ASSERT_SUCCESS( doc.get_string().get(view));
|
||||
ASSERT_EQUAL(view, u8"wow:\uFFFF");
|
||||
TEST_SUCCEED();
|
||||
}
|
||||
|
||||
bool issue_backslash() {
|
||||
TEST_START();
|
||||
ondemand::parser parser;
|
||||
auto json = R"( "sc:\\./" )"_padded;
|
||||
ondemand::document doc;
|
||||
ASSERT_SUCCESS(parser.iterate(json).get(doc));
|
||||
std::string_view view;
|
||||
ASSERT_SUCCESS( doc.get_string().get(view));
|
||||
ASSERT_EQUAL(view, "sc:\\./");
|
||||
TEST_SUCCEED();
|
||||
}
|
||||
|
||||
bool issue1870() {
|
||||
TEST_START();
|
||||
ondemand::parser parser;
|
||||
@@ -271,7 +295,9 @@ namespace misc_tests {
|
||||
ASSERT_SUCCESS(global.get(global_object));
|
||||
ondemand::value shadowable;
|
||||
ASSERT_SUCCESS(global_object["shadowable"].get(shadowable));
|
||||
ASSERT_TRUE(!shadowable.is_null());
|
||||
bool is_null_value;
|
||||
ASSERT_SUCCESS(shadowable.is_null().get(is_null_value));
|
||||
ASSERT_TRUE(!is_null_value);
|
||||
ondemand::value badvalue;
|
||||
auto error = global_object["writable"].get(badvalue);
|
||||
if(error == SUCCESS) {
|
||||
@@ -494,6 +520,8 @@ namespace misc_tests {
|
||||
|
||||
bool run() {
|
||||
return
|
||||
issue_uffff() &&
|
||||
issue_backslash() &&
|
||||
issue1870() &&
|
||||
issue1894() &&
|
||||
issue1894toolarge() &&
|
||||
|
||||
@@ -36,6 +36,93 @@ namespace number_in_string_tests {
|
||||
}
|
||||
)"_padded;
|
||||
|
||||
bool in_document_int64() {
|
||||
TEST_START();
|
||||
auto json = R"( "-11232321" )"_padded;
|
||||
ondemand::parser parser;
|
||||
auto doc = parser.iterate(json);
|
||||
int64_t result;
|
||||
ASSERT_SUCCESS(doc.get_int64_in_string().get(result));
|
||||
ASSERT_EQUAL(result,-11232321);
|
||||
TEST_SUCCEED();
|
||||
}
|
||||
|
||||
bool in_document_uint64() {
|
||||
TEST_START();
|
||||
auto json = R"( "11232321" )"_padded;
|
||||
ondemand::parser parser;
|
||||
auto doc = parser.iterate(json);
|
||||
uint64_t result;
|
||||
ASSERT_SUCCESS(doc.get_uint64_in_string().get(result));
|
||||
ASSERT_EQUAL(result,11232321);
|
||||
TEST_SUCCEED();
|
||||
}
|
||||
|
||||
bool in_document_double() {
|
||||
TEST_START();
|
||||
auto json = R"( "11232321.12" )"_padded;
|
||||
ondemand::parser parser;
|
||||
auto doc = parser.iterate(json);
|
||||
double result;
|
||||
ASSERT_SUCCESS(doc.get_double_in_string().get(result));
|
||||
ASSERT_EQUAL(result,11232321.12);
|
||||
TEST_SUCCEED();
|
||||
}
|
||||
|
||||
bool stream_of_pure_int64() {
|
||||
TEST_START();
|
||||
auto json = R"( 1 2 3 )"_padded;
|
||||
|
||||
ondemand::parser parser;
|
||||
ondemand::document_stream stream;
|
||||
ASSERT_SUCCESS(parser.iterate_many(json).get(stream));
|
||||
int document_index = 0;
|
||||
for (auto doc : stream) {
|
||||
document_index++;
|
||||
int64_t result;
|
||||
ASSERT_SUCCESS(doc.get_int64().get(result));
|
||||
ASSERT_EQUAL(result,document_index);
|
||||
}
|
||||
ASSERT_EQUAL(3,document_index);
|
||||
TEST_SUCCEED();
|
||||
}
|
||||
|
||||
bool stream_of_direct_int64() {
|
||||
TEST_START();
|
||||
auto json = R"( "1" "2" "3" )"_padded;
|
||||
|
||||
ondemand::parser parser;
|
||||
ondemand::document_stream stream;
|
||||
ASSERT_SUCCESS(parser.iterate_many(json).get(stream));
|
||||
int document_index = 0;
|
||||
for (auto doc : stream) {
|
||||
document_index++;
|
||||
int64_t result;
|
||||
ASSERT_SUCCESS(doc.get_int64_in_string().get(result));
|
||||
ASSERT_EQUAL(result,document_index);
|
||||
}
|
||||
ASSERT_EQUAL(3,document_index);
|
||||
TEST_SUCCEED();
|
||||
}
|
||||
|
||||
bool stream_of_int64() {
|
||||
TEST_START();
|
||||
auto json = R"( ["1"] ["2"] ["3"] )"_padded;
|
||||
|
||||
ondemand::parser parser;
|
||||
ondemand::document_stream stream;
|
||||
ASSERT_SUCCESS(parser.iterate_many(json).get(stream));
|
||||
int document_index = 0;
|
||||
for (auto doc : stream) {
|
||||
document_index++;
|
||||
int64_t result;
|
||||
ASSERT_SUCCESS(doc.get_array().at(0).get_int64_in_string().get(result));
|
||||
ASSERT_EQUAL(result,document_index);
|
||||
}
|
||||
ASSERT_EQUAL(3,document_index);
|
||||
TEST_SUCCEED();
|
||||
}
|
||||
|
||||
bool array_double() {
|
||||
TEST_START();
|
||||
auto json = R"(["1.2","2.3","-42.3","2.43442e3", "-1.234e3"])"_padded;
|
||||
@@ -255,7 +342,13 @@ namespace number_in_string_tests {
|
||||
}
|
||||
|
||||
bool run() {
|
||||
return array_double() &&
|
||||
return stream_of_pure_int64() &&
|
||||
stream_of_direct_int64() &&
|
||||
stream_of_int64() &&
|
||||
in_document_int64() &&
|
||||
in_document_uint64() &&
|
||||
in_document_double() &&
|
||||
array_double() &&
|
||||
array_int() &&
|
||||
array_unsigned() &&
|
||||
object() &&
|
||||
|
||||
@@ -87,7 +87,11 @@ void recursive_print_json(ondemand::value element) {
|
||||
cout << element.get_bool();
|
||||
break;
|
||||
case ondemand::json_type::null:
|
||||
cout << "null";
|
||||
// we check that the value is indeed null
|
||||
// otherwise: an error is thrown.
|
||||
if(element.is_null()) {
|
||||
cout << "null";
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -166,7 +170,11 @@ void recursive_print_json_breakline(ondemand::value element) {
|
||||
cout << element.get_bool();
|
||||
break;
|
||||
case ondemand::json_type::null:
|
||||
cout << "null";
|
||||
// We check that the value is indeed null
|
||||
// otherwise: an error is thrown.
|
||||
if(element.is_null()) {
|
||||
cout << "null";
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -206,11 +206,15 @@ namespace scalar_tests {
|
||||
SUBTEST("ondemand::document", test_ondemand_doc(json, [&](auto doc_result) {
|
||||
ondemand::document doc;
|
||||
ASSERT_SUCCESS( std::move(doc_result).get(doc) );
|
||||
ASSERT_EQUAL( doc.is_null(), true );
|
||||
bool is_null_value;
|
||||
ASSERT_SUCCESS( doc.is_null().get(is_null_value) );
|
||||
ASSERT_EQUAL( is_null_value, true );
|
||||
return true;
|
||||
}));
|
||||
SUBTEST("simdjson_result<ondemand::document>", test_ondemand_doc(json, [&](auto doc_result) {
|
||||
ASSERT_EQUAL( doc_result.is_null(), true );
|
||||
bool is_null_value;
|
||||
ASSERT_SUCCESS( doc_result.is_null().get(is_null_value) );
|
||||
ASSERT_EQUAL( is_null_value, true );
|
||||
return true;
|
||||
}));
|
||||
json = "[null]"_padded;
|
||||
@@ -219,7 +223,9 @@ namespace scalar_tests {
|
||||
for (auto value_result : doc_result) {
|
||||
ondemand::value value;
|
||||
ASSERT_SUCCESS( value_result.get(value) );
|
||||
ASSERT_EQUAL( value.is_null(), true );
|
||||
bool is_null_value;
|
||||
ASSERT_SUCCESS( value.is_null().get(is_null_value) );
|
||||
ASSERT_EQUAL( is_null_value, true );
|
||||
count++;
|
||||
}
|
||||
ASSERT_EQUAL( count, 1 );
|
||||
@@ -228,7 +234,9 @@ namespace scalar_tests {
|
||||
SUBTEST("simdjson_result<ondemand::value>", test_ondemand_doc(json, [&](auto doc_result) {
|
||||
int count = 0;
|
||||
for (auto value_result : doc_result) {
|
||||
ASSERT_EQUAL( value_result.is_null(), true );
|
||||
bool is_null_value;
|
||||
ASSERT_SUCCESS( value_result.is_null().get(is_null_value) );
|
||||
ASSERT_EQUAL( is_null_value, true );
|
||||
count++;
|
||||
}
|
||||
ASSERT_EQUAL( count, 1 );
|
||||
@@ -289,8 +297,92 @@ namespace scalar_tests {
|
||||
|
||||
#endif // SIMDJSON_EXCEPTIONS
|
||||
|
||||
bool string_with_trailing() {
|
||||
TEST_START();
|
||||
auto json = R"( "a string" badstuff )"_padded;
|
||||
ondemand::parser parser;
|
||||
ondemand::document doc;
|
||||
ASSERT_SUCCESS(parser.iterate(json).get(doc));
|
||||
std::string_view view;
|
||||
ASSERT_ERROR(doc.get_string().get(view), TRAILING_CONTENT);
|
||||
TEST_SUCCEED();
|
||||
}
|
||||
|
||||
bool uint64_with_trailing() {
|
||||
TEST_START();
|
||||
auto json = R"( 133 badstuff )"_padded;
|
||||
ondemand::parser parser;
|
||||
ondemand::document doc;
|
||||
ASSERT_SUCCESS(parser.iterate(json).get(doc));
|
||||
uint64_t x;
|
||||
ASSERT_ERROR(doc.get_uint64().get(x), TRAILING_CONTENT);
|
||||
TEST_SUCCEED();
|
||||
}
|
||||
|
||||
bool int64_with_trailing() {
|
||||
TEST_START();
|
||||
auto json = R"( 133 badstuff )"_padded;
|
||||
ondemand::parser parser;
|
||||
ondemand::document doc;
|
||||
ASSERT_SUCCESS(parser.iterate(json).get(doc));
|
||||
int64_t x;
|
||||
ASSERT_ERROR(doc.get_int64().get(x), TRAILING_CONTENT);
|
||||
TEST_SUCCEED();
|
||||
}
|
||||
|
||||
bool double_with_trailing() {
|
||||
TEST_START();
|
||||
auto json = R"( 133 badstuff )"_padded;
|
||||
ondemand::parser parser;
|
||||
ondemand::document doc;
|
||||
ASSERT_SUCCESS(parser.iterate(json).get(doc));
|
||||
double x;
|
||||
ASSERT_ERROR(doc.get_double().get(x), TRAILING_CONTENT);
|
||||
TEST_SUCCEED();
|
||||
}
|
||||
|
||||
|
||||
bool bool_with_trailing() {
|
||||
TEST_START();
|
||||
auto json = R"( true badstuff )"_padded;
|
||||
ondemand::parser parser;
|
||||
ondemand::document doc;
|
||||
ASSERT_SUCCESS(parser.iterate(json).get(doc));
|
||||
bool x;
|
||||
ASSERT_ERROR(doc.get_bool().get(x), TRAILING_CONTENT);
|
||||
TEST_SUCCEED();
|
||||
}
|
||||
|
||||
bool null_with_trailing() {
|
||||
TEST_START();
|
||||
auto json = R"( null badstuff )"_padded;
|
||||
ondemand::parser parser;
|
||||
ondemand::document doc;
|
||||
ASSERT_SUCCESS(parser.iterate(json).get(doc));
|
||||
ASSERT_ERROR(doc.is_null(), TRAILING_CONTENT);
|
||||
TEST_SUCCEED();
|
||||
}
|
||||
|
||||
bool nully() {
|
||||
TEST_START();
|
||||
auto json = R"( nully )"_padded;
|
||||
ondemand::parser parser;
|
||||
ondemand::document doc;
|
||||
ASSERT_SUCCESS(parser.iterate(json).get(doc));
|
||||
bool x;
|
||||
ASSERT_SUCCESS(doc.is_null().get(x));
|
||||
ASSERT_TRUE(!x);
|
||||
TEST_SUCCEED();
|
||||
}
|
||||
|
||||
bool run() {
|
||||
return
|
||||
nully() &&
|
||||
string_with_trailing() &&
|
||||
uint64_with_trailing() &&
|
||||
int64_with_trailing() &&
|
||||
bool_with_trailing() &&
|
||||
null_with_trailing() &&
|
||||
string_value() &&
|
||||
numeric_values() &&
|
||||
boolean_values() &&
|
||||
|
||||
+13
-1
@@ -20,7 +20,7 @@ int main(int argc, const char *argv[]) {
|
||||
std::string progName = "json2json";
|
||||
|
||||
std::string progUsage = "json2json version ";
|
||||
progUsage += SIMDJSON_STRINGIFY(SIMDJSON_VERSION);
|
||||
progUsage += SIMDJSON_VERSION;
|
||||
progUsage += " (";
|
||||
progUsage += simdjson::get_active_implementation()->name();
|
||||
progUsage += ")\n";
|
||||
@@ -63,7 +63,19 @@ int main(int argc, const char *argv[]) {
|
||||
simdjson::ondemand::document doc;
|
||||
error = parser.iterate(docdata).get(doc);
|
||||
if(error != simdjson::SUCCESS) { std::cout << error << std::endl; return EXIT_FAILURE; }
|
||||
// This locates the document and captures a string_view instance, it does
|
||||
// not validate the document:
|
||||
std::cout << doc;
|
||||
// check if there is more content
|
||||
const char * endofstream;
|
||||
if(doc.current_location().get(endofstream) == simdjson::SUCCESS) {
|
||||
// there is more content !
|
||||
// let us find what it is:
|
||||
size_t len = docdata.data() + docdata.size() - endofstream;
|
||||
std::string_view content{endofstream, len};
|
||||
std::cerr << "\nThere is leftover content: '" << content << "'" << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
simdjson::dom::parser parser;
|
||||
|
||||
Executable
+21
@@ -0,0 +1,21 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
PACKAGE_URL="https://github.com/jothepro/doxygen-awesome-css.git"
|
||||
PACKAGE_VERSION="v2.1.0"
|
||||
|
||||
BASE_DIR=$(pwd)
|
||||
THEME_DIR="$BASE_DIR/theme"
|
||||
WORKSPACE=$(mktemp -d 2> /dev/null || mktemp -d -t 'tmp')
|
||||
cleanup () {
|
||||
EXIT_CODE=$?
|
||||
[ -d "$WORKSPACE" ] && rm -rf "$WORKSPACE"
|
||||
exit $EXIT_CODE
|
||||
}
|
||||
|
||||
trap cleanup INT TERM EXIT
|
||||
|
||||
cd "$WORKSPACE"
|
||||
git clone --depth=1 --branch "$PACKAGE_VERSION" "$PACKAGE_URL" theme
|
||||
rm -rf "$THEME_DIR"
|
||||
mv "$WORKSPACE/theme" "$BASE_DIR"
|
||||
Reference in New Issue
Block a user