mirror of
https://github.com/simdjson/simdjson
synced 2026-06-08 17:27:07 +00:00
Compare commits
64 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8149284602 | |||
| 0e28a8312d | |||
| 04ab4bb4d9 | |||
| 3960880a0d | |||
| e0f906da79 | |||
| 6a054395a6 | |||
| eac04c7324 | |||
| 319b10acad | |||
| d2d15255bc | |||
| 5b7acd2aa7 | |||
| 61ef447595 | |||
| b524e29576 | |||
| a7b7bc2b69 | |||
| 76dd137c87 | |||
| 52b2414281 | |||
| 5d762fb67f | |||
| 9dc70e8d9c | |||
| 589ef23b56 | |||
| 4b1148384e | |||
| 32afd34a90 | |||
| 70674d2dbd | |||
| f594a49a4b | |||
| 54cbebfd29 | |||
| c6e43a631c | |||
| a8635c9b89 | |||
| 075bfb173b | |||
| a88ad515c2 | |||
| 78b4c0aa6e | |||
| 14ec0ca8f4 | |||
| 8dabd02c3a | |||
| c9692005fd | |||
| 2e0a9397c9 | |||
| f7922075c3 | |||
| b2e20e04c9 | |||
| adc9d18efd | |||
| bf849e3619 | |||
| c09e8dc225 | |||
| 5bf585ef02 | |||
| caff09cafc | |||
| f043db4dca | |||
| e3bd0828d1 | |||
| 9408298e0e | |||
| 573bbac2d2 | |||
| ac78c625df | |||
| 390a66c6e8 | |||
| 210e0a56a1 | |||
| 084f662f32 | |||
| c878ff2500 | |||
| 06afe9ecb3 | |||
| e658502adb | |||
| 6e7d415040 | |||
| 2ccd5b9c97 | |||
| 1cdcbf79b3 | |||
| 7013ed98cc | |||
| b383c717d7 | |||
| b8743bced0 | |||
| ae9ba2bed2 | |||
| 939844d79f | |||
| 4f4e81668e | |||
| bb54946b78 | |||
| 4dec6ed5a7 | |||
| 1dfd48195d | |||
| 23afc6b695 | |||
| 80bc9e5051 |
@@ -1,5 +1,8 @@
|
||||
CompileFlags:
|
||||
CompilationDatabase: build
|
||||
Add:
|
||||
- -Werror -Wall -Wextra -Weffc++ -Wsign-compare -Wshadow -Wwrite-strings -Wpointer-arith -Winit-self -Wconversion -Wno-sign-conversion
|
||||
- -Wundefined-inline
|
||||
Diagnostics:
|
||||
Suppress:
|
||||
- misc-unused-alias-decls
|
||||
@@ -16,10 +19,28 @@ If:
|
||||
CompileFlags:
|
||||
Add:
|
||||
- -Wno-unneeded-internal-declaration
|
||||
- -Wno-undefined-inline # TODO fix and remove these violations
|
||||
- -Wno-undefined-internal # TODO fix and remove these violations
|
||||
- -Wno-unused-function
|
||||
- -Wno-unused-const-variable
|
||||
Diagnostics:
|
||||
Suppress:
|
||||
- pp_including_mainfile_in_preamble
|
||||
---
|
||||
# Amalgamated files that require or partly define an implementation
|
||||
If:
|
||||
PathMatch:
|
||||
- .*/(arm64|fallback|haswell|icelake|ppc64|westmere)/begin.h
|
||||
- .*/generic/.*
|
||||
Diagnostics:
|
||||
Suppress:
|
||||
- pragma_attribute_no_pop_eof
|
||||
---
|
||||
# clang has a bad time detecting the push/pop together in src/ for some reason
|
||||
If:
|
||||
PathMatch:
|
||||
- include/simdjson/.*/end.h
|
||||
- src/(arm64|fallback|haswell|icelake|ppc64|westmere).cpp
|
||||
Diagnostics:
|
||||
Suppress:
|
||||
- pragma_attribute_no_pop_eof
|
||||
- pragma_attribute_stack_mismatch
|
||||
|
||||
@@ -49,7 +49,7 @@ It is fine to report bugs against our main branch, but if that is what you are d
|
||||
- Version [e.g. 22]
|
||||
- Optimization setting (e.g., -O3)
|
||||
|
||||
We support up-to-date 64-bit ARM and x64 FreeBSD, macOS, Windows and Linux systems. Please ensure that your configuration is supported before labelling the issue as a bug. In particular, we do not support legacy 32-bit systems.
|
||||
We support up-to-date 64-bit ARM and x64 FreeBSD, macOS, Windows and Linux systems. Please ensure that your configuration is supported before labelling the issue as a bug.
|
||||
|
||||
**Indicate whether you are willing or able to provide a bug fix as a pull request**
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ jobs:
|
||||
# fuzzers that change behaviour with SIMDJSON_FORCE_IMPLEMENTATION
|
||||
defaultimplfuzzers: atpointer dump dump_raw_tape element minify parser print_json
|
||||
# fuzzers that loop over the implementations themselves, or don't need to switch.
|
||||
implfuzzers: implementations minifyimpl ndjson ondemand padded utf8 # TODO add singlestage
|
||||
implfuzzers: implementations minifyimpl ndjson ondemand padded utf8
|
||||
implementations: haswell westmere fallback
|
||||
UBSAN_OPTIONS: halt_on_error=1
|
||||
MAXLEN: -max_len=4000
|
||||
@@ -34,6 +34,7 @@ jobs:
|
||||
sudo apt update
|
||||
sudo apt-get install --quiet ninja-build valgrind zip unzip lsb-release wget software-properties-common gnupg
|
||||
wget https://apt.llvm.org/llvm.sh
|
||||
sudo apt-get purge --auto-remove llvm python3-lldb-14 llvm-14
|
||||
chmod +x llvm.sh
|
||||
sudo ./llvm.sh $CLANGVERSION
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ name: Ubuntu 20.04 CI (GCC 9) With Memory Sanitizer
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
ubuntu-build:
|
||||
ubuntu-build-address-sanitizier:
|
||||
if: >-
|
||||
! contains(toJSON(github.event.commits.*.message), '[skip ci]') &&
|
||||
! contains(toJSON(github.event.commits.*.message), '[skip github]')
|
||||
@@ -21,6 +21,18 @@ jobs:
|
||||
cmake -DSIMDJSON_SANITIZE=ON -DCMAKE_BUILD_TYPE=Debug -DSIMDJSON_GOOGLE_BENCHMARKS=OFF -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=OFF .. &&
|
||||
cmake --build . &&
|
||||
ctest --output-on-failure -LE explicitonly -j
|
||||
ubuntu-build-undefined-sanitizer:
|
||||
if: >-
|
||||
! contains(toJSON(github.event.commits.*.message), '[skip ci]') &&
|
||||
! contains(toJSON(github.event.commits.*.message), '[skip github]')
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/cache@v3
|
||||
with:
|
||||
path: dependencies/.cache
|
||||
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
|
||||
ctest --output-on-failure -LE explicitonly -j
|
||||
- name: Use cmake with undefined sanitizer
|
||||
run: |
|
||||
mkdir builddebugundefsani &&
|
||||
|
||||
@@ -14,6 +14,20 @@ jobs:
|
||||
with:
|
||||
path: dependencies/.cache
|
||||
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
|
||||
- name: Use cmake to build just the library
|
||||
run: |
|
||||
mkdir buildjustlib &&
|
||||
cd buildjustlib &&
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DSIMDJSON_DEVELOPER_MODE=OFF -DCMAKE_INSTALL_PREFIX:PATH=destination .. &&
|
||||
cmake --build . &&
|
||||
cmake --install . &&
|
||||
echo -e '#include <simdjson.h>\nint main(int argc,char**argv) {simdjson::dom::parser parser;simdjson::dom::element tweets = parser.load(argv[1]); }' > tmp.cpp &&
|
||||
c++ -Idestination/include -Ldestination/lib -std=c++17 -Wl,-rpath,destination/lib -o linkandrun tmp.cpp -lsimdjson &&
|
||||
cd ../tests/installation_tests/find &&
|
||||
mkdir buildjustlib &&
|
||||
cd buildjustlib &&
|
||||
cmake -DCMAKE_INSTALL_PREFIX:PATH=../../../buildjustlib/destination .. &&
|
||||
cmake --build .
|
||||
- name: Use cmake
|
||||
run: |
|
||||
mkdir builddebug &&
|
||||
|
||||
@@ -14,8 +14,6 @@ jobs:
|
||||
with:
|
||||
path: dependencies/.cache
|
||||
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
|
||||
- name: Install clang++-13
|
||||
run: sudo apt-get install -y clang++-13
|
||||
- name: Use cmake
|
||||
run: |
|
||||
mkdir build &&
|
||||
|
||||
@@ -14,8 +14,6 @@ jobs:
|
||||
with:
|
||||
path: dependencies/.cache
|
||||
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
|
||||
- name: Install clang++-14
|
||||
run: sudo apt-get install -y clang++-14
|
||||
- name: Use cmake
|
||||
run: |
|
||||
mkdir build &&
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
name: Ubuntu 20.04 CI (GCC 9) with Thread Sanitizer
|
||||
name: Ubuntu 22.04 CI (GCC 11) with Thread Sanitizer
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
@@ -7,7 +7,7 @@ jobs:
|
||||
if: >-
|
||||
! contains(toJSON(github.event.commits.*.message), '[skip ci]') &&
|
||||
! contains(toJSON(github.event.commits.*.message), '[skip github]')
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/cache@v3
|
||||
@@ -14,6 +14,20 @@ jobs:
|
||||
with:
|
||||
path: dependencies/.cache
|
||||
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
|
||||
- name: Use cmake to build just the library
|
||||
run: |
|
||||
mkdir buildjustlib &&
|
||||
cd buildjustlib &&
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DSIMDJSON_DEVELOPER_MODE=OFF -DCMAKE_INSTALL_PREFIX:PATH=destination .. &&
|
||||
cmake --build . &&
|
||||
cmake --install . &&
|
||||
echo -e '#include <simdjson.h>\nint main(int argc,char**argv) {simdjson::dom::parser parser;simdjson::dom::element tweets = parser.load(argv[1]); }' > tmp.cpp &&
|
||||
c++ -Idestination/include -Ldestination/lib -std=c++17 -Wl,-rpath,destination/lib -o linkandrun tmp.cpp -lsimdjson &&
|
||||
cd ../tests/installation_tests/find &&
|
||||
mkdir buildjustlib &&
|
||||
cd buildjustlib &&
|
||||
cmake -DCMAKE_INSTALL_PREFIX:PATH=../../../buildjustlib/destination .. &&
|
||||
cmake --build .
|
||||
- name: Use cmake
|
||||
run: |
|
||||
mkdir builddebug &&
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.14)
|
||||
project(
|
||||
simdjson
|
||||
# The version number is modified by tools/release.py
|
||||
VERSION 3.2.1
|
||||
VERSION 3.2.3
|
||||
DESCRIPTION "Parsing gigabytes of JSON per second"
|
||||
HOMEPAGE_URL "https://simdjson.org/"
|
||||
LANGUAGES CXX C
|
||||
|
||||
@@ -38,7 +38,7 @@ PROJECT_NAME = simdjson
|
||||
# could be handy for archiving the generated documentation or if some version
|
||||
# control system is used.
|
||||
|
||||
PROJECT_NUMBER = "3.2.1"
|
||||
PROJECT_NUMBER = "3.2.3"
|
||||
|
||||
# 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
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
|
||||
#include "amazon_cellphones.h"
|
||||
|
||||
namespace amazon_cellphones {
|
||||
|
||||
using namespace simdjson;
|
||||
|
||||
template<bool threaded>
|
||||
struct simdjson_singlestage {
|
||||
using StringType = std::string;
|
||||
|
||||
singlestage::parser parser{};
|
||||
|
||||
bool run(simdjson::padded_string &json, std::map<StringType, brand> &result) {
|
||||
#ifdef SIMDJSON_THREADS_ENABLED
|
||||
parser.threaded = threaded;
|
||||
#endif
|
||||
singlestage::document_stream stream = parser.iterate_many(json);
|
||||
singlestage::document_stream::iterator i = stream.begin();
|
||||
++i; // Skip first line
|
||||
for (;i != stream.end(); ++i) {
|
||||
auto doc = *i;
|
||||
size_t index{0};
|
||||
StringType copy;
|
||||
double rating;
|
||||
uint64_t reviews;
|
||||
for ( auto value : doc ) {
|
||||
switch (index)
|
||||
{
|
||||
case 1:
|
||||
copy = StringType(std::string_view(value));
|
||||
break;
|
||||
case 5:
|
||||
rating = double(value);
|
||||
break;
|
||||
case 7:
|
||||
reviews = uint64_t(value);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
auto x = result.find(copy);
|
||||
if (x == result.end()) { // If key not found, add new key
|
||||
result.emplace(copy, amazon_cellphones::brand{
|
||||
rating * reviews,
|
||||
reviews
|
||||
});
|
||||
} else { // Otherwise, update key data
|
||||
x->second.cumulative_rating += rating * reviews;
|
||||
x->second.reviews_count += reviews;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
BENCHMARK_TEMPLATE(amazon_cellphones, simdjson_singlestage<UNTHREADED>)->UseManualTime();
|
||||
#ifdef SIMDJSON_THREADS_ENABLED
|
||||
BENCHMARK_TEMPLATE(amazon_cellphones, simdjson_singlestage<THREADED>)->UseManualTime();
|
||||
#endif
|
||||
|
||||
} // namespace amazon_cellphones
|
||||
|
||||
#endif // SIMDJSON_EXCEPTIONS
|
||||
File diff suppressed because it is too large
Load Diff
@@ -26,7 +26,6 @@ SIMDJSON_PUSH_DISABLE_ALL_WARNINGS
|
||||
|
||||
SIMDJSON_POP_DISABLE_WARNINGS
|
||||
#include "json2msgpack/simdjson_ondemand.h"
|
||||
#include "json2msgpack/simdjson_singlestage.h"
|
||||
#include "json2msgpack/simdjson_dom.h"
|
||||
#include "json2msgpack/yyjson.h"
|
||||
#include "json2msgpack/rapidjson.h"
|
||||
@@ -36,7 +35,6 @@ SIMDJSON_POP_DISABLE_WARNINGS
|
||||
#include "json2msgpack/nlohmann_json.h"
|
||||
|
||||
#include "partial_tweets/simdjson_ondemand.h"
|
||||
#include "partial_tweets/simdjson_singlestage.h"
|
||||
#include "partial_tweets/simdjson_dom.h"
|
||||
#include "partial_tweets/yyjson.h"
|
||||
#if SIMDJSON_COMPETITION_ONDEMAND_SAJSON
|
||||
@@ -54,8 +52,6 @@ SIMDJSON_POP_DISABLE_WARNINGS
|
||||
|
||||
#include "distinct_user_id/simdjson_ondemand.h"
|
||||
#include "distinct_user_id/simdjson_ondemand_json_pointer.h"
|
||||
#include "distinct_user_id/simdjson_singlestage.h"
|
||||
#include "distinct_user_id/simdjson_singlestage_json_pointer.h"
|
||||
#include "distinct_user_id/simdjson_dom.h"
|
||||
#include "distinct_user_id/simdjson_dom_json_pointer.h"
|
||||
#include "distinct_user_id/yyjson.h"
|
||||
@@ -72,7 +68,6 @@ SIMDJSON_POP_DISABLE_WARNINGS
|
||||
#endif // SIMDJSON_COMPETITION_SAX
|
||||
|
||||
#include "find_tweet/simdjson_ondemand.h"
|
||||
#include "find_tweet/simdjson_singlestage.h"
|
||||
#include "find_tweet/simdjson_dom.h"
|
||||
#include "find_tweet/yyjson.h"
|
||||
#if SIMDJSON_COMPETITION_ONDEMAND_SAJSON
|
||||
@@ -88,7 +83,6 @@ SIMDJSON_POP_DISABLE_WARNINGS
|
||||
#endif // SIMDJSON_COMPETITION_SAX
|
||||
|
||||
#include "top_tweet/simdjson_ondemand.h"
|
||||
#include "top_tweet/simdjson_singlestage.h"
|
||||
#include "top_tweet/simdjson_dom.h"
|
||||
#include "top_tweet/yyjson.h"
|
||||
#if SIMDJSON_COMPETITION_ONDEMAND_SAJSON
|
||||
@@ -105,7 +99,6 @@ SIMDJSON_POP_DISABLE_WARNINGS
|
||||
|
||||
|
||||
#include "kostya/simdjson_ondemand.h"
|
||||
#include "kostya/simdjson_singlestage.h"
|
||||
#include "kostya/simdjson_dom.h"
|
||||
#include "kostya/yyjson.h"
|
||||
#if SIMDJSON_COMPETITION_ONDEMAND_SAJSON
|
||||
@@ -124,10 +117,6 @@ SIMDJSON_POP_DISABLE_WARNINGS
|
||||
#if SIMDJSON_COMPETITION_ONDEMAND_UNORDERED
|
||||
#include "large_random/simdjson_ondemand_unordered.h"
|
||||
#endif // SIMDJSON_COMPETITION_ONDEMAND_UNORDERED
|
||||
#include "large_random/simdjson_singlestage.h"
|
||||
#if SIMDJSON_COMPETITION_SINGLESTAGE_UNORDERED
|
||||
#include "large_random/simdjson_singlestage_unordered.h"
|
||||
#endif // SIMDJSON_COMPETITION_SINGLESTAGE_UNORDERED
|
||||
#include "large_random/simdjson_dom.h"
|
||||
#include "large_random/yyjson.h"
|
||||
#if SIMDJSON_COMPETITION_ONDEMAND_SAJSON
|
||||
@@ -144,10 +133,8 @@ SIMDJSON_POP_DISABLE_WARNINGS
|
||||
|
||||
#include "amazon_cellphones/simdjson_dom.h"
|
||||
#include "amazon_cellphones/simdjson_ondemand.h"
|
||||
#include "amazon_cellphones/simdjson_singlestage.h"
|
||||
|
||||
#include "large_amazon_cellphones/simdjson_dom.h"
|
||||
#include "large_amazon_cellphones/simdjson_ondemand.h"
|
||||
#include "large_amazon_cellphones/simdjson_singlestage.h"
|
||||
|
||||
BENCHMARK_MAIN();
|
||||
|
||||
+13
-9
@@ -445,7 +445,7 @@ struct benchmarker {
|
||||
return 100.0 * a / b;
|
||||
}
|
||||
|
||||
void print(bool tabbed_output) const {
|
||||
void print(bool tabbed_output, bool stage1_only) const {
|
||||
if (tabbed_output) {
|
||||
char* filename_copy = reinterpret_cast<char*>(malloc(strlen(filename)+1));
|
||||
SIMDJSON_PUSH_DISABLE_WARNINGS
|
||||
@@ -503,17 +503,21 @@ struct benchmarker {
|
||||
stats->blocks_with_16_structurals_flipped, percent(stats->blocks_with_16_structurals_flipped, stats->blocks));
|
||||
}
|
||||
printf("\n");
|
||||
printf("All Stages (excluding allocation)\n");
|
||||
print_aggregate("| " , all_stages_without_allocation.best);
|
||||
// frequently, allocation is a tiny fraction of the running time so we omit it
|
||||
if(allocate_stage.best.elapsed_sec() > 0.01 * all_stages_without_allocation.best.elapsed_sec()) {
|
||||
printf("|- Allocation\n");
|
||||
print_aggregate("| ", allocate_stage.best);
|
||||
if(!stage1_only) {
|
||||
printf("All Stages (excluding allocation)\n");
|
||||
print_aggregate("| " , all_stages_without_allocation.best);
|
||||
// frequently, allocation is a tiny fraction of the running time so we omit it
|
||||
if(allocate_stage.best.elapsed_sec() > 0.01 * all_stages_without_allocation.best.elapsed_sec()) {
|
||||
printf("|- Allocation\n");
|
||||
print_aggregate("| ", allocate_stage.best);
|
||||
}
|
||||
}
|
||||
printf("|- Stage 1\n");
|
||||
print_aggregate("| ", stage1.best);
|
||||
printf("|- Stage 2\n");
|
||||
print_aggregate("| ", stage2.best);
|
||||
if(!stage1_only) {
|
||||
printf("|- Stage 2\n");
|
||||
print_aggregate("| ", stage2.best);
|
||||
}
|
||||
if (collector.has_events()) {
|
||||
double freq1 = (stage1.best.cycles() / stage1.best.elapsed_sec()) / 1000000000.0;
|
||||
double freq2 = (stage2.best.cycles() / stage2.best.elapsed_sec()) / 1000000000.0;
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
|
||||
#include "distinct_user_id.h"
|
||||
|
||||
namespace distinct_user_id {
|
||||
|
||||
using namespace simdjson;
|
||||
|
||||
struct simdjson_singlestage {
|
||||
singlestage::parser parser{};
|
||||
|
||||
bool run(simdjson::padded_string &json, std::vector<uint64_t> &result) {
|
||||
// Walk the document, parsing as we go
|
||||
auto doc = parser.iterate(json);
|
||||
for (singlestage::object tweet : doc.find_field("statuses")) {
|
||||
// We believe that all statuses have a matching
|
||||
// user, and we are willing to throw when they do not.
|
||||
result.push_back(tweet.find_field("user").find_field("id"));
|
||||
// Not all tweets have a "retweeted_status", but when they do
|
||||
// we want to go and find the user within.
|
||||
auto retweet = tweet.find_field("retweeted_status");
|
||||
if (!retweet.error()) {
|
||||
result.push_back(retweet.find_field("user").find_field("id"));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
BENCHMARK_TEMPLATE(distinct_user_id, simdjson_singlestage)->UseManualTime();
|
||||
|
||||
} // namespace distinct_user_id
|
||||
|
||||
#endif // SIMDJSON_EXCEPTIONS
|
||||
@@ -1,37 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
|
||||
#include "distinct_user_id.h"
|
||||
|
||||
namespace distinct_user_id {
|
||||
|
||||
using namespace simdjson;
|
||||
|
||||
struct simdjson_singlestage_json_pointer {
|
||||
singlestage::parser parser{};
|
||||
|
||||
bool run(simdjson::padded_string &json, std::vector<uint64_t> &result) {
|
||||
// Walk the document, parsing as we go
|
||||
auto doc = parser.iterate(json);
|
||||
for (singlestage::object tweet : doc.find_field("statuses")) {
|
||||
// We believe that all statuses have a matching
|
||||
// user, and we are willing to throw when they do not.
|
||||
result.push_back(tweet.at_pointer("/user/id"));
|
||||
// Not all tweets have a "retweeted_status", but when they do
|
||||
// we want to go and find the user within.
|
||||
auto retweet_id = tweet.at_pointer("/retweeted_status/user/id");
|
||||
if (retweet_id.error() != NO_SUCH_FIELD) {
|
||||
result.push_back(retweet_id);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
BENCHMARK_TEMPLATE(distinct_user_id, simdjson_singlestage_json_pointer)->UseManualTime();
|
||||
|
||||
} // namespace distinct_user_id
|
||||
|
||||
#endif // SIMDJSON_EXCEPTIONS
|
||||
@@ -218,7 +218,7 @@ int main(int argc, char *argv[]) {
|
||||
if (!options.verbose) { progress.erase(); }
|
||||
|
||||
for (size_t i=0; i<options.files.size(); i++) {
|
||||
benchmarkers[i]->print(options.tabbed_output);
|
||||
benchmarkers[i]->print(options.tabbed_output, options.stage1_only);
|
||||
delete benchmarkers[i];
|
||||
}
|
||||
|
||||
|
||||
@@ -34,11 +34,15 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "linux-perf-events.h"
|
||||
#ifdef __linux__
|
||||
#include "linux-perf-events.h"
|
||||
#include <libgen.h>
|
||||
#endif
|
||||
|
||||
#if __APPLE__ && __aarch64__
|
||||
#include "apple/apple_arm_events.h"
|
||||
#endif
|
||||
|
||||
#include "simdjson.h"
|
||||
|
||||
using std::string;
|
||||
@@ -134,7 +138,7 @@ struct event_collector {
|
||||
|
||||
#if defined(__linux__)
|
||||
LinuxEvents<PERF_TYPE_HARDWARE> linux_events;
|
||||
event_collector(simdjson_unused bool quiet = false) : linux_events(vector<int>{
|
||||
event_collector() : linux_events(vector<int>{
|
||||
#if SIMDJSON_SIMPLE_PERFORMANCE_COUNTERS
|
||||
PERF_COUNT_HW_CPU_CYCLES,
|
||||
PERF_COUNT_HW_INSTRUCTIONS,
|
||||
@@ -149,8 +153,17 @@ struct event_collector {
|
||||
bool has_events() {
|
||||
return linux_events.is_working();
|
||||
}
|
||||
#elif __APPLE__ && __aarch64__
|
||||
AppleEvents apple_events;
|
||||
performance_counters diff;
|
||||
event_collector() : diff(0) {
|
||||
apple_events.setup_performance_counters();
|
||||
}
|
||||
bool has_events() {
|
||||
return apple_events.setup_performance_counters();
|
||||
}
|
||||
#else
|
||||
event_collector(simdjson_unused bool _quiet = false) {}
|
||||
event_collector() {}
|
||||
bool has_events() {
|
||||
return false;
|
||||
}
|
||||
@@ -159,6 +172,8 @@ struct event_collector {
|
||||
simdjson_inline void start() {
|
||||
#if defined(__linux)
|
||||
linux_events.start();
|
||||
#elif __APPLE__ && __aarch64__
|
||||
if(has_events()) { diff = apple_events.get_counters(); }
|
||||
#endif
|
||||
start_clock = steady_clock::now();
|
||||
}
|
||||
@@ -166,6 +181,16 @@ struct event_collector {
|
||||
time_point<steady_clock> end_clock = steady_clock::now();
|
||||
#if defined(__linux)
|
||||
linux_events.end(count.event_counts);
|
||||
#elif __APPLE__ && __aarch64__
|
||||
if(has_events()) {
|
||||
performance_counters end = apple_events.get_counters();
|
||||
diff = end - diff;
|
||||
}
|
||||
count.event_counts[0] = diff.cycles;
|
||||
count.event_counts[1] = diff.instructions;
|
||||
count.event_counts[2] = diff.missed_branches;
|
||||
count.event_counts[3] = 0;
|
||||
count.event_counts[4] = 0;
|
||||
#endif
|
||||
count.elapsed = end_clock - start_clock;
|
||||
return count;
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
|
||||
#include "find_tweet.h"
|
||||
|
||||
namespace find_tweet {
|
||||
|
||||
using namespace simdjson;
|
||||
|
||||
struct simdjson_singlestage {
|
||||
using StringType=std::string_view;
|
||||
|
||||
singlestage::parser parser{};
|
||||
|
||||
bool run(simdjson::padded_string &json, uint64_t find_id, std::string_view &result) {
|
||||
// Walk the document, parsing as we go
|
||||
auto doc = parser.iterate(json);
|
||||
for (auto tweet : doc.find_field("statuses")) {
|
||||
if (uint64_t(tweet.find_field("id")) == find_id) {
|
||||
result = tweet.find_field("text");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
BENCHMARK_TEMPLATE(find_tweet, simdjson_singlestage)->UseManualTime();
|
||||
|
||||
} // namespace find_tweet
|
||||
|
||||
#endif // SIMDJSON_EXCEPTIONS
|
||||
@@ -8,7 +8,7 @@ namespace json2msgpack {
|
||||
using namespace simdjson;
|
||||
|
||||
/**
|
||||
* @brief The simdjsonondemand2msgpack struct is used to quickly convert
|
||||
* @brief The simdjson2msgpack struct is used to quickly convert
|
||||
* JSON strings to msgpack views. You must provide a pointer to
|
||||
* a large memory region where the msgpack gets written. The
|
||||
* buffer should be large enough to store the msgpack output (which
|
||||
@@ -17,7 +17,7 @@ using namespace simdjson;
|
||||
*
|
||||
* Recommended usage:
|
||||
*
|
||||
* simdjsonondemand2msgpack parser{};
|
||||
* simdjson2msgpack parser{};
|
||||
* simdjson::padded_string json = "[1,2]"_padded; // some JSON
|
||||
* uint8_t * buffer = new uint8_t[3*json.size() + simdjson::SIMDJSON_PADDING]; // large buffer
|
||||
*
|
||||
@@ -26,10 +26,10 @@ using namespace simdjson;
|
||||
* The result (msgpack) is a string view to a msgpack serialization of the input JSON,
|
||||
* it points inside the buffer you provided.
|
||||
*
|
||||
* You may reuse the simdjsonondemand2msgpack instance though you should use
|
||||
* You may reuse the simdjson2msgpack instance though you should use
|
||||
* one per thread.
|
||||
*/
|
||||
struct simdjsonondemand2msgpack {
|
||||
struct simdjson2msgpack {
|
||||
/**
|
||||
* @brief Converts the provided JSON into msgpack.
|
||||
*
|
||||
@@ -58,7 +58,7 @@ private:
|
||||
};
|
||||
|
||||
std::string_view
|
||||
simdjsonondemand2msgpack::to_msgpack(const simdjson::padded_string &json,
|
||||
simdjson2msgpack::to_msgpack(const simdjson::padded_string &json,
|
||||
uint8_t *buf) {
|
||||
buff = buf;
|
||||
ondemand::document doc = parser.iterate(json);
|
||||
@@ -106,33 +106,33 @@ simdjsonondemand2msgpack::to_msgpack(const simdjson::padded_string &json,
|
||||
return std::string_view(reinterpret_cast<char *>(buf), size_t(buff - buf));
|
||||
}
|
||||
|
||||
void simdjsonondemand2msgpack::write_double(const double d) noexcept {
|
||||
void simdjson2msgpack::write_double(const double d) noexcept {
|
||||
*buff++ = 0xcb;
|
||||
::memcpy(buff, &d, sizeof(d));
|
||||
buff += sizeof(d);
|
||||
}
|
||||
|
||||
void simdjsonondemand2msgpack::write_byte(const uint8_t b) noexcept {
|
||||
void simdjson2msgpack::write_byte(const uint8_t b) noexcept {
|
||||
*buff = b;
|
||||
buff++;
|
||||
}
|
||||
|
||||
void simdjsonondemand2msgpack::write_uint32(const uint32_t w) noexcept {
|
||||
void simdjson2msgpack::write_uint32(const uint32_t w) noexcept {
|
||||
::memcpy(buff, &w, sizeof(w));
|
||||
buff += sizeof(w);
|
||||
}
|
||||
|
||||
uint8_t *simdjsonondemand2msgpack::skip_uint32() noexcept {
|
||||
uint8_t *simdjson2msgpack::skip_uint32() noexcept {
|
||||
uint8_t *ret = buff;
|
||||
buff += sizeof(uint32_t);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void simdjsonondemand2msgpack::write_uint32_at(const uint32_t w, uint8_t *p) noexcept {
|
||||
void simdjson2msgpack::write_uint32_at(const uint32_t w, uint8_t *p) noexcept {
|
||||
::memcpy(p, &w, sizeof(w));
|
||||
}
|
||||
|
||||
void simdjsonondemand2msgpack::write_raw_string(
|
||||
void simdjson2msgpack::write_raw_string(
|
||||
simdjson::ondemand::raw_json_string in) {
|
||||
write_byte(0xdb);
|
||||
uint8_t *location = skip_uint32();
|
||||
@@ -140,7 +140,7 @@ void simdjsonondemand2msgpack::write_raw_string(
|
||||
write_uint32_at(uint32_t(v.size()), location);
|
||||
}
|
||||
|
||||
void simdjsonondemand2msgpack::recursive_processor(simdjson::ondemand::value element) {
|
||||
void simdjson2msgpack::recursive_processor(simdjson::ondemand::value element) {
|
||||
switch (element.type()) {
|
||||
case simdjson::ondemand::json_type::array: {
|
||||
uint32_t counter = 0;
|
||||
@@ -185,7 +185,7 @@ void simdjsonondemand2msgpack::recursive_processor(simdjson::ondemand::value ele
|
||||
}
|
||||
|
||||
|
||||
void simdjsonondemand2msgpack::recursive_processor_ref(simdjson::ondemand::value& element) {
|
||||
void simdjson2msgpack::recursive_processor_ref(simdjson::ondemand::value& element) {
|
||||
switch (element.type()) {
|
||||
case simdjson::ondemand::json_type::array: {
|
||||
uint32_t counter = 0;
|
||||
@@ -234,7 +234,7 @@ void simdjsonondemand2msgpack::recursive_processor_ref(simdjson::ondemand::value
|
||||
struct simdjson_ondemand {
|
||||
using StringType = std::string_view;
|
||||
|
||||
simdjsonondemand2msgpack parser{};
|
||||
simdjson2msgpack parser{};
|
||||
|
||||
bool run(simdjson::padded_string &json, char *buffer,
|
||||
std::string_view &result) {
|
||||
|
||||
@@ -1,250 +0,0 @@
|
||||
#pragma once
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
|
||||
#include "json2msgpack.h"
|
||||
|
||||
namespace json2msgpack {
|
||||
|
||||
using namespace simdjson;
|
||||
|
||||
/**
|
||||
* @brief The simdjsonsinglestage2msgpack struct is used to quickly convert
|
||||
* JSON strings to msgpack views. You must provide a pointer to
|
||||
* a large memory region where the msgpack gets written. The
|
||||
* buffer should be large enough to store the msgpack output (which
|
||||
* can never be 3x larger than the input JSON) with an additional
|
||||
* simdjson::SIMDJSON_PADDING bytes.
|
||||
*
|
||||
* Recommended usage:
|
||||
*
|
||||
* simdjsonsinglestage2msgpack parser{};
|
||||
* simdjson::padded_string json = "[1,2]"_padded; // some JSON
|
||||
* uint8_t * buffer = new uint8_t[3*json.size() + simdjson::SIMDJSON_PADDING]; // large buffer
|
||||
*
|
||||
* std::string_view msgpack = parser.to_msgpack(json, buffer);
|
||||
*
|
||||
* The result (msgpack) is a string view to a msgpack serialization of the input JSON,
|
||||
* it points inside the buffer you provided.
|
||||
*
|
||||
* You may reuse the simdjsonsinglestage2msgpack instance though you should use
|
||||
* one per thread.
|
||||
*/
|
||||
struct simdjsonsinglestage2msgpack {
|
||||
/**
|
||||
* @brief Converts the provided JSON into msgpack.
|
||||
*
|
||||
* @param json JSON input
|
||||
* @param buf temporary buffer (must be large enough, with simdjson::SIMDJSON_PADDING bytes
|
||||
* of padding)
|
||||
* @return std::string_view msgpack output, writing to the temporary buffer
|
||||
*/
|
||||
inline std::string_view to_msgpack(const simdjson::padded_string &json,
|
||||
uint8_t *buf);
|
||||
|
||||
private:
|
||||
simdjson_inline void write_double(const double d) noexcept;
|
||||
simdjson_inline void write_byte(const uint8_t b) noexcept;
|
||||
simdjson_inline void write_uint32(const uint32_t w) noexcept;
|
||||
simdjson_inline uint8_t *skip_uint32() noexcept;
|
||||
simdjson_inline void write_uint32_at(const uint32_t w,
|
||||
uint8_t *p) noexcept;
|
||||
simdjson_inline void
|
||||
write_raw_string(simdjson::singlestage::raw_json_string rjs);
|
||||
inline void recursive_processor(simdjson::singlestage::value element);
|
||||
inline void recursive_processor_ref(simdjson::singlestage::value& element);
|
||||
|
||||
simdjson::singlestage::parser parser;
|
||||
uint8_t *buff{};
|
||||
};
|
||||
|
||||
std::string_view
|
||||
simdjsonsinglestage2msgpack::to_msgpack(const simdjson::padded_string &json,
|
||||
uint8_t *buf) {
|
||||
buff = buf;
|
||||
singlestage::document doc = parser.iterate(json);
|
||||
if (doc.is_scalar()) {
|
||||
// we have a special case where the JSON document is a single document...
|
||||
switch (doc.type()) {
|
||||
case simdjson::singlestage::json_type::number:
|
||||
write_double(doc.get_double());
|
||||
break;
|
||||
case simdjson::singlestage::json_type::string:
|
||||
write_raw_string(doc.get_raw_json_string());
|
||||
break;
|
||||
case simdjson::singlestage::json_type::boolean:
|
||||
write_byte(0xc2 + doc.get_bool());
|
||||
break;
|
||||
case simdjson::singlestage::json_type::null:
|
||||
// We check that the value is indeed null
|
||||
// otherwise: an error is thrown.
|
||||
if(doc.is_null()) {
|
||||
write_byte(0xc0);
|
||||
}
|
||||
break;
|
||||
case simdjson::singlestage::json_type::array:
|
||||
case simdjson::singlestage::json_type::object:
|
||||
default:
|
||||
// impossible
|
||||
SIMDJSON_UNREACHABLE();
|
||||
}
|
||||
} else {
|
||||
simdjson::singlestage::value val = doc;
|
||||
#define SIMDJSON_GCC_COMPILER ((__GNUC__) && !(__clang__) && !(__INTEL_COMPILER))
|
||||
#if SIMDJSON_GCC_COMPILER
|
||||
// the GCC compiler does well with by-value passing.
|
||||
// GCC has superior recursive inlining:
|
||||
// https://stackoverflow.com/questions/29186186/why-does-gcc-generate-a-faster-program-than-clang-in-this-recursive-fibonacci-co
|
||||
// https://godbolt.org/z/TeK4doE51
|
||||
recursive_processor(val);
|
||||
#else
|
||||
recursive_processor_ref(val);
|
||||
#endif
|
||||
}
|
||||
if (!doc.at_end()) {
|
||||
throw "There are unexpectedly tokens after the end of the json in the json2msgpack sample data";
|
||||
}
|
||||
return std::string_view(reinterpret_cast<char *>(buf), size_t(buff - buf));
|
||||
}
|
||||
|
||||
void simdjsonsinglestage2msgpack::write_double(const double d) noexcept {
|
||||
*buff++ = 0xcb;
|
||||
::memcpy(buff, &d, sizeof(d));
|
||||
buff += sizeof(d);
|
||||
}
|
||||
|
||||
void simdjsonsinglestage2msgpack::write_byte(const uint8_t b) noexcept {
|
||||
*buff = b;
|
||||
buff++;
|
||||
}
|
||||
|
||||
void simdjsonsinglestage2msgpack::write_uint32(const uint32_t w) noexcept {
|
||||
::memcpy(buff, &w, sizeof(w));
|
||||
buff += sizeof(w);
|
||||
}
|
||||
|
||||
uint8_t *simdjsonsinglestage2msgpack::skip_uint32() noexcept {
|
||||
uint8_t *ret = buff;
|
||||
buff += sizeof(uint32_t);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void simdjsonsinglestage2msgpack::write_uint32_at(const uint32_t w, uint8_t *p) noexcept {
|
||||
::memcpy(p, &w, sizeof(w));
|
||||
}
|
||||
|
||||
void simdjsonsinglestage2msgpack::write_raw_string(
|
||||
simdjson::singlestage::raw_json_string in) {
|
||||
write_byte(0xdb);
|
||||
uint8_t *location = skip_uint32();
|
||||
std::string_view v = parser.unescape(in, buff);
|
||||
write_uint32_at(uint32_t(v.size()), location);
|
||||
}
|
||||
|
||||
void simdjsonsinglestage2msgpack::recursive_processor(simdjson::singlestage::value element) {
|
||||
switch (element.type()) {
|
||||
case simdjson::singlestage::json_type::array: {
|
||||
uint32_t counter = 0;
|
||||
write_byte(0xdd);
|
||||
uint8_t *location = skip_uint32();
|
||||
for (auto child : element.get_array()) {
|
||||
counter++;
|
||||
recursive_processor(child.value());
|
||||
}
|
||||
write_uint32_at(counter, location);
|
||||
} break;
|
||||
case simdjson::singlestage::json_type::object: {
|
||||
uint32_t counter = 0;
|
||||
write_byte(0xdf);
|
||||
uint8_t *location = skip_uint32();
|
||||
for (auto field : element.get_object()) {
|
||||
counter++;
|
||||
write_raw_string(field.key());
|
||||
recursive_processor(field.value());
|
||||
}
|
||||
write_uint32_at(counter, location);
|
||||
} break;
|
||||
case simdjson::singlestage::json_type::number:
|
||||
write_double(element.get_double());
|
||||
break;
|
||||
case simdjson::singlestage::json_type::string:
|
||||
write_raw_string(element.get_raw_json_string());
|
||||
break;
|
||||
case simdjson::singlestage::json_type::boolean:
|
||||
write_byte(0xc2 + element.get_bool());
|
||||
break;
|
||||
case simdjson::singlestage::json_type::null:
|
||||
// We check that the value is indeed null
|
||||
// otherwise: an error is thrown.
|
||||
if(element.is_null()) {
|
||||
write_byte(0xc0);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
SIMDJSON_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void simdjsonsinglestage2msgpack::recursive_processor_ref(simdjson::singlestage::value& element) {
|
||||
switch (element.type()) {
|
||||
case simdjson::singlestage::json_type::array: {
|
||||
uint32_t counter = 0;
|
||||
write_byte(0xdd);
|
||||
uint8_t *location = skip_uint32();
|
||||
for (auto child : element.get_array()) {
|
||||
counter++;
|
||||
simdjson::singlestage::value v = child.value();
|
||||
recursive_processor_ref(v);
|
||||
}
|
||||
write_uint32_at(counter, location);
|
||||
} break;
|
||||
case simdjson::singlestage::json_type::object: {
|
||||
uint32_t counter = 0;
|
||||
write_byte(0xdf);
|
||||
uint8_t *location = skip_uint32();
|
||||
for (auto field : element.get_object()) {
|
||||
counter++;
|
||||
write_raw_string(field.key());
|
||||
simdjson::singlestage::value v = field.value();
|
||||
recursive_processor_ref(v);
|
||||
}
|
||||
write_uint32_at(counter, location);
|
||||
} break;
|
||||
case simdjson::singlestage::json_type::number:
|
||||
write_double(element.get_double());
|
||||
break;
|
||||
case simdjson::singlestage::json_type::string:
|
||||
write_raw_string(element.get_raw_json_string());
|
||||
break;
|
||||
case simdjson::singlestage::json_type::boolean:
|
||||
write_byte(0xc2 + element.get_bool());
|
||||
break;
|
||||
case simdjson::singlestage::json_type::null:
|
||||
// We check that the value is indeed null
|
||||
// otherwise: an error is thrown.
|
||||
if(element.is_null()) {
|
||||
write_byte(0xc0);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
SIMDJSON_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
struct simdjson_singlestage {
|
||||
using StringType = std::string_view;
|
||||
|
||||
simdjsonsinglestage2msgpack parser{};
|
||||
|
||||
bool run(simdjson::padded_string &json, char *buffer,
|
||||
std::string_view &result) {
|
||||
result = parser.to_msgpack(json, reinterpret_cast<uint8_t *>(buffer));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
BENCHMARK_TEMPLATE(json2msgpack, simdjson_singlestage)->UseManualTime();
|
||||
|
||||
} // namespace json2msgpack
|
||||
|
||||
#endif // SIMDJSON_EXCEPTIONS
|
||||
@@ -13,15 +13,13 @@ void maybe_display_implementation() {
|
||||
std::cout << "simdjson::dom implementation: " << simdjson::get_active_implementation()->name() << std::endl;
|
||||
std::cout << "simdjson::ondemand implementation (stage 1): " << simdjson::get_active_implementation()->name() << std::endl;
|
||||
std::cout << "simdjson::ondemand implementation (stage 2): " << simdjson::builtin_implementation()->name() << std::endl;
|
||||
std::cout << "simdjson::singlestage implementation (stage 1): " << simdjson::get_active_implementation()->name() << std::endl;
|
||||
std::cout << "simdjson::singlestage implementation (stage 2): " << simdjson::builtin_implementation()->name() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename B, typename R> static void run_json_benchmark(benchmark::State &state) {
|
||||
maybe_display_implementation();
|
||||
|
||||
event_collector collector(true);
|
||||
event_collector collector;
|
||||
event_aggregate events;
|
||||
|
||||
// Warmup and equality check (make sure the data is right!)
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
|
||||
#include "kostya.h"
|
||||
|
||||
namespace kostya {
|
||||
|
||||
using namespace simdjson;
|
||||
|
||||
struct simdjson_singlestage {
|
||||
static constexpr diff_flags DiffFlags = diff_flags::NONE;
|
||||
|
||||
singlestage::parser parser{};
|
||||
|
||||
bool run(simdjson::padded_string &json, std::vector<point> &result) {
|
||||
auto doc = parser.iterate(json);
|
||||
for (singlestage::object point : doc.find_field("coordinates")) {
|
||||
result.emplace_back(json_benchmark::point{point.find_field("x"), point.find_field("y"), point.find_field("z")});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
BENCHMARK_TEMPLATE(kostya, simdjson_singlestage)->UseManualTime();
|
||||
|
||||
} // namespace kostya
|
||||
|
||||
#endif // SIMDJSON_EXCEPTIONS
|
||||
@@ -1,72 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
|
||||
#include "large_amazon_cellphones.h"
|
||||
|
||||
namespace large_amazon_cellphones {
|
||||
|
||||
using namespace simdjson;
|
||||
|
||||
template<bool threaded>
|
||||
struct simdjson_singlestage {
|
||||
using StringType = std::string;
|
||||
|
||||
singlestage::parser parser{};
|
||||
|
||||
bool run(simdjson::padded_string &json, std::map<StringType, brand> &result) {
|
||||
#ifdef SIMDJSON_THREADS_ENABLED
|
||||
parser.threaded = threaded;
|
||||
#endif
|
||||
singlestage::document_stream stream = parser.iterate_many(json);
|
||||
singlestage::document_stream::iterator i = stream.begin();
|
||||
++i; // Skip first line
|
||||
for (;i != stream.end(); ++i) {
|
||||
auto doc = *i;
|
||||
size_t index{0};
|
||||
StringType copy;
|
||||
double rating;
|
||||
uint64_t reviews;
|
||||
for ( auto value : doc ) {
|
||||
switch (index)
|
||||
{
|
||||
case 1:
|
||||
copy = StringType(std::string_view(value));
|
||||
break;
|
||||
case 5:
|
||||
rating = double(value);
|
||||
break;
|
||||
case 7:
|
||||
reviews = uint64_t(value);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
auto x = result.find(copy);
|
||||
if (x == result.end()) { // If key not found, add new key
|
||||
result.emplace(copy, large_amazon_cellphones::brand{
|
||||
rating * reviews,
|
||||
reviews
|
||||
});
|
||||
} else { // Otherwise, update key data
|
||||
x->second.cumulative_rating += rating * reviews;
|
||||
x->second.reviews_count += reviews;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
BENCHMARK_TEMPLATE(large_amazon_cellphones, simdjson_singlestage<UNTHREADED>)->UseManualTime();
|
||||
#ifdef SIMDJSON_THREADS_ENABLED
|
||||
BENCHMARK_TEMPLATE(large_amazon_cellphones, simdjson_singlestage<THREADED>)->UseManualTime();
|
||||
#endif
|
||||
|
||||
} // namespace amazon_cellphones
|
||||
|
||||
#endif // SIMDJSON_EXCEPTIONS
|
||||
@@ -1,29 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
|
||||
#include "large_random.h"
|
||||
|
||||
namespace large_random {
|
||||
|
||||
using namespace simdjson;
|
||||
|
||||
struct simdjson_singlestage {
|
||||
static constexpr diff_flags DiffFlags = diff_flags::NONE;
|
||||
|
||||
singlestage::parser parser{};
|
||||
|
||||
bool run(simdjson::padded_string &json, std::vector<point> &result) {
|
||||
auto doc = parser.iterate(json);
|
||||
for (singlestage::object coord : doc) {
|
||||
result.emplace_back(json_benchmark::point{coord.find_field("x"), coord.find_field("y"), coord.find_field("z")});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
BENCHMARK_TEMPLATE(large_random, simdjson_singlestage)->UseManualTime();
|
||||
|
||||
} // namespace large_random
|
||||
|
||||
#endif // SIMDJSON_EXCEPTIONS
|
||||
@@ -1,29 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
|
||||
#include "large_random.h"
|
||||
|
||||
namespace large_random {
|
||||
|
||||
using namespace simdjson;
|
||||
|
||||
struct simdjson_singlestage_unordered {
|
||||
static constexpr diff_flags DiffFlags = diff_flags::NONE;
|
||||
|
||||
singlestage::parser parser{};
|
||||
|
||||
bool run(simdjson::padded_string &json, std::vector<point> &result) {
|
||||
auto doc = parser.iterate(json);
|
||||
for (singlestage::object coord : doc) {
|
||||
result.emplace_back(json_benchmark::point{coord["x"], coord["y"], coord["z"]});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
BENCHMARK_TEMPLATE(large_random, simdjson_singlestage_unordered)->UseManualTime();
|
||||
|
||||
} // namespace large_random
|
||||
|
||||
#endif // SIMDJSON_EXCEPTIONS
|
||||
@@ -1,37 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
|
||||
#include "largerandom.h"
|
||||
|
||||
namespace largerandom {
|
||||
|
||||
using namespace simdjson;
|
||||
|
||||
class OnDemand {
|
||||
public:
|
||||
simdjson_inline bool Run(const padded_string &json);
|
||||
simdjson_inline const std::vector<my_point> &Result() { return container; }
|
||||
simdjson_inline size_t ItemCount() { return container.size(); }
|
||||
|
||||
private:
|
||||
singlestage::parser parser{};
|
||||
std::vector<my_point> container{};
|
||||
};
|
||||
|
||||
simdjson_inline bool OnDemand::Run(const padded_string &json) {
|
||||
container.clear();
|
||||
|
||||
auto doc = parser.iterate(json);
|
||||
for (singlestage::object coord : doc) {
|
||||
container.emplace_back(my_point{coord.find_field("x"), coord.find_field("y"), coord.find_field("z")});
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
BENCHMARK_TEMPLATE(LargeRandom, OnDemand);
|
||||
|
||||
} // namespace largerandom
|
||||
|
||||
#endif // SIMDJSON_EXCEPTIONS
|
||||
@@ -1,48 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
|
||||
#include "partial_tweets.h"
|
||||
|
||||
namespace partial_tweets {
|
||||
|
||||
using namespace simdjson;
|
||||
|
||||
struct simdjson_singlestage {
|
||||
using StringType=std::string_view;
|
||||
|
||||
singlestage::parser parser{};
|
||||
|
||||
simdjson_inline uint64_t nullable_int(singlestage::value value) {
|
||||
if (value.is_null()) { return 0; }
|
||||
return value;
|
||||
}
|
||||
|
||||
simdjson_inline twitter_user<std::string_view> read_user(singlestage::object user) {
|
||||
return { user.find_field("id"), user.find_field("screen_name") };
|
||||
}
|
||||
|
||||
bool run(simdjson::padded_string &json, std::vector<tweet<std::string_view>> &result) {
|
||||
// Walk the document, parsing the tweets as we go
|
||||
auto doc = parser.iterate(json);
|
||||
for (singlestage::object tweet : doc.find_field("statuses")) {
|
||||
result.emplace_back(partial_tweets::tweet<std::string_view>{
|
||||
tweet.find_field("created_at"),
|
||||
tweet.find_field("id"),
|
||||
tweet.find_field("text"),
|
||||
nullable_int(tweet.find_field("in_reply_to_status_id")),
|
||||
read_user(tweet.find_field("user")),
|
||||
tweet.find_field("retweet_count"),
|
||||
tweet.find_field("favorite_count")
|
||||
});
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
BENCHMARK_TEMPLATE(partial_tweets, simdjson_singlestage)->UseManualTime();
|
||||
|
||||
} // namespace partial_tweets
|
||||
|
||||
#endif // SIMDJSON_EXCEPTIONS
|
||||
@@ -1,63 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
|
||||
#include "partial_tweets.h"
|
||||
|
||||
namespace partial_tweets {
|
||||
|
||||
using namespace simdjson;
|
||||
|
||||
|
||||
class SingleStage {
|
||||
public:
|
||||
SingleStage() {
|
||||
if(!displayed_implementation) {
|
||||
std::cout << "On Demand implementation: " << builtin_implementation()->name() << std::endl;
|
||||
displayed_implementation = true;
|
||||
}
|
||||
}
|
||||
simdjson_inline bool Run(const padded_string &json);
|
||||
simdjson_inline const std::vector<tweet> &Result() { return tweets; }
|
||||
simdjson_inline size_t ItemCount() { return tweets.size(); }
|
||||
|
||||
private:
|
||||
singlestage::parser parser{};
|
||||
std::vector<tweet> tweets{};
|
||||
|
||||
simdjson_inline uint64_t nullable_int(singlestage::value value) {
|
||||
if (value.is_null()) { return 0; }
|
||||
return value;
|
||||
}
|
||||
|
||||
simdjson_inline twitter_user read_user(singlestage::object user) {
|
||||
return { user.find_field("id"), user.find_field("screen_name") };
|
||||
}
|
||||
|
||||
static inline bool displayed_implementation = false;
|
||||
};
|
||||
|
||||
simdjson_inline bool SingleStage::Run(const padded_string &json) {
|
||||
tweets.clear();
|
||||
|
||||
// Walk the document, parsing the tweets as we go
|
||||
auto doc = parser.iterate(json);
|
||||
for (singlestage::object tweet : doc.find_field("statuses")) {
|
||||
tweets.emplace_back(partial_tweets::tweet{
|
||||
tweet.find_field("created_at"),
|
||||
tweet.find_field("id"),
|
||||
tweet.find_field("text"),
|
||||
nullable_int(tweet.find_field("in_reply_to_status_id")),
|
||||
read_user(tweet.find_field("user")),
|
||||
tweet.find_field("retweet_count"),
|
||||
tweet.find_field("favorite_count")
|
||||
});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
BENCHMARK_TEMPLATE(PartialTweets, SingleStage);
|
||||
|
||||
} // namespace partial_tweets
|
||||
|
||||
#endif // SIMDJSON_EXCEPTIONS
|
||||
@@ -1,80 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
|
||||
#include "top_tweet.h"
|
||||
|
||||
namespace top_tweet {
|
||||
|
||||
using namespace simdjson;
|
||||
|
||||
struct simdjson_singlestage {
|
||||
using StringType=std::string_view;
|
||||
|
||||
singlestage::parser parser{};
|
||||
|
||||
bool run(simdjson::padded_string &json, int64_t max_retweet_count, top_tweet_result<StringType> &result) {
|
||||
result.retweet_count = -1;
|
||||
// We save these DOM values for later so we don't have to parse them
|
||||
// into string_views until we're sure which ones we want to parse
|
||||
// NOTE: simdjson does not presently support reuse of objects or arrays--just scalars. This is
|
||||
// why we have to grab the text and screen_name fields instead of just saving the tweet object.
|
||||
singlestage::value screen_name, text;
|
||||
|
||||
auto doc = parser.iterate(json);
|
||||
for (auto tweet : doc["statuses"]) {
|
||||
// Since text, user.screen_name, and retweet_count generally appear in order, it's nearly free
|
||||
// for us to retrieve them here (and will cost a bit more if we do it in the if
|
||||
// statement).
|
||||
auto tweet_text = tweet["text"];
|
||||
auto tweet_screen_name = tweet["user"]["screen_name"];
|
||||
int64_t retweet_count = tweet["retweet_count"];
|
||||
if (retweet_count <= max_retweet_count && retweet_count >= result.retweet_count) {
|
||||
result.retweet_count = retweet_count;
|
||||
// TODO std::move should not be necessary
|
||||
text = std::move(tweet_text);
|
||||
screen_name = std::move(tweet_screen_name);
|
||||
}
|
||||
}
|
||||
|
||||
// Now that we know which was the most retweeted, parse the values in it
|
||||
result.screen_name = screen_name;
|
||||
result.text = text;
|
||||
return result.retweet_count != -1;
|
||||
}
|
||||
};
|
||||
|
||||
BENCHMARK_TEMPLATE(top_tweet, simdjson_singlestage)->UseManualTime();
|
||||
|
||||
struct simdjson_singlestage_forward_only {
|
||||
using StringType=std::string_view;
|
||||
|
||||
singlestage::parser parser{};
|
||||
|
||||
bool run(simdjson::padded_string &json, int64_t max_retweet_count, top_tweet_result<StringType> &result) {
|
||||
result.retweet_count = -1;
|
||||
|
||||
auto doc = parser.iterate(json);
|
||||
for (auto tweet : doc["statuses"]) {
|
||||
// Since text, user.screen_name, and retweet_count generally appear in order, it's nearly free
|
||||
// for us to retrieve them here (and will cost a bit more if we do it in the if
|
||||
// statement).
|
||||
auto tweet_text = tweet["text"];
|
||||
auto tweet_screen_name = tweet["user"]["screen_name"];
|
||||
int64_t retweet_count = tweet["retweet_count"];
|
||||
if (retweet_count <= max_retweet_count && retweet_count >= result.retweet_count) {
|
||||
result.retweet_count = retweet_count;
|
||||
result.text = tweet_text;
|
||||
result.screen_name = tweet_screen_name;
|
||||
}
|
||||
}
|
||||
|
||||
return result.retweet_count != -1;
|
||||
}
|
||||
};
|
||||
|
||||
BENCHMARK_TEMPLATE(top_tweet, simdjson_singlestage_forward_only)->UseManualTime();
|
||||
|
||||
} // namespace top_tweet
|
||||
|
||||
#endif // SIMDJSON_EXCEPTIONS
|
||||
@@ -117,7 +117,12 @@ set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
set(CMAKE_MACOSX_RPATH OFF)
|
||||
set(CMAKE_THREAD_PREFER_PTHREAD ON)
|
||||
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||
set(SIMDJSON_STRUCTURAL_INDEXER_STEP CACHE STRING "the SIMDJSON_STRUCTURAL_INDEXER_STEP variable")
|
||||
|
||||
if(SIMDJSON_STRUCTURAL_INDEXER_STEP)
|
||||
message(STATUS "Setting SIMDJSON_STRUCTURAL_INDEXER_STEP to ${SIMDJSON_STRUCTURAL_INDEXER_STEP}.")
|
||||
add_compile_definitions(SIMDJSON_STRUCTURAL_INDEXER_STEP=${SIMDJSON_STRUCTURAL_INDEXER_STEP})
|
||||
endif()
|
||||
# LTO seems to create all sorts of fun problems. Let us
|
||||
# disable temporarily.
|
||||
#include(CheckIPOSupported)
|
||||
|
||||
@@ -17,6 +17,9 @@ Contents
|
||||
|
||||
- [Motivations](#motivations)
|
||||
- [How it works](#how-it-works)
|
||||
- [Context](#context)
|
||||
- [Design](#design)
|
||||
- [Threads](#threads)
|
||||
- [Support](#support)
|
||||
- [API](#api)
|
||||
- [Use cases](#use-cases)
|
||||
|
||||
@@ -35,14 +35,4 @@ IF(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
||||
add_quickstart_test(quickstart_ondemand_noexceptions quickstart_ondemand_noexceptions.cpp NO_EXCEPTIONS LABELS quickstart_ondemand acceptance)
|
||||
add_quickstart_test(quickstart_ondemand_noexceptions11 quickstart_ondemand_noexceptions.cpp NO_EXCEPTIONS CXX_STANDARD c++11 LABELS quickstart_ondemand)
|
||||
|
||||
# SingleStage Quick Start
|
||||
if (SIMDJSON_EXCEPTIONS)
|
||||
add_quickstart_test(quickstart_singlestage quickstart_singlestage.cpp LABELS quickstart_singlestage acceptance)
|
||||
add_quickstart_test(quickstart_singlestage11 quickstart_singlestage.cpp CXX_STANDARD c++11 LABELS quickstart_singlestage acceptance)
|
||||
add_quickstart_test(quickstart_singlestage14 quickstart_singlestage.cpp CXX_STANDARD c++14 LABELS quickstart_singlestage)
|
||||
endif()
|
||||
|
||||
add_quickstart_test(quickstart_singlestage_noexceptions quickstart_singlestage_noexceptions.cpp NO_EXCEPTIONS LABELS quickstart_singlestage acceptance)
|
||||
add_quickstart_test(quickstart_singlestage_noexceptions11 quickstart_singlestage_noexceptions.cpp NO_EXCEPTIONS CXX_STANDARD c++11 LABELS quickstart_singlestage)
|
||||
|
||||
endif()
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
#include <iostream>
|
||||
#include "simdjson.h"
|
||||
using namespace simdjson;
|
||||
int main(void) {
|
||||
ondemand::parser parser;
|
||||
padded_string json = padded_string::load("twitter.json");
|
||||
ondemand::document tweets = parser.iterate(json);
|
||||
std::cout << uint64_t(tweets["search_metadata"]["count"]) << " results." << std::endl;
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
#include <iostream>
|
||||
#include "simdjson.h"
|
||||
using namespace simdjson;
|
||||
int main(void) {
|
||||
padded_string json;
|
||||
auto error = padded_string::load("twitter.json").get(json);
|
||||
if (error) { std::cerr << error << std::endl; return EXIT_FAILURE; }
|
||||
|
||||
ondemand::parser parser;
|
||||
ondemand::document tweets;
|
||||
error = parser.iterate(json).get(tweets);
|
||||
if (error) { std::cerr << error << std::endl; return EXIT_FAILURE; }
|
||||
|
||||
uint64_t count;
|
||||
error = tweets["search_metadata"]["count"].get(count);
|
||||
if (error) { std::cerr << error << std::endl; return EXIT_FAILURE; }
|
||||
|
||||
std::cout << count << " results." << std::endl;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@@ -63,7 +63,6 @@ if(SIMDJSON_ENABLE_FUZZING)
|
||||
implement_fuzzer(fuzz_minifyimpl) # minify *without* parsing, plus compare implementations
|
||||
implement_fuzzer(fuzz_ndjson) # the ndjson api
|
||||
implement_fuzzer(fuzz_ondemand)
|
||||
# implement_fuzzer(fuzz_singlestage) # TODO why no worky
|
||||
implement_fuzzer(fuzz_padded)
|
||||
implement_fuzzer(fuzz_parser)
|
||||
implement_fuzzer(fuzz_print_json)
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
#include "FuzzUtils.h"
|
||||
#include "simdjson.h"
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
|
||||
FuzzData fd(Data, Size);
|
||||
const int action = fd.getInt<0, 12>();
|
||||
|
||||
// split the remainder of the document into strings
|
||||
auto strings = fd.splitIntoStrings();
|
||||
while (strings.size() < 1) {
|
||||
strings.emplace_back();
|
||||
}
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
try {
|
||||
#endif
|
||||
simdjson::singlestage::parser parser;
|
||||
simdjson::padded_string padded(strings[0]);
|
||||
auto doc = parser.iterate(padded);
|
||||
if (doc.error()) {
|
||||
return 0;
|
||||
}
|
||||
for (auto item : doc) {
|
||||
switch (action) {
|
||||
case 0: {
|
||||
simdjson_unused auto x = item.get_string();
|
||||
} break;
|
||||
case 1: {
|
||||
simdjson_unused auto x = item.get_bool();
|
||||
} break;
|
||||
case 2: {
|
||||
simdjson_unused auto x = item.get_array();
|
||||
} break;
|
||||
case 3: {
|
||||
simdjson_unused auto x = item.get_int64();
|
||||
} break;
|
||||
case 4: {
|
||||
simdjson_unused auto x = item.get_double();
|
||||
} break;
|
||||
case 5: {
|
||||
simdjson_unused auto x = item.get_object();
|
||||
} break;
|
||||
case 6: {
|
||||
simdjson_unused auto x = item.get_uint64();
|
||||
} break;
|
||||
case 7: {
|
||||
simdjson_unused auto x = item.get_raw_json_string();
|
||||
} break;
|
||||
case 8: {
|
||||
simdjson_unused auto x = item.is_null();
|
||||
} break;
|
||||
case 9: {
|
||||
simdjson_unused auto x = item.begin();
|
||||
} break;
|
||||
case 10: {
|
||||
simdjson_unused auto x = item.end();
|
||||
} break;
|
||||
case 11: {
|
||||
for (auto e : item) {
|
||||
simdjson_unused auto x = e.is_null();
|
||||
}
|
||||
} break;
|
||||
default:;
|
||||
}
|
||||
}
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
} catch (...) {
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -53,6 +53,5 @@
|
||||
|
||||
#include "simdjson/dom.h"
|
||||
#include "simdjson/ondemand.h"
|
||||
#include "simdjson/singlestage.h"
|
||||
|
||||
#endif // SIMDJSON_H
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include "simdjson/arm64/begin.h"
|
||||
#include "simdjson/generic/amalgamated.h"
|
||||
#include "simdjson/generic/lookup_table.h"
|
||||
#include "simdjson/arm64/end.h"
|
||||
|
||||
#endif // SIMDJSON_ARM64_H
|
||||
@@ -1,9 +1,9 @@
|
||||
#ifndef SIMDJSON_ARM64_BASE_H
|
||||
#define SIMDJSON_ARM64_BASE_H
|
||||
|
||||
#ifndef SIMDJSON_AMALGAMATED
|
||||
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
#include "simdjson/base.h"
|
||||
#endif // SIMDJSON_AMALGAMATED
|
||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
namespace simdjson {
|
||||
/**
|
||||
@@ -13,21 +13,16 @@ namespace arm64 {
|
||||
|
||||
class implementation;
|
||||
|
||||
namespace {
|
||||
namespace simd {
|
||||
|
||||
template <typename T> struct simd8;
|
||||
template <> struct simd8<bool>;
|
||||
template <> struct simd8<uint8_t>;
|
||||
template <typename T> struct simd8x64;
|
||||
|
||||
} // namespace simd
|
||||
} // unnamed namespace
|
||||
|
||||
} // namespace arm64
|
||||
} // namespace simdjson
|
||||
|
||||
#ifndef SIMDJSON_AMALGAMATED
|
||||
// If we're editing one of the files in this directory, begin the implementation!
|
||||
#ifndef SIMDJSON_IMPLEMENTATION
|
||||
#include "simdjson/arm64/begin.h"
|
||||
#endif
|
||||
#endif // SIMDJSON_AMALGAMATED
|
||||
|
||||
#endif // SIMDJSON_ARM64_BASE_H
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
#define SIMDJSON_IMPLEMENTATION arm64
|
||||
#include "simdjson/arm64/base.h"
|
||||
#include "simdjson/arm64/intrinsics.h"
|
||||
#include "simdjson/arm64/bitmanipulation.h"
|
||||
#include "simdjson/arm64/bitmask.h"
|
||||
#include "simdjson/arm64/bitmask.h"
|
||||
#include "simdjson/arm64/numberparsing_defs.h"
|
||||
#include "simdjson/arm64/simd.h"
|
||||
#include "simdjson/arm64/stringparsing_defs.h"
|
||||
|
||||
#define SIMDJSON_SKIP_BACKSLASH_SHORT_CIRCUIT 1
|
||||
@@ -1,104 +0,0 @@
|
||||
#ifndef SIMDJSON_ARM64_BITMANIPULATION_H
|
||||
#define SIMDJSON_ARM64_BITMANIPULATION_H
|
||||
|
||||
#include "simdjson/arm64/base.h"
|
||||
#include "simdjson/arm64/intrinsics.h"
|
||||
|
||||
namespace simdjson {
|
||||
namespace SIMDJSON_IMPLEMENTATION {
|
||||
namespace {
|
||||
|
||||
// We sometimes call trailing_zero on inputs that are zero,
|
||||
// but the algorithms do not end up using the returned value.
|
||||
// Sadly, sanitizers are not smart enough to figure it out.
|
||||
SIMDJSON_NO_SANITIZE_UNDEFINED
|
||||
// This function can be used safely even if not all bytes have been
|
||||
// initialized.
|
||||
// See issue https://github.com/simdjson/simdjson/issues/1965
|
||||
SIMDJSON_NO_SANITIZE_MEMORY
|
||||
simdjson_inline int trailing_zeroes(uint64_t input_num) {
|
||||
#ifdef 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).
|
||||
_BitScanForward64(&ret, input_num);
|
||||
return (int)ret;
|
||||
#else // SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||
return __builtin_ctzll(input_num);
|
||||
#endif // SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||
}
|
||||
|
||||
/* result might be undefined when input_num is zero */
|
||||
simdjson_inline uint64_t clear_lowest_bit(uint64_t input_num) {
|
||||
return input_num & (input_num-1);
|
||||
}
|
||||
|
||||
/* result might be undefined when input_num is zero */
|
||||
simdjson_inline int leading_zeroes(uint64_t input_num) {
|
||||
#ifdef 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).
|
||||
if (_BitScanReverse64(&leading_zero, input_num))
|
||||
return (int)(63 - leading_zero);
|
||||
else
|
||||
return 64;
|
||||
#else
|
||||
return __builtin_clzll(input_num);
|
||||
#endif// SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||
}
|
||||
|
||||
/* result might be undefined when input_num is zero */
|
||||
simdjson_inline int count_ones(uint64_t input_num) {
|
||||
return vaddv_u8(vcnt_u8(vcreate_u8(input_num)));
|
||||
}
|
||||
|
||||
|
||||
#if defined(__GNUC__) // catches clang and gcc
|
||||
/**
|
||||
* ARM has a fast 64-bit "bit reversal function" that is handy. However,
|
||||
* it is not generally available as an intrinsic function under Visual
|
||||
* Studio (though this might be changing). Even under clang/gcc, we
|
||||
* apparently need to invoke inline assembly.
|
||||
*/
|
||||
/*
|
||||
* We use SIMDJSON_PREFER_REVERSE_BITS as a hint that algorithms that
|
||||
* work well with bit reversal may use it.
|
||||
*/
|
||||
#define SIMDJSON_PREFER_REVERSE_BITS 1
|
||||
|
||||
/* reverse the bits */
|
||||
simdjson_inline uint64_t reverse_bits(uint64_t input_num) {
|
||||
uint64_t rev_bits;
|
||||
__asm("rbit %0, %1" : "=r"(rev_bits) : "r"(input_num));
|
||||
return rev_bits;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flips bit at index 63 - lz. Thus if you have 'leading_zeroes' leading zeroes,
|
||||
* then this will set to zero the leading bit. It is possible for leading_zeroes to be
|
||||
* greating or equal to 63 in which case we trigger undefined behavior, but the output
|
||||
* of such undefined behavior is never used.
|
||||
**/
|
||||
SIMDJSON_NO_SANITIZE_UNDEFINED
|
||||
simdjson_inline uint64_t zero_leading_bit(uint64_t rev_bits, int leading_zeroes) {
|
||||
return rev_bits ^ (uint64_t(0x8000000000000000) >> leading_zeroes);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
simdjson_inline bool add_overflow(uint64_t value1, uint64_t value2, uint64_t *result) {
|
||||
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||
*result = value1 + value2;
|
||||
return *result < value1;
|
||||
#else
|
||||
return __builtin_uaddll_overflow(value1, value2,
|
||||
reinterpret_cast<unsigned long long *>(result));
|
||||
#endif
|
||||
}
|
||||
|
||||
} // unnamed namespace
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
} // namespace simdjson
|
||||
|
||||
#endif // SIMDJSON_ARM64_BITMANIPULATION_H
|
||||
@@ -1,11 +1,131 @@
|
||||
#ifndef SIMDJSON_ARM64_BITMASK_H
|
||||
#define SIMDJSON_ARM64_BITMASK_H
|
||||
|
||||
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
#include "simdjson/arm64/base.h"
|
||||
#include "simdjson/arm64/intrinsics.h"
|
||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
namespace simdjson {
|
||||
namespace SIMDJSON_IMPLEMENTATION {
|
||||
namespace {
|
||||
namespace arm64 {
|
||||
namespace bitmask {
|
||||
|
||||
// We sometimes call trailing_zero on inputs that are zero,
|
||||
// but the algorithms do not end up using the returned value.
|
||||
// Sadly, sanitizers are not smart enough to figure it out.
|
||||
SIMDJSON_NO_SANITIZE_UNDEFINED
|
||||
// This function can be used safely even if not all bytes have been
|
||||
// initialized.
|
||||
// See issue https://github.com/simdjson/simdjson/issues/1965
|
||||
SIMDJSON_NO_SANITIZE_MEMORY
|
||||
simdjson_inline int trailing_zeroes(uint64_t input_num) {
|
||||
#ifdef 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).
|
||||
_BitScanForward64(&ret, input_num);
|
||||
return (int)ret;
|
||||
#else // SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||
return __builtin_ctzll(input_num);
|
||||
#endif // SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||
}
|
||||
|
||||
/* result might be undefined when input_num is zero */
|
||||
simdjson_inline uint64_t clear_lowest_bit(uint64_t input_num) {
|
||||
return input_num & (input_num-1);
|
||||
}
|
||||
|
||||
/* result might be undefined when input_num is zero */
|
||||
simdjson_inline int leading_zeroes(uint64_t input_num) {
|
||||
#ifdef 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).
|
||||
if (_BitScanReverse64(&leading_zero, input_num))
|
||||
return (int)(63 - leading_zero);
|
||||
else
|
||||
return 64;
|
||||
#else
|
||||
return __builtin_clzll(input_num);
|
||||
#endif// SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||
}
|
||||
|
||||
/* result might be undefined when input_num is zero */
|
||||
simdjson_inline int count_ones(uint64_t input_num) {
|
||||
return vaddv_u8(vcnt_u8(vcreate_u8(input_num)));
|
||||
}
|
||||
|
||||
|
||||
#if defined(__GNUC__) // catches clang and gcc
|
||||
/**
|
||||
* ARM has a fast 64-bit "bit reversal function" that is handy. However,
|
||||
* it is not generally available as an intrinsic function under Visual
|
||||
* Studio (though this might be changing). Even under clang/gcc, we
|
||||
* apparently need to invoke inline assembly.
|
||||
*/
|
||||
/*
|
||||
* We use SIMDJSON_PREFER_REVERSE_BITS as a hint that algorithms that
|
||||
* work well with bit reversal may use it.
|
||||
*/
|
||||
#define SIMDJSON_PREFER_REVERSE_BITS 1
|
||||
|
||||
/* reverse the bits */
|
||||
simdjson_inline uint64_t reverse_bits(uint64_t input_num) {
|
||||
uint64_t rev_bits;
|
||||
__asm("rbit %0, %1" : "=r"(rev_bits) : "r"(input_num));
|
||||
return rev_bits;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flips bit at index 63 - lz. Thus if you have 'leading_zeroes' leading zeroes,
|
||||
* then this will set to zero the leading bit. It is possible for leading_zeroes to be
|
||||
* greating or equal to 63 in which case we trigger undefined behavior, but the output
|
||||
* of such undefined behavior is never used.
|
||||
**/
|
||||
SIMDJSON_NO_SANITIZE_UNDEFINED
|
||||
simdjson_inline uint64_t zero_leading_bit(uint64_t rev_bits, int leading_zeroes) {
|
||||
return rev_bits ^ (uint64_t(0x8000000000000000) >> leading_zeroes);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
simdjson_inline uint64_t add_carry_out(uint64_t value1, uint64_t value2, bool &carry_out) {
|
||||
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||
uint64_t result = value1 + value2;
|
||||
carry_out = result < value1;
|
||||
return result;
|
||||
#else
|
||||
unsigned long long result;
|
||||
carry_out = __builtin_uaddll_overflow(value1, value2, &result);
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
simdjson_inline uint64_t subtract_borrow(uint64_t value1, uint64_t value2, bool &borrow) {
|
||||
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||
value2 += borrow;
|
||||
uint64_t result = value1 - value2;
|
||||
borrow = value1 > value2;
|
||||
return result;
|
||||
#else
|
||||
unsigned long long result;
|
||||
bool borrow1 = __builtin_usubll_overflow(value1, value2, &result);
|
||||
borrow = borrow1 | __builtin_usubll_overflow(result, borrow, &result);
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
simdjson_inline uint64_t subtract_borrow_out(uint64_t value1, uint64_t value2, bool &borrow_out) {
|
||||
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||
uint64_t result = value1 - value2;
|
||||
borrow_out = result > value1;
|
||||
return result;
|
||||
#else
|
||||
unsigned long long result;
|
||||
borrow_out = __builtin_usubll_overflow(value1, value2, &result);
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
//
|
||||
// Perform a "cumulative bitwise xor," flipping bits each time a 1 is encountered.
|
||||
|
||||
@@ -1 +1,6 @@
|
||||
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
#include "simdjson/arm64/base.h"
|
||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
#undef SIMDJSON_SKIP_BACKSLASH_SHORT_CIRCUIT
|
||||
#undef SIMDJSON_IMPLEMENTATION
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
#ifndef SIMDJSON_ARM64_IMPLEMENTATION_H
|
||||
#define SIMDJSON_ARM64_IMPLEMENTATION_H
|
||||
|
||||
#ifndef SIMDJSON_AMALGAMATED
|
||||
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
#include "simdjson/base.h"
|
||||
#include "simdjson/implementation.h"
|
||||
#include "simdjson/internal/instruction_set.h"
|
||||
#endif // SIMDJSON_AMALGAMATED
|
||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
namespace simdjson {
|
||||
namespace arm64 {
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
#ifndef SIMDJSON_ARM64_INTRINSICS_H
|
||||
#define SIMDJSON_ARM64_INTRINSICS_H
|
||||
|
||||
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
#include "simdjson/arm64/base.h"
|
||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
// This should be the correct header whether
|
||||
// you use visual studio or other compilers.
|
||||
#include <arm_neon.h>
|
||||
|
||||
#include "simdjson/arm64/base.h"
|
||||
|
||||
static_assert(sizeof(uint8x16_t) <= simdjson::SIMDJSON_PADDING, "insufficient padding for arm64");
|
||||
|
||||
#endif // SIMDJSON_ARM64_INTRINSICS_H
|
||||
|
||||
@@ -1,22 +1,21 @@
|
||||
#ifndef SIMDJSON_ARM64_NUMBERPARSING_DEFS_H
|
||||
#define SIMDJSON_ARM64_NUMBERPARSING_DEFS_H
|
||||
|
||||
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
#include "simdjson/arm64/base.h"
|
||||
#include "simdjson/arm64/intrinsics.h"
|
||||
#include "simdjson/internal/numberparsing_tables.h"
|
||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#if _M_ARM64
|
||||
// __umulh requires intrin.h
|
||||
#include <intrin.h>
|
||||
#endif // _M_ARM64
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#ifndef SIMDJSON_AMALGAMATED
|
||||
#include "simdjson/internal/numberparsing_tables.h"
|
||||
#endif // SIMDJSON_AMALGAMATED
|
||||
|
||||
namespace simdjson {
|
||||
namespace SIMDJSON_IMPLEMENTATION {
|
||||
namespace arm64 {
|
||||
namespace numberparsing {
|
||||
|
||||
// we don't have SSE, so let us use a scalar function
|
||||
@@ -49,7 +48,7 @@ simdjson_inline internal::value128 full_multiplication(uint64_t value1, uint64_t
|
||||
}
|
||||
|
||||
} // namespace numberparsing
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
} // namespace arm64
|
||||
} // namespace simdjson
|
||||
|
||||
#define SIMDJSON_SWAR_NUMBER_PARSING 1
|
||||
|
||||
+208
-55
@@ -1,16 +1,14 @@
|
||||
#ifndef SIMDJSON_ARM64_SIMD_H
|
||||
#define SIMDJSON_ARM64_SIMD_H
|
||||
|
||||
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
#include "simdjson/arm64/base.h"
|
||||
#include "simdjson/arm64/bitmanipulation.h"
|
||||
|
||||
#ifndef SIMDJSON_AMALGAMATED
|
||||
#include "simdjson/arm64/bitmask.h"
|
||||
#include "simdjson/internal/simdprune_tables.h"
|
||||
#endif // SIMDJSON_AMALGAMATED
|
||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
namespace simdjson {
|
||||
namespace SIMDJSON_IMPLEMENTATION {
|
||||
namespace {
|
||||
namespace arm64 {
|
||||
namespace simd {
|
||||
|
||||
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||
@@ -29,7 +27,7 @@ namespace {
|
||||
* You should not use this function except for compile-time constants:
|
||||
* it is not efficient.
|
||||
*/
|
||||
simdjson_inline uint8x16_t make_uint8x16_t(uint8_t x1, uint8_t x2, uint8_t x3, uint8_t x4,
|
||||
simdjson_inline simd_t make_uint8x16_t(uint8_t x1, uint8_t x2, uint8_t x3, uint8_t x4,
|
||||
uint8_t x5, uint8_t x6, uint8_t x7, uint8_t x8,
|
||||
uint8_t x9, uint8_t x10, uint8_t x11, uint8_t x12,
|
||||
uint8_t x13, uint8_t x14, uint8_t x15, uint8_t x16) {
|
||||
@@ -37,7 +35,7 @@ simdjson_inline uint8x16_t make_uint8x16_t(uint8_t x1, uint8_t x2, uint8_t x3,
|
||||
// uint8_t array[16] = {x1, x2, x3, x4, x5, x6, x7, x8,
|
||||
// x9, x10,x11,x12,x13,x14,x15,x16};
|
||||
// return vld1q_u8(array);
|
||||
uint8x16_t x{};
|
||||
simd_t x{};
|
||||
// incredibly, Visual Studio does not allow x[0] = x1
|
||||
x = vsetq_lane_u8(x1, x, 0);
|
||||
x = vsetq_lane_u8(x2, x, 1);
|
||||
@@ -110,18 +108,28 @@ simdjson_inline int8x16_t make_int8x16_t(int8_t x1, int8_t x2, int8_t x3, int
|
||||
template<typename T>
|
||||
struct simd8;
|
||||
|
||||
#if !SIMDJSON_IS_ARM && !defined(SIMDJSON_CONDITIONAL_INCLUDE)
|
||||
// Make errors a bit more manageable when editing on non-ARM
|
||||
struct uint8x16_t { uint8_t x[16]; };
|
||||
#endif
|
||||
|
||||
//
|
||||
// Base class of simd8<uint8_t> and simd8<bool>, both of which use uint8x16_t internally.
|
||||
//
|
||||
template<typename T, typename Mask=simd8<bool>>
|
||||
struct base_u8 {
|
||||
uint8x16_t value;
|
||||
static const int SIZE = sizeof(value);
|
||||
/** The actual underlying system SIMD type. */
|
||||
using simd_t = uint8x16_t;
|
||||
static constexpr const int LANES = sizeof(simd_t);
|
||||
using bitmask_t = uint16_t;
|
||||
static_assert(sizeof(bitmask_t)*8 == LANES, "Bitmask type's bits must equal the simd type's bytes");
|
||||
|
||||
simd_t value;
|
||||
|
||||
// Conversion from/to SIMD register
|
||||
simdjson_inline base_u8(const uint8x16_t _value) : value(_value) {}
|
||||
simdjson_inline operator const uint8x16_t&() const { return this->value; }
|
||||
simdjson_inline operator uint8x16_t&() { return this->value; }
|
||||
simdjson_inline base_u8(const simd_t _value) : value(_value) {}
|
||||
simdjson_inline operator const simd_t&() const { return this->value; }
|
||||
simdjson_inline operator simd_t&() { return this->value; }
|
||||
|
||||
// Bit operations
|
||||
simdjson_inline simd8<T> operator|(const simd8<T> other) const { return vorrq_u8(*this, other); }
|
||||
@@ -133,7 +141,8 @@ simdjson_inline int8x16_t make_int8x16_t(int8_t x1, int8_t x2, int8_t x3, int
|
||||
simdjson_inline simd8<T>& operator&=(const simd8<T> other) { auto this_cast = static_cast<simd8<T>*>(this); *this_cast = *this_cast & other; return *this_cast; }
|
||||
simdjson_inline simd8<T>& operator^=(const simd8<T> other) { auto this_cast = static_cast<simd8<T>*>(this); *this_cast = *this_cast ^ other; return *this_cast; }
|
||||
|
||||
friend simdjson_inline Mask operator==(const simd8<T> lhs, const simd8<T> rhs) { return vceqq_u8(lhs, rhs); }
|
||||
simdjson_inline Mask eq(const simd8<T> rhs) const { return vceqq_u8(*this, rhs); }
|
||||
friend simdjson_inline Mask operator==(const simd8<T> lhs, const simd8<T> rhs) { return lhs.eq(rhs); }
|
||||
|
||||
template<int N=1>
|
||||
simdjson_inline simd8<T> prev(const simd8<T> prev_chunk) const {
|
||||
@@ -149,7 +158,7 @@ simdjson_inline int8x16_t make_int8x16_t(int8_t x1, int8_t x2, int8_t x3, int
|
||||
|
||||
static simdjson_inline simd8<bool> splat(bool _value) { return vmovq_n_u8(uint8_t(-(!!_value))); }
|
||||
|
||||
simdjson_inline simd8(const uint8x16_t _value) : base_u8<bool>(_value) {}
|
||||
simdjson_inline simd8(const simd_t _value) : base_u8<bool>(_value) {}
|
||||
// False constructor
|
||||
simdjson_inline simd8() : simd8(vdupq_n_u8(0)) {}
|
||||
// Splat constructor
|
||||
@@ -159,14 +168,14 @@ simdjson_inline int8x16_t make_int8x16_t(int8_t x1, int8_t x2, int8_t x3, int
|
||||
// purposes (cutting it down to uint16_t costs performance in some compilers).
|
||||
simdjson_inline uint32_t to_bitmask() const {
|
||||
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||
const uint8x16_t bit_mask = make_uint8x16_t(0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80,
|
||||
const simd_t bit_mask = make_simd_t(0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80,
|
||||
0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80);
|
||||
#else
|
||||
const uint8x16_t bit_mask = {0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80,
|
||||
const simd_t bit_mask = {0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80,
|
||||
0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80};
|
||||
#endif
|
||||
auto minput = *this & bit_mask;
|
||||
uint8x16_t tmp = vpaddq_u8(minput, minput);
|
||||
simd_t tmp = vpaddq_u8(minput, minput);
|
||||
tmp = vpaddq_u8(tmp, tmp);
|
||||
tmp = vpaddq_u8(tmp, tmp);
|
||||
return vgetq_lane_u16(vreinterpretq_u16_u8(tmp), 0);
|
||||
@@ -177,11 +186,14 @@ simdjson_inline int8x16_t make_int8x16_t(int8_t x1, int8_t x2, int8_t x3, int
|
||||
// Unsigned bytes
|
||||
template<>
|
||||
struct simd8<uint8_t>: base_u8<uint8_t> {
|
||||
static simdjson_inline uint8x16_t splat(uint8_t _value) { return vmovq_n_u8(_value); }
|
||||
static simdjson_inline uint8x16_t zero() { return vdupq_n_u8(0); }
|
||||
static simdjson_inline uint8x16_t load(const uint8_t* values) { return vld1q_u8(values); }
|
||||
using typename base_u8<uint8_t>::simd_t;
|
||||
using base_u8<uint8_t>::LANES;
|
||||
|
||||
simdjson_inline simd8(const uint8x16_t _value) : base_u8<uint8_t>(_value) {}
|
||||
static simdjson_inline simd_t splat(uint8_t _value) { return vmovq_n_u8(_value); }
|
||||
static simdjson_inline simd_t zero() { return vdupq_n_u8(0); }
|
||||
static simdjson_inline simd_t load(const uint8_t* values) { return vld1q_u8(values); }
|
||||
|
||||
simdjson_inline simd8(const simd_t _value) : base_u8<uint8_t>(_value) {}
|
||||
// Zero constructor
|
||||
simdjson_inline simd8() : simd8(zero()) {}
|
||||
// Array constructor
|
||||
@@ -201,7 +213,7 @@ simdjson_inline int8x16_t make_int8x16_t(int8_t x1, int8_t x2, int8_t x3, int
|
||||
simdjson_inline simd8(
|
||||
uint8_t v0, uint8_t v1, uint8_t v2, uint8_t v3, uint8_t v4, uint8_t v5, uint8_t v6, uint8_t v7,
|
||||
uint8_t v8, uint8_t v9, uint8_t v10, uint8_t v11, uint8_t v12, uint8_t v13, uint8_t v14, uint8_t v15
|
||||
) : simd8(uint8x16_t{
|
||||
) : simd8(simd_t{
|
||||
v0, v1, v2, v3, v4, v5, v6, v7,
|
||||
v8, v9, v10,v11,v12,v13,v14,v15
|
||||
}) {}
|
||||
@@ -255,15 +267,20 @@ simdjson_inline int8x16_t make_int8x16_t(int8_t x1, int8_t x2, int8_t x3, int
|
||||
simdjson_inline simd8<uint8_t> shl() const { return vshlq_n_u8(*this, N); }
|
||||
|
||||
// Perform a lookup assuming the value is between 0 and 16 (undefined behavior for out of range values)
|
||||
template<typename L>
|
||||
simdjson_inline simd8<L> lookup_16(simd8<L> lookup_table) const {
|
||||
simdjson_inline simd8<uint8_t> lookup_16(simd8<uint8_t> lookup_table) const {
|
||||
return lookup_table.apply_lookup_16_to(*this);
|
||||
}
|
||||
|
||||
// Perform a lookup based on the lower 4 bits of each lane. (Platform-dependent behavior for
|
||||
// non-ASCII values--may look up the lower 4 bits on some platforms, and return 0 on others.)
|
||||
simdjson_inline simd8<uint8_t> lookup_low_nibble_ascii(simd8<uint8_t> lookup_table) const {
|
||||
return lookup_table.apply_lookup_16_to(*this & 0b10001111);
|
||||
}
|
||||
|
||||
|
||||
// Copies to 'output" all bytes corresponding to a 0 in the mask (interpreted as a bitset).
|
||||
// Passing a 0 value for mask would be equivalent to writing out every byte to output.
|
||||
// Only the first 16 - count_ones(mask) bytes of the result are significant but 16 bytes
|
||||
// Only the first 16 - bitmask::count_ones(mask) bytes of the result are significant but 16 bytes
|
||||
// get written.
|
||||
// Design consideration: it seems like a function with the
|
||||
// signature simd8<L> compress(uint16_t mask) would be
|
||||
@@ -281,16 +298,16 @@ simdjson_inline int8x16_t make_int8x16_t(int8_t x1, int8_t x2, int8_t x3, int
|
||||
// thintable_epi8[mask2] into a 128-bit register, using only
|
||||
// two instructions on most compilers.
|
||||
uint64x2_t shufmask64 = {thintable_epi8[mask1], thintable_epi8[mask2]};
|
||||
uint8x16_t shufmask = vreinterpretq_u8_u64(shufmask64);
|
||||
simd_t shufmask = vreinterpretq_u8_u64(shufmask64);
|
||||
// we increment by 0x08 the second half of the mask
|
||||
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||
uint8x16_t inc = make_uint8x16_t(0, 0, 0, 0, 0, 0, 0, 0, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08);
|
||||
simd_t inc = make_uint8x16_t(0, 0, 0, 0, 0, 0, 0, 0, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08);
|
||||
#else
|
||||
uint8x16_t inc = {0, 0, 0, 0, 0, 0, 0, 0, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08};
|
||||
simd_t inc = {0, 0, 0, 0, 0, 0, 0, 0, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08};
|
||||
#endif
|
||||
shufmask = vaddq_u8(shufmask, inc);
|
||||
// this is the version "nearly pruned"
|
||||
uint8x16_t pruned = vqtbl1q_u8(*this, shufmask);
|
||||
simd_t pruned = vqtbl1q_u8(*this, shufmask);
|
||||
// we still need to put the two halves together.
|
||||
// we compute the popcount of the first half:
|
||||
int pop1 = BitsSetTable256mul2[mask1];
|
||||
@@ -298,8 +315,8 @@ simdjson_inline int8x16_t make_int8x16_t(int8_t x1, int8_t x2, int8_t x3, int
|
||||
// only the first pop1 bytes from the first 8 bytes, and then
|
||||
// it fills in with the bytes from the second 8 bytes + some filling
|
||||
// at the end.
|
||||
uint8x16_t compactmask = vld1q_u8(reinterpret_cast<const uint8_t *>(pshufb_combine_table + pop1 * 8));
|
||||
uint8x16_t answer = vqtbl1q_u8(pruned, compactmask);
|
||||
simd_t compactmask = vld1q_u8(reinterpret_cast<const uint8_t *>(pshufb_combine_table + pop1 * 8));
|
||||
simd_t answer = vqtbl1q_u8(pruned, compactmask);
|
||||
vst1q_u8(reinterpret_cast<uint8_t*>(output), answer);
|
||||
}
|
||||
|
||||
@@ -324,20 +341,6 @@ simdjson_inline int8x16_t make_int8x16_t(int8_t x1, int8_t x2, int8_t x3, int
|
||||
vst1_u8((uint8_t*)output2, vqtbl1_u8(*this, compactmask2));
|
||||
}
|
||||
|
||||
template<typename L>
|
||||
simdjson_inline simd8<L> lookup_16(
|
||||
L replace0, L replace1, L replace2, L replace3,
|
||||
L replace4, L replace5, L replace6, L replace7,
|
||||
L replace8, L replace9, L replace10, L replace11,
|
||||
L replace12, L replace13, L replace14, L replace15) const {
|
||||
return lookup_16(simd8<L>::repeat_16(
|
||||
replace0, replace1, replace2, replace3,
|
||||
replace4, replace5, replace6, replace7,
|
||||
replace8, replace9, replace10, replace11,
|
||||
replace12, replace13, replace14, replace15
|
||||
));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
simdjson_inline simd8<uint8_t> apply_lookup_16_to(const simd8<T> original) {
|
||||
return vqtbl1q_u8(*this, simd8<uint8_t>(original));
|
||||
@@ -402,7 +405,7 @@ simdjson_inline int8x16_t make_int8x16_t(int8_t x1, int8_t x2, int8_t x3, int
|
||||
// In theory, we could check this occurrence with std::same_as and std::enabled_if but it is C++14
|
||||
// and relatively ugly and hard to read.
|
||||
#ifndef SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||
simdjson_inline explicit simd8(const uint8x16_t other): simd8(vreinterpretq_s8_u8(other)) {}
|
||||
simdjson_inline explicit simd8(const simd_t other): simd8(vreinterpretq_s8_u8(other)) {}
|
||||
#endif
|
||||
simdjson_inline explicit operator simd8<uint8_t>() const { return vreinterpretq_u8_s8(this->value); }
|
||||
|
||||
@@ -425,10 +428,13 @@ simdjson_inline int8x16_t make_int8x16_t(int8_t x1, int8_t x2, int8_t x3, int
|
||||
}
|
||||
|
||||
// Perform a lookup assuming no value is larger than 16
|
||||
template<typename L>
|
||||
simdjson_inline simd8<L> lookup_16(simd8<L> lookup_table) const {
|
||||
simdjson_inline simd8<int8_t> lookup_16(simd8<int8_t> lookup_table) const {
|
||||
return lookup_table.apply_lookup_16_to(*this);
|
||||
}
|
||||
// Perform a lookup based on the lower 4 bits of each lane, returning 0 for values with a high bit of 1.
|
||||
simdjson_inline simd8<int8_t> lookup_low_nibble_ascii(simd8<int8_t> lookup_table) const {
|
||||
return lookup_table.apply_lookup_16_to(*this & 0b10001111);
|
||||
}
|
||||
template<typename L>
|
||||
simdjson_inline simd8<L> lookup_16(
|
||||
L replace0, L replace1, L replace2, L replace3,
|
||||
@@ -461,6 +467,8 @@ simdjson_inline int8x16_t make_int8x16_t(int8_t x1, int8_t x2, int8_t x3, int
|
||||
|
||||
simdjson_inline simd8x64(const simd8<T> chunk0, const simd8<T> chunk1, const simd8<T> chunk2, const simd8<T> chunk3) : chunks{chunk0, chunk1, chunk2, chunk3} {}
|
||||
simdjson_inline simd8x64(const T ptr[64]) : chunks{simd8<T>::load(ptr), simd8<T>::load(ptr+16), simd8<T>::load(ptr+32), simd8<T>::load(ptr+48)} {}
|
||||
simdjson_inline simd8x64(simd8x64<T>&& o) noexcept = default;
|
||||
simdjson_inline simd8x64<T>& operator=(simd8x64<T>&& other) noexcept = default;
|
||||
|
||||
simdjson_inline void store(T ptr[64]) const {
|
||||
this->chunks[0].store(ptr+sizeof(simd8<T>)*0);
|
||||
@@ -487,19 +495,19 @@ simdjson_inline int8x16_t make_int8x16_t(int8_t x1, int8_t x2, int8_t x3, int
|
||||
|
||||
simdjson_inline uint64_t to_bitmask() const {
|
||||
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||
const uint8x16_t bit_mask = make_uint8x16_t(
|
||||
const simd_t bit_mask = make_uint8x16_t(
|
||||
0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80,
|
||||
0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80
|
||||
);
|
||||
#else
|
||||
const uint8x16_t bit_mask = {
|
||||
const simd_t bit_mask = {
|
||||
0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80,
|
||||
0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80
|
||||
};
|
||||
#endif
|
||||
// Add each of the elements next to each other, successively, to stuff each 8 byte mask into one.
|
||||
uint8x16_t sum0 = vpaddq_u8(this->chunks[0] & bit_mask, this->chunks[1] & bit_mask);
|
||||
uint8x16_t sum1 = vpaddq_u8(this->chunks[2] & bit_mask, this->chunks[3] & bit_mask);
|
||||
simd_t sum0 = vpaddq_u8(this->chunks[0] & bit_mask, this->chunks[1] & bit_mask);
|
||||
simd_t sum1 = vpaddq_u8(this->chunks[2] & bit_mask, this->chunks[3] & bit_mask);
|
||||
sum0 = vpaddq_u8(sum0, sum1);
|
||||
sum0 = vpaddq_u8(sum0, sum0);
|
||||
return vgetq_lane_u64(vreinterpretq_u64_u8(sum0), 0);
|
||||
@@ -515,6 +523,24 @@ simdjson_inline int8x16_t make_int8x16_t(int8_t x1, int8_t x2, int8_t x3, int
|
||||
).to_bitmask();
|
||||
}
|
||||
|
||||
simdjson_inline simd8x64<T> lookup_16(const simd8<T>& lookup_table) const {
|
||||
return {
|
||||
this->chunks[0].lookup_16(lookup_table),
|
||||
this->chunks[1].lookup_16(lookup_table),
|
||||
this->chunks[2].lookup_16(lookup_table),
|
||||
this->chunks[3].lookup_16(lookup_table)
|
||||
};
|
||||
}
|
||||
|
||||
simdjson_inline simd8x64<T> lookup_low_nibble_ascii(const simd8<T>& lookup_table) const {
|
||||
return {
|
||||
this->chunks[0].lookup_low_nibble_ascii(lookup_table),
|
||||
this->chunks[1].lookup_low_nibble_ascii(lookup_table),
|
||||
this->chunks[2].lookup_low_nibble_ascii(lookup_table),
|
||||
this->chunks[3].lookup_low_nibble_ascii(lookup_table)
|
||||
};
|
||||
}
|
||||
|
||||
simdjson_inline uint64_t lteq(const T m) const {
|
||||
const simd8<T> mask = simd8<T>::splat(m);
|
||||
return simd8x64<bool>(
|
||||
@@ -524,11 +550,138 @@ simdjson_inline int8x16_t make_int8x16_t(int8_t x1, int8_t x2, int8_t x3, int
|
||||
this->chunks[3] <= mask
|
||||
).to_bitmask();
|
||||
}
|
||||
|
||||
simdjson_inline simd8x64<T> operator&(const simd8x64<T>& other) const {
|
||||
return {
|
||||
this->chunks[0] & other.chunks[0],
|
||||
this->chunks[1] & other.chunks[1],
|
||||
this->chunks[2] & other.chunks[2],
|
||||
this->chunks[3] & other.chunks[3]
|
||||
};
|
||||
}
|
||||
|
||||
simdjson_inline simd8x64<T> operator&(const simd8<T>& other) const {
|
||||
return {
|
||||
this->chunks[0] & other,
|
||||
this->chunks[1] & other,
|
||||
this->chunks[2] & other,
|
||||
this->chunks[3] & other
|
||||
};
|
||||
}
|
||||
|
||||
simdjson_inline simd8x64<T> operator|(const simd8x64<T>& other) const {
|
||||
return {
|
||||
this->chunks[0] | other.chunks[0],
|
||||
this->chunks[1] | other.chunks[1],
|
||||
this->chunks[2] | other.chunks[2],
|
||||
this->chunks[3] | other.chunks[3]
|
||||
};
|
||||
}
|
||||
|
||||
simdjson_inline simd8x64<T> operator|(const simd8<T>& other) const {
|
||||
return {
|
||||
this->chunks[0] | other,
|
||||
this->chunks[1] | other,
|
||||
this->chunks[2] | other,
|
||||
this->chunks[3] | other
|
||||
};
|
||||
}
|
||||
|
||||
simdjson_inline simd8x64<T> operator^(const simd8x64<T>& other) const {
|
||||
return {
|
||||
this->chunks[0] ^ other.chunks[0],
|
||||
this->chunks[1] ^ other.chunks[1],
|
||||
this->chunks[2] ^ other.chunks[2],
|
||||
this->chunks[3] ^ other.chunks[3]
|
||||
};
|
||||
}
|
||||
|
||||
simdjson_inline simd8x64<T> operator^(const simd8<T>& other) const {
|
||||
return {
|
||||
this->chunks[0] ^ other,
|
||||
this->chunks[1] ^ other,
|
||||
this->chunks[2] ^ other,
|
||||
this->chunks[3] ^ other
|
||||
};
|
||||
}
|
||||
|
||||
simdjson_inline simd8x64<T> bit_andnot(const simd8x64<T>& other) const {
|
||||
return {
|
||||
this->chunks[0].bit_andnot(other.chunks[0]),
|
||||
this->chunks[1].bit_andnot(other.chunks[1]),
|
||||
this->chunks[2].bit_andnot(other.chunks[2]),
|
||||
this->chunks[3].bit_andnot(other.chunks[3])
|
||||
};
|
||||
}
|
||||
|
||||
simdjson_inline simd8x64<T> bit_andnot(const simd8<T>& other) const {
|
||||
return {
|
||||
this->chunks[0].bit_andnot(other),
|
||||
this->chunks[1].bit_andnot(other),
|
||||
this->chunks[2].bit_andnot(other),
|
||||
this->chunks[3].bit_andnot(other)
|
||||
};
|
||||
}
|
||||
|
||||
template <int N>
|
||||
simdjson_inline simd8x64<T> shr() const noexcept {
|
||||
return {
|
||||
this->chunks[0].template shr<N>(),
|
||||
this->chunks[1].template shr<N>(),
|
||||
this->chunks[2].template shr<N>(),
|
||||
this->chunks[3].template shr<N>()
|
||||
};
|
||||
}
|
||||
|
||||
template <int N>
|
||||
simdjson_inline simd8x64<T> shl() const noexcept {
|
||||
return {
|
||||
this->chunks[0].template shl<N>(),
|
||||
this->chunks[1].template shl<N>(),
|
||||
this->chunks[2].template shl<N>(),
|
||||
this->chunks[3].template shl<N>()
|
||||
};
|
||||
}
|
||||
|
||||
simdjson_inline simd8x64<bool> any_bits_set(const simd8<T>& bits) const {
|
||||
return {
|
||||
this->chunks[0].any_bits_set(bits),
|
||||
this->chunks[1].any_bits_set(bits),
|
||||
this->chunks[2].any_bits_set(bits),
|
||||
this->chunks[3].any_bits_set(bits)
|
||||
};
|
||||
}
|
||||
|
||||
simdjson_inline simd8x64<bool> any_bits_set(const simd8x64<T>& bits) const {
|
||||
return {
|
||||
this->chunks[0].any_bits_set(bits.chunks[0]),
|
||||
this->chunks[1].any_bits_set(bits.chunks[1]),
|
||||
this->chunks[2].any_bits_set(bits.chunks[2]),
|
||||
this->chunks[3].any_bits_set(bits.chunks[3])
|
||||
};
|
||||
}
|
||||
|
||||
simdjson_inline simd8x64<bool> no_bits_set(const simd8<T>& bits) const {
|
||||
return {
|
||||
this->chunks[0].no_bits_set(bits),
|
||||
this->chunks[1].no_bits_set(bits),
|
||||
this->chunks[2].no_bits_set(bits),
|
||||
this->chunks[3].no_bits_set(bits)
|
||||
};
|
||||
}
|
||||
|
||||
simdjson_inline simd8x64<bool> no_bits_set(const simd8x64<T>& bits) const {
|
||||
return {
|
||||
this->chunks[0].no_bits_set(bits.chunks[0]),
|
||||
this->chunks[1].no_bits_set(bits.chunks[1]),
|
||||
this->chunks[2].no_bits_set(bits.chunks[2]),
|
||||
this->chunks[3].no_bits_set(bits.chunks[3])
|
||||
};
|
||||
}
|
||||
}; // struct simd8x64<T>
|
||||
|
||||
} // namespace simd
|
||||
} // unnamed namespace
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
} // namespace arm64
|
||||
} // namespace simdjson
|
||||
|
||||
#endif // SIMDJSON_ARM64_SIMD_H
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
#ifndef SIMDJSON_ARM64_SINGLESTAGE_H
|
||||
#define SIMDJSON_ARM64_SINGLESTAGE_H
|
||||
|
||||
#include "simdjson/arm64/begin.h"
|
||||
#include "simdjson/generic/singlestage/amalgamated.h"
|
||||
#include "simdjson/arm64/end.h"
|
||||
|
||||
#endif // SIMDJSON_ARM64_SINGLESTAGE_H
|
||||
@@ -1,12 +1,14 @@
|
||||
#ifndef SIMDJSON_ARM64_STRINGPARSING_DEFS_H
|
||||
#define SIMDJSON_ARM64_STRINGPARSING_DEFS_H
|
||||
|
||||
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
#include "simdjson/arm64/base.h"
|
||||
#include "simdjson/arm64/simd.h"
|
||||
#include "simdjson/arm64/bitmanipulation.h"
|
||||
#include "simdjson/arm64/bitmask.h"
|
||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
namespace simdjson {
|
||||
namespace SIMDJSON_IMPLEMENTATION {
|
||||
namespace arm64 {
|
||||
namespace {
|
||||
|
||||
using namespace simd;
|
||||
@@ -19,8 +21,8 @@ public:
|
||||
|
||||
simdjson_inline bool has_quote_first() { return ((bs_bits - 1) & quote_bits) != 0; }
|
||||
simdjson_inline bool has_backslash() { return bs_bits != 0; }
|
||||
simdjson_inline int quote_index() { return trailing_zeroes(quote_bits); }
|
||||
simdjson_inline int backslash_index() { return trailing_zeroes(bs_bits); }
|
||||
simdjson_inline int quote_index() { return bitmask::trailing_zeroes(quote_bits); }
|
||||
simdjson_inline int backslash_index() { return bitmask::trailing_zeroes(bs_bits); }
|
||||
|
||||
uint32_t bs_bits;
|
||||
uint32_t quote_bits;
|
||||
@@ -45,7 +47,7 @@ simdjson_inline backslash_and_quote backslash_and_quote::copy_and_find(const uin
|
||||
}
|
||||
|
||||
} // unnamed namespace
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
} // namespace arm64
|
||||
} // namespace simdjson
|
||||
|
||||
#endif // SIMDJSON_ARM64_STRINGPARSING_DEFS_H
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
#include "simdjson/generic/dependencies.h"
|
||||
|
||||
#define SIMDJSON_AMALGAMATED
|
||||
#define SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
#if SIMDJSON_BUILTIN_IMPLEMENTATION_IS(arm64)
|
||||
#include "simdjson/arm64.h"
|
||||
@@ -24,6 +24,6 @@
|
||||
#error Unknown SIMDJSON_BUILTIN_IMPLEMENTATION
|
||||
#endif
|
||||
|
||||
#undef SIMDJSON_AMALGAMATED
|
||||
#undef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
#endif // SIMDJSON_BUILTIN_H
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
#include "simdjson/generic/dependencies.h"
|
||||
|
||||
#define SIMDJSON_AMALGAMATED
|
||||
#define SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
#if SIMDJSON_BUILTIN_IMPLEMENTATION_IS(arm64)
|
||||
#include "simdjson/arm64/implementation.h"
|
||||
@@ -23,7 +23,7 @@
|
||||
#error Unknown SIMDJSON_BUILTIN_IMPLEMENTATION
|
||||
#endif
|
||||
|
||||
#undef SIMDJSON_AMALGAMATED
|
||||
#undef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
namespace simdjson {
|
||||
/**
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
#include "simdjson/generic/ondemand/dependencies.h"
|
||||
|
||||
#define SIMDJSON_AMALGAMATED
|
||||
#define SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
#if SIMDJSON_BUILTIN_IMPLEMENTATION_IS(arm64)
|
||||
#include "simdjson/arm64/ondemand.h"
|
||||
@@ -24,7 +24,7 @@
|
||||
#error Unknown SIMDJSON_BUILTIN_IMPLEMENTATION
|
||||
#endif
|
||||
|
||||
#undef SIMDJSON_AMALGAMATED
|
||||
#undef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
namespace simdjson {
|
||||
/**
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
#ifndef SIMDJSON_BUILTIN_SINGLESTAGE_H
|
||||
#define SIMDJSON_BUILTIN_SINGLESTAGE_H
|
||||
|
||||
#include "simdjson/builtin.h"
|
||||
#include "simdjson/builtin/base.h"
|
||||
|
||||
#include "simdjson/generic/singlestage/dependencies.h"
|
||||
|
||||
#define SIMDJSON_AMALGAMATED
|
||||
|
||||
#if SIMDJSON_BUILTIN_IMPLEMENTATION_IS(arm64)
|
||||
#include "simdjson/arm64/singlestage.h"
|
||||
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(fallback)
|
||||
#include "simdjson/fallback/singlestage.h"
|
||||
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(haswell)
|
||||
#include "simdjson/haswell/singlestage.h"
|
||||
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(icelake)
|
||||
#include "simdjson/icelake/singlestage.h"
|
||||
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(ppc64)
|
||||
#include "simdjson/ppc64/singlestage.h"
|
||||
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(westmere)
|
||||
#include "simdjson/westmere/singlestage.h"
|
||||
#else
|
||||
#error Unknown SIMDJSON_BUILTIN_IMPLEMENTATION
|
||||
#endif
|
||||
|
||||
#undef SIMDJSON_AMALGAMATED
|
||||
|
||||
namespace simdjson {
|
||||
/**
|
||||
* @copydoc simdjson::SIMDJSON_BUILTIN_IMPLEMENTATION::singlestage
|
||||
*/
|
||||
namespace singlestage = SIMDJSON_BUILTIN_IMPLEMENTATION::singlestage;
|
||||
} // namespace simdjson
|
||||
|
||||
#endif // SIMDJSON_BUILTIN_SINGLESTAGE_H
|
||||
@@ -167,6 +167,41 @@ double from_chars(const char *first, const char* end) noexcept;
|
||||
#define simdjson_inline simdjson_really_inline
|
||||
#endif
|
||||
|
||||
#ifndef simdjson_constexpr
|
||||
#if __cpp_constexpr
|
||||
#define simdjson_constexpr constexpr simdjson_inline
|
||||
#else
|
||||
#define simdjson_constexpr simdjson_inline
|
||||
#endif
|
||||
#endif
|
||||
// simdjson_constexpr
|
||||
|
||||
#ifndef simdjson_consteval
|
||||
#if __cpp_consteval
|
||||
#define simdjson_consteval consteval simdjson_inline
|
||||
#else
|
||||
#define simdjson_consteval simdjson_constexpr
|
||||
#endif
|
||||
#endif // simdjson_consteval
|
||||
|
||||
#ifndef simdjson_constinit
|
||||
#if __cpp_constinit
|
||||
#define simdjson_constinit constinit
|
||||
#elif __cpp_consteval
|
||||
#define simdjson_constinit consteval
|
||||
#else
|
||||
#define simdjson_constinit constexpr
|
||||
#endif
|
||||
#endif // simdjson_constinit
|
||||
|
||||
#ifndef simdjson_if_constexpr
|
||||
#if SIMDJSON_CPLUSPLUS17
|
||||
#define simdjson_if_constexpr constexpr
|
||||
#else
|
||||
#define simdjson_if_constexpr
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if SIMDJSON_VISUAL_STUDIO
|
||||
/**
|
||||
* Windows users need to do some extra work when building
|
||||
|
||||
@@ -32,4 +32,12 @@
|
||||
#error simdjson requires a compiler compliant with the C++11 standard
|
||||
#endif
|
||||
|
||||
#ifndef SIMDJSON_IF_CONSTEXPR
|
||||
#if SIMDJSON_CPLUSPLUS17
|
||||
#define SIMDJSON_IF_CONSTEXPR if constexpr
|
||||
#else
|
||||
#define SIMDJSON_IF_CONSTEXPR if
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif // SIMDJSON_COMPILER_CHECK_H
|
||||
|
||||
@@ -5,10 +5,12 @@
|
||||
|
||||
#include "simdjson/dom/base.h"
|
||||
#include "simdjson/dom/document.h"
|
||||
#include "simdjson/dom/element.h"
|
||||
#include "simdjson/dom/element-inl.h"
|
||||
#include "simdjson/internal/tape_ref-inl.h"
|
||||
#include "simdjson/internal/jsonformatutils.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace simdjson {
|
||||
namespace dom {
|
||||
|
||||
|
||||
@@ -7,8 +7,12 @@
|
||||
#include "simdjson/dom/object.h"
|
||||
#include "simdjson/internal/tape_type.h"
|
||||
|
||||
#include "simdjson/dom/object-inl.h"
|
||||
#include "simdjson/error-inl.h"
|
||||
|
||||
#include <ostream>
|
||||
#include <limits>
|
||||
|
||||
namespace simdjson {
|
||||
|
||||
//
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
#include "simdjson/dom/parser.h"
|
||||
#include "simdjson/dom/element.h"
|
||||
|
||||
#include "simdjson/dom/parser-inl.h"
|
||||
|
||||
namespace simdjson {
|
||||
|
||||
//
|
||||
|
||||
@@ -5,6 +5,11 @@
|
||||
#include "simdjson/dom/object.h"
|
||||
#include "simdjson/dom/document.h"
|
||||
|
||||
#include "simdjson/dom/element-inl.h"
|
||||
#include "simdjson/error-inl.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace simdjson {
|
||||
|
||||
//
|
||||
|
||||
@@ -3,10 +3,15 @@
|
||||
|
||||
#include "simdjson/dom/base.h"
|
||||
#include "simdjson/dom/parsedjson_iterator.h"
|
||||
#include "simdjson/internal/tape_ref-inl.h"
|
||||
#include "simdjson/internal/jsonformatutils.h"
|
||||
#include <ostream>
|
||||
|
||||
#include "simdjson/dom/parser-inl.h"
|
||||
#include "simdjson/internal/tape_ref-inl.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
#include <ostream>
|
||||
|
||||
#ifndef SIMDJSON_DISABLE_DEPRECATED_API
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include "simdjson/error-inl.h"
|
||||
#include "simdjson/padded_string-inl.h"
|
||||
#include "simdjson/dom/document_stream-inl.h"
|
||||
#include "simdjson/dom/element-inl.h"
|
||||
|
||||
#include <climits>
|
||||
|
||||
@@ -7,6 +7,12 @@
|
||||
#include "simdjson/dom/parser.h"
|
||||
#include "simdjson/internal/tape_type.h"
|
||||
|
||||
#include "simdjson/dom/array-inl.h"
|
||||
#include "simdjson/dom/object-inl.h"
|
||||
#include "simdjson/internal/tape_ref-inl.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace simdjson {
|
||||
namespace dom {
|
||||
inline bool parser::print_json(std::ostream &os) const noexcept {
|
||||
@@ -17,12 +23,46 @@ inline bool parser::print_json(std::ostream &os) const noexcept {
|
||||
os << answer;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& out, simdjson::dom::element value) {
|
||||
simdjson::internal::string_builder<> sb;
|
||||
sb.append(value);
|
||||
return (out << sb.str());
|
||||
}
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::dom::element> x) {
|
||||
if (x.error()) { throw simdjson::simdjson_error(x.error()); }
|
||||
return (out << x.value());
|
||||
}
|
||||
#endif
|
||||
inline std::ostream& operator<<(std::ostream& out, simdjson::dom::array value) {
|
||||
simdjson::internal::string_builder<> sb;
|
||||
sb.append(value);
|
||||
return (out << sb.str());
|
||||
}
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::dom::array> x) {
|
||||
if (x.error()) { throw simdjson::simdjson_error(x.error()); }
|
||||
return (out << x.value());
|
||||
}
|
||||
#endif
|
||||
inline std::ostream& operator<<(std::ostream& out, simdjson::dom::object value) {
|
||||
simdjson::internal::string_builder<> sb;
|
||||
sb.append(value);
|
||||
return (out << sb.str());
|
||||
}
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::dom::object> x) {
|
||||
if (x.error()) { throw simdjson::simdjson_error(x.error()); }
|
||||
return (out << x.value());
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace dom
|
||||
|
||||
/***
|
||||
* Number utility functions
|
||||
**/
|
||||
|
||||
|
||||
namespace {
|
||||
/**@private
|
||||
* Escape sequence like \b or \u0001
|
||||
|
||||
@@ -146,16 +146,9 @@ namespace dom {
|
||||
* @param value The element.
|
||||
* @throw if there is an error with the underlying output stream. simdjson itself will not throw.
|
||||
*/
|
||||
inline std::ostream& operator<<(std::ostream& out, simdjson::dom::element value) {
|
||||
simdjson::internal::string_builder<> sb;
|
||||
sb.append(value);
|
||||
return (out << sb.str());
|
||||
}
|
||||
inline std::ostream& operator<<(std::ostream& out, simdjson::dom::element value);
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::dom::element> x) {
|
||||
if (x.error()) { throw simdjson::simdjson_error(x.error()); }
|
||||
return (out << x.value());
|
||||
}
|
||||
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::dom::element> x);
|
||||
#endif
|
||||
/**
|
||||
* Print JSON to an output stream.
|
||||
@@ -164,16 +157,9 @@ inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<sim
|
||||
* @param value The array.
|
||||
* @throw if there is an error with the underlying output stream. simdjson itself will not throw.
|
||||
*/
|
||||
inline std::ostream& operator<<(std::ostream& out, simdjson::dom::array value) {
|
||||
simdjson::internal::string_builder<> sb;
|
||||
sb.append(value);
|
||||
return (out << sb.str());
|
||||
}
|
||||
inline std::ostream& operator<<(std::ostream& out, simdjson::dom::array value);
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::dom::array> x) {
|
||||
if (x.error()) { throw simdjson::simdjson_error(x.error()); }
|
||||
return (out << x.value());
|
||||
}
|
||||
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::dom::array> x);
|
||||
#endif
|
||||
/**
|
||||
* Print JSON to an output stream.
|
||||
@@ -182,16 +168,9 @@ inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<sim
|
||||
* @param value The object.
|
||||
* @throw if there is an error with the underlying output stream. simdjson itself will not throw.
|
||||
*/
|
||||
inline std::ostream& operator<<(std::ostream& out, simdjson::dom::object value) {
|
||||
simdjson::internal::string_builder<> sb;
|
||||
sb.append(value);
|
||||
return (out << sb.str());
|
||||
}
|
||||
inline std::ostream& operator<<(std::ostream& out, simdjson::dom::object value);
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::dom::object> x) {
|
||||
if (x.error()) { throw simdjson::simdjson_error(x.error()); }
|
||||
return (out << x.value());
|
||||
}
|
||||
inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::dom::object> x);
|
||||
#endif
|
||||
} // namespace dom
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#ifndef SIMDJSON_ERROR_INL_H
|
||||
#define SIMDJSON_ERROR_INL_H
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "simdjson/error.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace simdjson {
|
||||
namespace internal {
|
||||
// We store the error code so we can validate the error message is associated with the right code
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
#define SIMDJSON_ERROR_H
|
||||
|
||||
#include "simdjson/base.h"
|
||||
|
||||
#include <string>
|
||||
#include <ostream>
|
||||
|
||||
namespace simdjson {
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#ifndef SIMDJSON_FALLBACK_BASE_H
|
||||
#define SIMDJSON_FALLBACK_BASE_H
|
||||
|
||||
#ifndef SIMDJSON_AMALGAMATED
|
||||
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
#include "simdjson/base.h"
|
||||
#endif // SIMDJSON_AMALGAMATED
|
||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
namespace simdjson {
|
||||
/**
|
||||
@@ -16,11 +16,4 @@ class implementation;
|
||||
} // namespace fallback
|
||||
} // namespace simdjson
|
||||
|
||||
#ifndef SIMDJSON_AMALGAMATED
|
||||
// If we're editing one of the files in this directory, begin the implementation!
|
||||
#ifndef SIMDJSON_IMPLEMENTATION
|
||||
#include "simdjson/fallback/begin.h"
|
||||
#endif
|
||||
#endif // SIMDJSON_AMALGAMATED
|
||||
|
||||
#endif // SIMDJSON_FALLBACK_BASE_H
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#define SIMDJSON_IMPLEMENTATION fallback
|
||||
#include "simdjson/fallback/base.h"
|
||||
#include "simdjson/fallback/bitmanipulation.h"
|
||||
#include "simdjson/fallback/bitmask.h"
|
||||
#include "simdjson/fallback/stringparsing_defs.h"
|
||||
#include "simdjson/fallback/numberparsing_defs.h"
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
#ifndef SIMDJSON_FALLBACK_BITMANIPULATION_H
|
||||
#define SIMDJSON_FALLBACK_BITMANIPULATION_H
|
||||
#ifndef SIMDJSON_FALLBACK_BITMASK_H
|
||||
#define SIMDJSON_FALLBACK_BITMASK_H
|
||||
|
||||
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
#include "simdjson/fallback/base.h"
|
||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
namespace simdjson {
|
||||
namespace SIMDJSON_IMPLEMENTATION {
|
||||
namespace {
|
||||
namespace fallback {
|
||||
namespace bitmask {
|
||||
|
||||
#if defined(_MSC_VER) && !defined(_M_ARM64) && !defined(_M_X64)
|
||||
static inline unsigned char _BitScanForward64(unsigned long* ret, uint64_t x) {
|
||||
@@ -40,7 +42,7 @@ simdjson_inline int leading_zeroes(uint64_t input_num) {
|
||||
}
|
||||
|
||||
} // unnamed namespace
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
} // namespace fallback
|
||||
} // namespace simdjson
|
||||
|
||||
#endif // SIMDJSON_FALLBACK_BITMANIPULATION_H
|
||||
@@ -1 +1,5 @@
|
||||
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
#include "simdjson/fallback/base.h"
|
||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
#undef SIMDJSON_IMPLEMENTATION
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
#ifndef SIMDJSON_FALLBACK_IMPLEMENTATION_H
|
||||
#define SIMDJSON_FALLBACK_IMPLEMENTATION_H
|
||||
|
||||
#ifndef SIMDJSON_AMALGAMATED
|
||||
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
#include "simdjson/fallback/base.h"
|
||||
#include "simdjson/implementation.h"
|
||||
#endif // SIMDJSON_AMALGAMATED
|
||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
namespace simdjson {
|
||||
namespace fallback {
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
#ifndef SIMDJSON_FALLBACK_NUMBERPARSING_DEFS_H
|
||||
#define SIMDJSON_FALLBACK_NUMBERPARSING_DEFS_H
|
||||
|
||||
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
#include "simdjson/fallback/base.h"
|
||||
|
||||
#ifndef SIMDJSON_AMALGAMATED
|
||||
#include "simdjson/internal/numberparsing_tables.h"
|
||||
#endif // SIMDJSON_AMALGAMATED
|
||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#ifdef JSON_TEST_NUMBERS // for unit testing
|
||||
void found_invalid_number(const uint8_t *buf);
|
||||
@@ -15,7 +16,7 @@ void found_float(double result, const uint8_t *buf);
|
||||
#endif
|
||||
|
||||
namespace simdjson {
|
||||
namespace SIMDJSON_IMPLEMENTATION {
|
||||
namespace fallback {
|
||||
namespace numberparsing {
|
||||
|
||||
// credit: https://johnnylee-sde.github.io/Fast-numeric-string-to-int/
|
||||
@@ -71,7 +72,7 @@ simdjson_inline internal::value128 full_multiplication(uint64_t value1, uint64_t
|
||||
}
|
||||
|
||||
} // namespace numberparsing
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
} // namespace fallback
|
||||
} // namespace simdjson
|
||||
|
||||
#define SIMDJSON_SWAR_NUMBER_PARSING 1
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
#ifndef SIMDJSON_FALLBACK_SINGLESTAGE_H
|
||||
#define SIMDJSON_FALLBACK_SINGLESTAGE_H
|
||||
|
||||
#include "simdjson/fallback/begin.h"
|
||||
#include "simdjson/generic/singlestage/amalgamated.h"
|
||||
#include "simdjson/fallback/end.h"
|
||||
|
||||
#endif // SIMDJSON_FALLBACK_SINGLESTAGE_H
|
||||
@@ -1,10 +1,12 @@
|
||||
#ifndef SIMDJSON_FALLBACK_STRINGPARSING_DEFS_H
|
||||
#define SIMDJSON_FALLBACK_STRINGPARSING_DEFS_H
|
||||
|
||||
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
#include "simdjson/fallback/base.h"
|
||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
namespace simdjson {
|
||||
namespace SIMDJSON_IMPLEMENTATION {
|
||||
namespace fallback {
|
||||
namespace {
|
||||
|
||||
// Holds backslashes and quotes locations.
|
||||
@@ -28,7 +30,7 @@ simdjson_inline backslash_and_quote backslash_and_quote::copy_and_find(const uin
|
||||
}
|
||||
|
||||
} // unnamed namespace
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
} // namespace fallback
|
||||
} // namespace simdjson
|
||||
|
||||
#endif // SIMDJSON_FALLBACK_STRINGPARSING_DEFS_H
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#if defined(SIMDJSON_AMALGAMATED) && !defined(SIMDJSON_GENERIC_DEPENDENCIES_H)
|
||||
#if defined(SIMDJSON_CONDITIONAL_INCLUDE) && !defined(SIMDJSON_GENERIC_DEPENDENCIES_H)
|
||||
#error simdjson/generic/dependencies.h must be included before simdjson/generic/amalgamated.h!
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
#ifndef SIMDJSON_GENERIC_ATOMPARSING_H
|
||||
|
||||
#ifndef SIMDJSON_AMALGAMATED
|
||||
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
#define SIMDJSON_GENERIC_ATOMPARSING_H
|
||||
#include "simdjson/generic/base.h"
|
||||
#include "simdjson/generic/jsoncharutils.h"
|
||||
#endif // SIMDJSON_AMALGAMATED
|
||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace simdjson {
|
||||
namespace SIMDJSON_IMPLEMENTATION {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#ifndef SIMDJSON_GENERIC_BASE_H
|
||||
|
||||
#ifndef SIMDJSON_AMALGAMATED
|
||||
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
#define SIMDJSON_GENERIC_BASE_H
|
||||
#include "simdjson/base.h"
|
||||
// If we haven't got an implementation yet, we're in the editor, editing a generic file! Just
|
||||
@@ -23,7 +23,7 @@
|
||||
#error "All possible implementations (including fallback) have been disabled! simdjson will not run."
|
||||
#endif
|
||||
#endif // SIMDJSON_IMPLEMENTATION
|
||||
#endif // SIMDJSON_AMALGAMATED
|
||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
namespace simdjson {
|
||||
namespace SIMDJSON_IMPLEMENTATION {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#ifdef SIMDJSON_AMALGAMATED
|
||||
#error simdjson/generic/dependencies.h must be included before defining SIMDJSON_AMALGAMATED!
|
||||
#ifdef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
#error simdjson/generic/dependencies.h must be included before defining SIMDJSON_CONDITIONAL_INCLUDE!
|
||||
#endif
|
||||
|
||||
#ifndef SIMDJSON_GENERIC_DEPENDENCIES_H
|
||||
@@ -10,6 +10,7 @@
|
||||
// Otherwise, amalgamation will fail.
|
||||
#include "simdjson/base.h"
|
||||
#include "simdjson/implementation.h"
|
||||
#include "simdjson/implementation_detection.h"
|
||||
#include "simdjson/internal/instruction_set.h"
|
||||
#include "simdjson/internal/dom_parser_implementation.h"
|
||||
#include "simdjson/internal/jsoncharutils_tables.h"
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#ifndef SIMDJSON_GENERIC_DOM_PARSER_IMPLEMENTATION_H
|
||||
|
||||
#ifndef SIMDJSON_AMALGAMATED
|
||||
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
#define SIMDJSON_GENERIC_DOM_PARSER_IMPLEMENTATION_H
|
||||
#include "simdjson/generic/base.h"
|
||||
#include "simdjson/internal/dom_parser_implementation.h"
|
||||
#endif // SIMDJSON_AMALGAMATED
|
||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
namespace simdjson {
|
||||
namespace SIMDJSON_IMPLEMENTATION {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#ifndef SIMDJSON_GENERIC_IMPLEMENTATION_SIMDJSON_RESULT_BASE_INL_H
|
||||
|
||||
#ifndef SIMDJSON_AMALGAMATED
|
||||
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
#define SIMDJSON_GENERIC_IMPLEMENTATION_SIMDJSON_RESULT_BASE_INL_H
|
||||
#include "simdjson/generic/base.h"
|
||||
#include "simdjson/generic/implementation_simdjson_result_base.h"
|
||||
#endif // SIMDJSON_AMALGAMATED
|
||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
namespace simdjson {
|
||||
namespace SIMDJSON_IMPLEMENTATION {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#ifndef SIMDJSON_GENERIC_IMPLEMENTATION_SIMDJSON_RESULT_BASE_H
|
||||
|
||||
#ifndef SIMDJSON_AMALGAMATED
|
||||
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
#define SIMDJSON_GENERIC_IMPLEMENTATION_SIMDJSON_RESULT_BASE_H
|
||||
#include "simdjson/generic/base.h"
|
||||
#endif // SIMDJSON_AMALGAMATED
|
||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
namespace simdjson {
|
||||
namespace SIMDJSON_IMPLEMENTATION {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
#ifndef SIMDJSON_GENERIC_JSONCHARUTILS_H
|
||||
|
||||
#ifndef SIMDJSON_AMALGAMATED
|
||||
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
#define SIMDJSON_GENERIC_JSONCHARUTILS_H
|
||||
#include "simdjson/generic/base.h"
|
||||
#include "simdjson/internal/jsoncharutils_tables.h"
|
||||
#include "simdjson/internal/numberparsing_tables.h"
|
||||
#endif // SIMDJSON_AMALGAMATED
|
||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
namespace simdjson {
|
||||
namespace SIMDJSON_IMPLEMENTATION {
|
||||
@@ -96,16 +96,6 @@ static simdjson_inline uint64_t _umul128(uint64_t ab, uint64_t cd, uint64_t *hi)
|
||||
}
|
||||
#endif
|
||||
|
||||
inline std::string_view trim(const std::string_view str) noexcept {
|
||||
// We can almost surely do better by rolling our own find_first_not_of function.
|
||||
size_t first = str.find_first_not_of(" \t\n\r");
|
||||
// If we have the empty string (just white space), then no trimming is possible, and
|
||||
// we return the empty string_view.
|
||||
if (std::string_view::npos == first) { return std::string_view(); }
|
||||
size_t last = str.find_last_not_of(" \t\n\r");
|
||||
return str.substr(first, (last - first + 1));
|
||||
}
|
||||
|
||||
} // namespace jsoncharutils
|
||||
} // unnamed namespace
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
|
||||
@@ -0,0 +1,303 @@
|
||||
#ifndef SIMDJSON_GENERIC_SIMD_LOOKUP_TABLE_H
|
||||
|
||||
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
#define SIMDJSON_GENERIC_SIMD_LOOKUP_TABLE_H
|
||||
#include "simdjson/generic/base.h"
|
||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
namespace simdjson {
|
||||
namespace SIMDJSON_IMPLEMENTATION {
|
||||
namespace simd {
|
||||
|
||||
template <typename T = uint8_t>
|
||||
struct simd8_buffer {
|
||||
T buf[simd8<T>::LANES] = {0};
|
||||
simdjson_consteval T& operator[](size_t i) noexcept { return buf[i]; }
|
||||
simdjson_consteval T operator[](size_t i) const noexcept { return buf[i]; }
|
||||
simdjson_inline operator simd8<T>() const noexcept { return buf; }
|
||||
};
|
||||
|
||||
|
||||
struct nibble_range;
|
||||
|
||||
struct byte_range {
|
||||
struct _exclusive{};
|
||||
static simdjson_constinit _exclusive exclusive{};
|
||||
|
||||
simdjson_consteval byte_range(uint8_t start, uint16_t end, const _exclusive&) noexcept : _start{start}, _end{end} {
|
||||
SIMDJSON_ASSUME(start < end && end <= 256);
|
||||
}
|
||||
simdjson_consteval byte_range(uint8_t first, uint8_t last) noexcept : byte_range(first, static_cast<uint16_t>(last+1), exclusive) {}
|
||||
simdjson_consteval byte_range(uint8_t first) noexcept : byte_range(first, first) {}
|
||||
|
||||
simdjson_consteval size_t size() const noexcept { return static_cast<size_t>(_end - _start); }
|
||||
simdjson_consteval byte_range operator|(const byte_range& other) const noexcept {
|
||||
SIMDJSON_ASSUME((_end + 1 >= other._start) || (other._end + 1 >= _start));
|
||||
return {std::min(_start, other._start), std::max(_end, other._end), exclusive};
|
||||
}
|
||||
|
||||
simdjson_consteval bool includes(uint8_t byte) const noexcept { return _start <= byte && byte < _end; }
|
||||
|
||||
struct nibble_iter {
|
||||
int nibble;
|
||||
const int last_nibble;
|
||||
simdjson_consteval nibble_iter& operator++() noexcept {
|
||||
if (nibble == last_nibble) {
|
||||
nibble = -1;
|
||||
} else {
|
||||
++nibble;
|
||||
nibble %= 16;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
simdjson_consteval nibble_iter operator++(int) noexcept { auto copy = *this; ++*this; return copy; }
|
||||
simdjson_consteval bool operator==(const nibble_iter& other) const noexcept { return nibble == other.nibble; }
|
||||
simdjson_consteval bool operator!=(const nibble_iter& other) const noexcept { return nibble != other.nibble; }
|
||||
simdjson_consteval uint8_t operator*() const noexcept { return static_cast<uint8_t>(nibble); }
|
||||
simdjson_consteval nibble_iter begin() const noexcept { return *this; }
|
||||
simdjson_consteval nibble_iter end() const noexcept { return {-1, last_nibble}; }
|
||||
};
|
||||
|
||||
simdjson_consteval nibble_iter nibble(int shift) const noexcept {
|
||||
SIMDJSON_ASSUME(_start < _end);
|
||||
auto first_nibble = _start >> shift;
|
||||
auto last_nibble = (_end-1) >> shift;
|
||||
if ((last_nibble - first_nibble) >= 16) { return {0x00, 0x0F}; }
|
||||
return {static_cast<uint8_t>(first_nibble & 0x0F), static_cast<uint8_t>(last_nibble & 0x0F)};
|
||||
}
|
||||
|
||||
struct _iter {
|
||||
uint16_t value;
|
||||
simdjson_consteval _iter& operator++() noexcept { ++value; return *this; }
|
||||
simdjson_consteval _iter operator++(int) noexcept { auto copy = *this; ++*this; return copy; }
|
||||
simdjson_consteval bool operator==(const _iter& other) const noexcept { return value == other.value; }
|
||||
simdjson_consteval bool operator!=(const _iter& other) const noexcept { return value != other.value; }
|
||||
simdjson_consteval uint8_t operator*() const noexcept { return static_cast<uint8_t>(value); }
|
||||
};
|
||||
|
||||
simdjson_consteval _iter begin() const noexcept { return _iter{_start}; }
|
||||
simdjson_consteval _iter end() const noexcept { return _iter{_end}; }
|
||||
|
||||
uint8_t _start;
|
||||
const uint16_t _end;
|
||||
};
|
||||
|
||||
namespace {
|
||||
|
||||
struct _lookup_entry_range;
|
||||
|
||||
struct _lookup_entry : byte_range {
|
||||
const uint8_t value;
|
||||
|
||||
simdjson_consteval _lookup_entry(const byte_range& bytes, uint8_t value) noexcept
|
||||
: byte_range{bytes}, value{value} {}
|
||||
};
|
||||
|
||||
simdjson_consteval simd8_buffer<uint8_t> _make_nibble_lookup_table(
|
||||
std::initializer_list<_lookup_entry> entries, int shift) noexcept {
|
||||
// Make the buffer
|
||||
simd8_buffer<uint8_t> buf;
|
||||
for (auto entry : entries) {
|
||||
for (auto key : entry.nibble(shift)) {
|
||||
// Repeat the value over and over for longer simd types.
|
||||
for (uint8_t k = key; k < sizeof(buf); k += 16) { buf[k] |= entry.value; }
|
||||
}
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
} // unnamed namespace
|
||||
|
||||
/**
|
||||
* Byte lookup table where the key is the high 4 bits of the input, and the value is an
|
||||
* arbitrary byte.
|
||||
*
|
||||
* - Unmatched values yield 0.
|
||||
* - Multiple keys may yield the same value.
|
||||
* - Multiple bytes with the same high 4 bits may NOT yield different values.
|
||||
*
|
||||
* ```
|
||||
* enum ops_t : uint8_t {
|
||||
* COMMA = 1,
|
||||
* COLON = 2,
|
||||
* BRACKET = 3,
|
||||
* CURLY = 4
|
||||
* };
|
||||
* static constinit const high_nibble_lookup OPS(
|
||||
* {',', COMMA},
|
||||
* {':', COLON},
|
||||
* {'[', BRACKET},
|
||||
* {']', BRACKET},
|
||||
* {'{', CURLY},
|
||||
* {'}', CURLY}
|
||||
* );
|
||||
* simd8<uint8_t> lookup_ops(simd8<uint8_t>& operators) { return OPS[operators]; }
|
||||
* ```
|
||||
*/
|
||||
struct high_nibble_lookup {
|
||||
const simd8_buffer<uint8_t> table;
|
||||
|
||||
/**
|
||||
* Construct a nibble lookup table from the high bits of the input to the output.
|
||||
*
|
||||
* @param entries A list of {key, value} pairs (e.g. {'a', 10}).
|
||||
* @error asserts if multiple keys have the same high 4 bits but different values.
|
||||
*/
|
||||
simdjson_consteval high_nibble_lookup(std::initializer_list<_lookup_entry> entries) noexcept
|
||||
: table{_make_nibble_lookup_table(entries, 4)} {}
|
||||
simdjson_consteval high_nibble_lookup(const simd8_buffer<uint8_t>& table) noexcept : table(table) {}
|
||||
|
||||
/** Look up the value corresponding the higher 4 bits of each input byte, and return it. */
|
||||
simdjson_inline simd8<uint8_t> operator[](const simd8<uint8_t>& keys) const noexcept { return lookup(keys); }
|
||||
/** Look up the value corresponding the higher 4 bits of each input byte, and return it. */
|
||||
simdjson_inline simd8<uint8_t> lookup(const simd8<uint8_t>& keys) const noexcept { return lookup_low(keys.shr<4>()); }
|
||||
/**
|
||||
* Look up the value in the table assuming the high 4 key bits are stored in the lower 4 bits.
|
||||
* @pre all indexes be less than 16.
|
||||
*/
|
||||
simdjson_inline simd8<uint8_t> lookup_low(const simd8<uint8_t>& shifted_keys) const noexcept {
|
||||
return shifted_keys.lookup_16(table);
|
||||
}
|
||||
|
||||
/**
|
||||
* Look up the value in the table assuming the high 4 key bits are stored in the lower 4 bits.
|
||||
* @pre all indexes be less than 16.
|
||||
*/
|
||||
simdjson_inline simd8x64<uint8_t> lookup_low(const simd8x64<uint8_t>& shifted_keys) const noexcept {
|
||||
return shifted_keys.lookup_16(table);
|
||||
}
|
||||
/** Look up the value corresponding the higher 4 bits of each input byte, and return it. */
|
||||
simdjson_inline simd8x64<uint8_t> lookup(const simd8x64<uint8_t>& keys) const noexcept { return lookup_low(keys.shr<4>()); }
|
||||
/** Look up the value corresponding the higher 4 bits of each input byte, and return it. */
|
||||
simdjson_inline simd8x64<uint8_t> operator[](const simd8x64<uint8_t>& keys) const noexcept { return lookup(keys); }
|
||||
|
||||
simdjson_consteval uint8_t operator[](uint8_t key) const noexcept { return lookup(key); }
|
||||
simdjson_consteval uint8_t lookup(uint8_t key) const noexcept { return table[key >> 4]; }
|
||||
};
|
||||
|
||||
/**
|
||||
* Byte lookup table where the key is the low 4 bits of the input, and the value is an
|
||||
* arbitrary byte.
|
||||
*
|
||||
* - Unmatched values yield 0.
|
||||
* - Multiple keys may yield the same value.
|
||||
* - Multiple bytes with the same low 4 bits may NOT yield different values.
|
||||
*
|
||||
* ```
|
||||
* enum ops_t : uint8_t {
|
||||
* COMMA = 1,
|
||||
* COLON = 2,
|
||||
* BRACKET = 3,
|
||||
* CURLY = 4
|
||||
* };
|
||||
* static constinit const high_nibble_lookup OPS(
|
||||
* {',', COMMA},
|
||||
* {':', COLON},
|
||||
* {'[', BRACKET},
|
||||
* {']', BRACKET},
|
||||
* {'{', CURLY},
|
||||
* {'}', CURLY}
|
||||
* );
|
||||
* simd8<uint8_t> lookup_ops(simd8<uint8_t>& operators) { return OPS[operators]; }
|
||||
* ```
|
||||
*/
|
||||
struct low_nibble_lookup {
|
||||
const simd8_buffer<uint8_t> table;
|
||||
|
||||
/**
|
||||
* Construct a nibble lookup table from the low bits of the input to the output.
|
||||
*
|
||||
* @param entries A list of {key, value} pairs (e.g. {'a', 0}).
|
||||
* @error asserts if multiple keys have the same low 4 bits but different values.
|
||||
*/
|
||||
simdjson_consteval low_nibble_lookup(std::initializer_list<_lookup_entry> entries) noexcept
|
||||
: table{_make_nibble_lookup_table(entries, 0)} {}
|
||||
simdjson_consteval low_nibble_lookup(const simd8_buffer<uint8_t>& table) noexcept : table(table) {}
|
||||
|
||||
/** Look up the value corresponding the lower 4 bits of each input byte, and return it. */
|
||||
simdjson_inline simd8<uint8_t> operator[](const simd8<uint8_t>& keys) const noexcept { return lookup(keys); }
|
||||
/** Look up the value corresponding the lower 4 bits of each input byte, and return it. */
|
||||
simdjson_inline simd8<uint8_t> lookup(const simd8<uint8_t>& keys) const noexcept {
|
||||
return keys.lookup_low_nibble_ascii(table);
|
||||
}
|
||||
/**
|
||||
* Look up the value in the table. Behavior is system-dependent for indexes greater than 16.
|
||||
*
|
||||
* - On some platforms like arm64, indexes greater than 16 will not match anything in the table.
|
||||
* - On platforms like Intel, index bits 4-6 will be ignored, but if the high bit is set, it
|
||||
* will not match anything in the table. greater than 16 will be ignored, *except* if the high bit is 1,
|
||||
*/
|
||||
simdjson_inline simd8<uint8_t> lookup_unsafe(const simd8<uint8_t>& keys) const noexcept {
|
||||
return keys.lookup_16(table);
|
||||
}
|
||||
|
||||
/** Look up the value corresponding the lower 4 bits of each input byte, and return it. */
|
||||
simdjson_inline simd8x64<uint8_t> operator[](const simd8x64<uint8_t>& keys) const noexcept { return lookup(keys); }
|
||||
/** Look up the value corresponding the lower 4 bits of each input byte, and return it. */
|
||||
simdjson_inline simd8x64<uint8_t> lookup(const simd8x64<uint8_t>& keys) const noexcept {
|
||||
return keys.lookup_low_nibble_ascii(table);
|
||||
}
|
||||
/**
|
||||
* Look up the value in the table. Behavior is system-dependent for indexes greater than 16.
|
||||
*
|
||||
* - On some platforms like arm64, indexes greater than 16 will not match anything in the table.
|
||||
* - On platforms like Intel, index bits 4-6 will be ignored, but if the high bit is set, it
|
||||
* will not match anything in the table. greater than 16 will be ignored, *except* if the high bit is 1,
|
||||
*/
|
||||
simdjson_inline simd8x64<uint8_t> lookup_unsafe(const simd8x64<uint8_t>& low_keys) const noexcept {
|
||||
return low_keys.lookup_16(table);
|
||||
}
|
||||
|
||||
simdjson_consteval uint8_t operator[](uint8_t key) const noexcept { return lookup(key); }
|
||||
simdjson_consteval uint8_t lookup(uint8_t key) const noexcept { return table[key & 0x0F]; }
|
||||
};
|
||||
|
||||
/**
|
||||
* Classifies bytes by looking up their lower 4 bits, then their high 4 bits, and &'ing the
|
||||
* results together.
|
||||
*
|
||||
* Pass the bytes you want to match, and the classifications you want for them.
|
||||
*/
|
||||
struct byte_classifier {
|
||||
const low_nibble_lookup low;
|
||||
const high_nibble_lookup high;
|
||||
simdjson_consteval byte_classifier(std::initializer_list<_lookup_entry> entries)
|
||||
: low{entries}, high{entries} {}
|
||||
|
||||
simdjson_inline simd8<uint8_t> classify(const simd8<uint8_t>& bytes) const noexcept {
|
||||
return low.lookup(bytes) & high.lookup(bytes);
|
||||
}
|
||||
simdjson_inline simd8x64<uint8_t> classify(const simd8x64<uint8_t>& bytes) const noexcept {
|
||||
auto low_lookup = low.lookup(bytes); // 3 (+simd:N)
|
||||
auto high_lookup = high.lookup(bytes); // 6 (+simd:2N)
|
||||
return low_lookup & high_lookup; // 3 (+simd:N)
|
||||
// critical path: 9 (+simd:4N)
|
||||
}
|
||||
simdjson_consteval uint8_t classify(uint8_t byte) const noexcept {
|
||||
return low.lookup(byte) & high.lookup(byte);
|
||||
}
|
||||
|
||||
simdjson_inline simd8<uint8_t> operator[](const simd8<uint8_t>& bytes) const noexcept { return classify(bytes); }
|
||||
simdjson_inline simd8x64<uint8_t> operator[](const simd8x64<uint8_t>& bytes) const noexcept { return classify(bytes); }
|
||||
simdjson_consteval uint8_t operator[](uint8_t byte) const noexcept { return classify(byte); }
|
||||
|
||||
simdjson_inline bool matches_correctly(std::initializer_list<_lookup_entry> entries) const noexcept {
|
||||
uint8_t expected_output[256] = {};
|
||||
for (auto entry : entries) {
|
||||
for (uint8_t byte : entry) {
|
||||
expected_output[byte] |= entry.value;
|
||||
}
|
||||
}
|
||||
for (uint8_t byte = 0; byte <= 0xFF; byte++) {
|
||||
if (expected_output[byte] != classify(byte)) { return false; }
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace simd
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
} // namespace simdjson
|
||||
|
||||
#endif // SIMDJSON_GENERIC_SIMD_LOOKUP_TABLE_H
|
||||
@@ -1,14 +1,15 @@
|
||||
#ifndef SIMDJSON_GENERIC_NUMBERPARSING_H
|
||||
|
||||
#ifndef SIMDJSON_AMALGAMATED
|
||||
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
#define SIMDJSON_GENERIC_NUMBERPARSING_H
|
||||
#include "simdjson/generic/base.h"
|
||||
#include "simdjson/generic/jsoncharutils.h"
|
||||
#include "simdjson/internal/numberparsing_tables.h"
|
||||
#endif // SIMDJSON_AMALGAMATED
|
||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
#include <limits>
|
||||
#include <ostream>
|
||||
#include <cstring>
|
||||
|
||||
namespace simdjson {
|
||||
namespace SIMDJSON_IMPLEMENTATION {
|
||||
@@ -142,7 +143,7 @@ simdjson_inline bool compute_float_64(int64_t power, uint64_t i, bool negative,
|
||||
|
||||
|
||||
// We want the most significant bit of i to be 1. Shift if needed.
|
||||
int lz = leading_zeroes(i);
|
||||
int lz = bitmask::leading_zeroes(i);
|
||||
i <<= lz;
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#if defined(SIMDJSON_AMALGAMATED) && !defined(SIMDJSON_GENERIC_ONDEMAND_DEPENDENCIES_H)
|
||||
#if defined(SIMDJSON_CONDITIONAL_INCLUDE) && !defined(SIMDJSON_GENERIC_ONDEMAND_DEPENDENCIES_H)
|
||||
#error simdjson/generic/ondemand/dependencies.h must be included before simdjson/generic/ondemand/amalgamated.h!
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#ifndef SIMDJSON_GENERIC_ONDEMAND_ARRAY_INL_H
|
||||
|
||||
#ifndef SIMDJSON_AMALGAMATED
|
||||
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
#define SIMDJSON_GENERIC_ONDEMAND_ARRAY_INL_H
|
||||
#include "simdjson/generic/ondemand/base.h"
|
||||
#include "simdjson/generic/ondemand/array.h"
|
||||
@@ -8,7 +8,7 @@
|
||||
#include "simdjson/generic/ondemand/json_iterator.h"
|
||||
#include "simdjson/generic/ondemand/value.h"
|
||||
#include "simdjson/generic/ondemand/value_iterator-inl.h"
|
||||
#endif // SIMDJSON_AMALGAMATED
|
||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
namespace simdjson {
|
||||
namespace SIMDJSON_IMPLEMENTATION {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
#ifndef SIMDJSON_GENERIC_ONDEMAND_ARRAY_H
|
||||
|
||||
#ifndef SIMDJSON_AMALGAMATED
|
||||
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
#define SIMDJSON_GENERIC_ONDEMAND_ARRAY_H
|
||||
#include "simdjson/generic/ondemand/base.h"
|
||||
#include "simdjson/generic/implementation_simdjson_result_base.h"
|
||||
#include "simdjson/generic/ondemand/value_iterator.h"
|
||||
#endif // SIMDJSON_AMALGAMATED
|
||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
namespace simdjson {
|
||||
namespace SIMDJSON_IMPLEMENTATION {
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
#ifndef SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_INL_H
|
||||
|
||||
#ifndef SIMDJSON_AMALGAMATED
|
||||
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
#define SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_INL_H
|
||||
#include "simdjson/generic/ondemand/base.h"
|
||||
#include "simdjson/generic/ondemand/array_iterator.h"
|
||||
#include "simdjson/generic/ondemand/value-inl.h"
|
||||
#include "simdjson/generic/ondemand/value_iterator-inl.h"
|
||||
#endif // SIMDJSON_AMALGAMATED
|
||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
namespace simdjson {
|
||||
namespace SIMDJSON_IMPLEMENTATION {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
#ifndef SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_H
|
||||
|
||||
#ifndef SIMDJSON_AMALGAMATED
|
||||
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
#define SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_H
|
||||
#include "simdjson/generic/implementation_simdjson_result_base.h"
|
||||
#include "simdjson/generic/ondemand/base.h"
|
||||
#include "simdjson/generic/ondemand/value_iterator.h"
|
||||
#endif // SIMDJSON_AMALGAMATED
|
||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
|
||||
namespace simdjson {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#ifndef SIMDJSON_GENERIC_ONDEMAND_BASE_H
|
||||
|
||||
#ifndef SIMDJSON_AMALGAMATED
|
||||
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
#define SIMDJSON_GENERIC_ONDEMAND_BASE_H
|
||||
#include "simdjson/generic/base.h"
|
||||
#endif // SIMDJSON_AMALGAMATED
|
||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
namespace simdjson {
|
||||
namespace SIMDJSON_IMPLEMENTATION {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#ifdef SIMDJSON_AMALGAMATED
|
||||
#error simdjson/generic/ondemand/dependencies.h must be included before defining SIMDJSON_AMALGAMATED!
|
||||
#ifdef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
#error simdjson/generic/ondemand/dependencies.h must be included before defining SIMDJSON_CONDITIONAL_INCLUDE!
|
||||
#endif
|
||||
|
||||
#ifndef SIMDJSON_GENERIC_ONDEMAND_DEPENDENCIES_H
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#ifndef SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_INL_H
|
||||
|
||||
#ifndef SIMDJSON_AMALGAMATED
|
||||
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
#define SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_INL_H
|
||||
#include "simdjson/generic/ondemand/base.h"
|
||||
#include "simdjson/generic/ondemand/array-inl.h"
|
||||
@@ -12,7 +12,7 @@
|
||||
#include "simdjson/generic/ondemand/raw_json_string.h"
|
||||
#include "simdjson/generic/ondemand/value.h"
|
||||
#include "simdjson/generic/ondemand/value_iterator-inl.h"
|
||||
#endif // SIMDJSON_AMALGAMATED
|
||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
namespace simdjson {
|
||||
namespace SIMDJSON_IMPLEMENTATION {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#ifndef SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_H
|
||||
|
||||
#ifndef SIMDJSON_AMALGAMATED
|
||||
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
#define SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_H
|
||||
#include "simdjson/generic/ondemand/base.h"
|
||||
#include "simdjson/generic/ondemand/json_iterator.h"
|
||||
#endif // SIMDJSON_AMALGAMATED
|
||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
namespace simdjson {
|
||||
namespace SIMDJSON_IMPLEMENTATION {
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
#ifndef SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_STREAM_INL_H
|
||||
|
||||
#ifndef SIMDJSON_AMALGAMATED
|
||||
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
#define SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_STREAM_INL_H
|
||||
#include "simdjson/generic/ondemand/base.h"
|
||||
#include "simdjson/generic/ondemand/document_stream.h"
|
||||
#include "simdjson/generic/ondemand/document-inl.h"
|
||||
#include "simdjson/generic/implementation_simdjson_result_base-inl.h"
|
||||
#endif // SIMDJSON_AMALGAMATED
|
||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
#ifndef SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_STREAM_H
|
||||
|
||||
#ifndef SIMDJSON_AMALGAMATED
|
||||
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
#define SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_STREAM_H
|
||||
#include "simdjson/generic/ondemand/base.h"
|
||||
#include "simdjson/generic/implementation_simdjson_result_base.h"
|
||||
#include "simdjson/generic/ondemand/document.h"
|
||||
#include "simdjson/generic/ondemand/parser.h"
|
||||
#endif // SIMDJSON_AMALGAMATED
|
||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
#ifdef SIMDJSON_THREADS_ENABLED
|
||||
#include <thread>
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
#ifndef SIMDJSON_GENERIC_ONDEMAND_FIELD_INL_H
|
||||
|
||||
#ifndef SIMDJSON_AMALGAMATED
|
||||
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
#define SIMDJSON_GENERIC_ONDEMAND_FIELD_INL_H
|
||||
#include "simdjson/generic/ondemand/base.h"
|
||||
#include "simdjson/generic/ondemand/field.h"
|
||||
#include "simdjson/generic/ondemand/value-inl.h"
|
||||
#include "simdjson/generic/ondemand/value_iterator-inl.h"
|
||||
#endif // SIMDJSON_AMALGAMATED
|
||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
namespace simdjson {
|
||||
namespace SIMDJSON_IMPLEMENTATION {
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
#ifndef SIMDJSON_GENERIC_ONDEMAND_FIELD_H
|
||||
|
||||
#ifndef SIMDJSON_AMALGAMATED
|
||||
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
#define SIMDJSON_GENERIC_ONDEMAND_FIELD_H
|
||||
#include "simdjson/generic/ondemand/base.h"
|
||||
#include "simdjson/generic/implementation_simdjson_result_base.h"
|
||||
#include "simdjson/generic/ondemand/raw_json_string.h"
|
||||
#include "simdjson/generic/ondemand/value.h"
|
||||
#endif // SIMDJSON_AMALGAMATED
|
||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
namespace simdjson {
|
||||
namespace SIMDJSON_IMPLEMENTATION {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#ifndef SIMDJSON_GENERIC_ONDEMAND_JSON_ITERATOR_INL_H
|
||||
|
||||
#ifndef SIMDJSON_AMALGAMATED
|
||||
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
#define SIMDJSON_GENERIC_ONDEMAND_JSON_ITERATOR_INL_H
|
||||
#include "simdjson/internal/dom_parser_implementation.h"
|
||||
#include "simdjson/generic/ondemand/base.h"
|
||||
@@ -10,7 +10,7 @@
|
||||
#include "simdjson/generic/ondemand/logger-inl.h"
|
||||
#include "simdjson/generic/ondemand/parser-inl.h"
|
||||
#include "simdjson/generic/ondemand/token_iterator-inl.h"
|
||||
#endif // SIMDJSON_AMALGAMATED
|
||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
namespace simdjson {
|
||||
namespace SIMDJSON_IMPLEMENTATION {
|
||||
@@ -101,10 +101,6 @@ simdjson_warn_unused simdjson_inline error_code json_iterator::skip_child(depth_
|
||||
case '[': case '{': case ':':
|
||||
logger::log_start_value(*this, "skip");
|
||||
break;
|
||||
// If there is a comma, we have just finished a value in an array/object, and need to get back in
|
||||
case ',':
|
||||
logger::log_value(*this, "skip");
|
||||
break;
|
||||
// ] or } means we just finished a value and need to jump out of the array/object
|
||||
case ']': case '}':
|
||||
logger::log_end_value(*this, "skip");
|
||||
@@ -254,7 +250,7 @@ simdjson_inline const uint8_t *json_iterator::return_current_and_advance() noexc
|
||||
|
||||
simdjson_inline const uint8_t *json_iterator::unsafe_pointer() const noexcept {
|
||||
// deliberately done without safety guard:
|
||||
return token.peek(0);
|
||||
return token.peek();
|
||||
}
|
||||
|
||||
simdjson_inline const uint8_t *json_iterator::peek(int32_t delta) const noexcept {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
#ifndef SIMDJSON_GENERIC_ONDEMAND_JSON_ITERATOR_H
|
||||
|
||||
#ifndef SIMDJSON_AMALGAMATED
|
||||
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
#define SIMDJSON_GENERIC_ONDEMAND_JSON_ITERATOR_H
|
||||
#include "simdjson/generic/ondemand/base.h"
|
||||
#include "simdjson/generic/implementation_simdjson_result_base.h"
|
||||
#include "simdjson/generic/ondemand/token_iterator.h"
|
||||
#endif // SIMDJSON_AMALGAMATED
|
||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
namespace simdjson {
|
||||
namespace SIMDJSON_IMPLEMENTATION {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user