mirror of
https://github.com/simdjson/simdjson
synced 2026-06-08 17:27:07 +00:00
Compare commits
33 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f1bfa43385 | |||
| 29fbbee852 | |||
| baa7d961ce | |||
| 6412b27c7e | |||
| 503da5ec83 | |||
| 9dd6e9c959 | |||
| 6db330c1a2 | |||
| 993ac4b87c | |||
| 35e87896f0 | |||
| f7e281cadc | |||
| 13405afd4b | |||
| 24b44309fb | |||
| e11ad58aad | |||
| 1875ed6550 | |||
| 80d26298a0 | |||
| 25b5015c09 | |||
| 26f8c566c7 | |||
| ff77ac801e | |||
| e0699994ef | |||
| 68ba9a1b2a | |||
| 6fed6bd29b | |||
| cc24bb4114 | |||
| 14ec0ca8f4 | |||
| 8dabd02c3a | |||
| c9692005fd | |||
| 2e0a9397c9 | |||
| f7922075c3 | |||
| b2e20e04c9 | |||
| adc9d18efd | |||
| bf849e3619 | |||
| c09e8dc225 | |||
| 5bf585ef02 | |||
| caff09cafc |
@@ -31,7 +31,7 @@ A clear and concise description of any alternative solutions or features you've
|
|||||||
**Additional context**
|
**Additional context**
|
||||||
Add any other context or screenshots about the feature request here.
|
Add any other context or screenshots about the feature request here.
|
||||||
|
|
||||||
** Are you willing to contribute code or documentation toward this new feature? **
|
**Are you willing to contribute code or documentation toward this new feature?**
|
||||||
If you plan to contribute to simdjson, please read our
|
If you plan to contribute to simdjson, please read our
|
||||||
* CONTRIBUTING guide: https://github.com/simdjson/simdjson/blob/master/CONTRIBUTING.md and our
|
* CONTRIBUTING guide: https://github.com/simdjson/simdjson/blob/master/CONTRIBUTING.md and our
|
||||||
* HACKING guide: https://github.com/simdjson/simdjson/blob/master/HACKING.md
|
* HACKING guide: https://github.com/simdjson/simdjson/blob/master/HACKING.md
|
||||||
|
|||||||
@@ -31,3 +31,14 @@ jobs:
|
|||||||
echo -e '#include <simdjson.h>\nint main(int argc,char**argv) {simdjson::dom::parser parser;simdjson::dom::element tweets = parser.load(argv[1]); }' > tmp.cpp && c++ -Idestination/include -Ldestination/lib -std=c++17 -Wl,-rpath,destination/lib -o linkandrun tmp.cpp -lsimdjson && ./linkandrun jsonexamples/twitter.json &&
|
echo -e '#include <simdjson.h>\nint main(int argc,char**argv) {simdjson::dom::parser parser;simdjson::dom::element tweets = parser.load(argv[1]); }' > tmp.cpp && c++ -Idestination/include -Ldestination/lib -std=c++17 -Wl,-rpath,destination/lib -o linkandrun tmp.cpp -lsimdjson && ./linkandrun jsonexamples/twitter.json &&
|
||||||
cd ../tests/installation_tests/find &&
|
cd ../tests/installation_tests/find &&
|
||||||
mkdir build && cd build && cmake -DCMAKE_INSTALL_PREFIX:PATH=../../../build/destination .. && cmake --build .
|
mkdir build && cd build && cmake -DCMAKE_INSTALL_PREFIX:PATH=../../../build/destination .. && cmake --build .
|
||||||
|
- name: Use cmake (shared)
|
||||||
|
run: |
|
||||||
|
mkdir buildshared &&
|
||||||
|
cd buildshared &&
|
||||||
|
cmake -DSIMDJSON_GOOGLE_BENCHMARKS=ON -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=ON -DCMAKE_INSTALL_PREFIX:PATH=destination .. &&
|
||||||
|
cmake --build . &&
|
||||||
|
ctest --output-on-failure -LE explicitonly -j &&
|
||||||
|
cmake --install . &&
|
||||||
|
echo -e '#include <simdjson.h>\nint main(int argc,char**argv) {simdjson::dom::parser parser;simdjson::dom::element tweets = parser.load(argv[1]); }' > tmp.cpp && c++ -Idestination/include -Ldestination/lib -std=c++17 -Wl,-rpath,destination/lib -o linkandrun tmp.cpp -lsimdjson && ./linkandrun jsonexamples/twitter.json &&
|
||||||
|
cd ../tests/installation_tests/find &&
|
||||||
|
mkdir buildshared && cd buildshared && cmake -DCMAKE_INSTALL_PREFIX:PATH=../../../buildshared/destination .. && cmake --build .
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
path: dependencies/.cache
|
path: dependencies/.cache
|
||||||
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
|
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
|
||||||
ctest --output-on-failure -LE explicitonly -j
|
|
||||||
- name: Use cmake with undefined sanitizer
|
- name: Use cmake with undefined sanitizer
|
||||||
run: |
|
run: |
|
||||||
mkdir builddebugundefsani &&
|
mkdir builddebugundefsani &&
|
||||||
|
|||||||
+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]
|
on: [push, pull_request]
|
||||||
|
|
||||||
@@ -7,7 +7,7 @@ jobs:
|
|||||||
if: >-
|
if: >-
|
||||||
! contains(toJSON(github.event.commits.*.message), '[skip ci]') &&
|
! contains(toJSON(github.event.commits.*.message), '[skip ci]') &&
|
||||||
! contains(toJSON(github.event.commits.*.message), '[skip github]')
|
! contains(toJSON(github.event.commits.*.message), '[skip github]')
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-22.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: actions/cache@v3
|
- uses: actions/cache@v3
|
||||||
+32
-5
@@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.14)
|
|||||||
project(
|
project(
|
||||||
simdjson
|
simdjson
|
||||||
# The version number is modified by tools/release.py
|
# The version number is modified by tools/release.py
|
||||||
VERSION 3.2.2
|
VERSION 3.5.0
|
||||||
DESCRIPTION "Parsing gigabytes of JSON per second"
|
DESCRIPTION "Parsing gigabytes of JSON per second"
|
||||||
HOMEPAGE_URL "https://simdjson.org/"
|
HOMEPAGE_URL "https://simdjson.org/"
|
||||||
LANGUAGES CXX C
|
LANGUAGES CXX C
|
||||||
@@ -20,8 +20,10 @@ string(
|
|||||||
# ---- Options, variables ----
|
# ---- Options, variables ----
|
||||||
|
|
||||||
# These version numbers are modified by tools/release.py
|
# These version numbers are modified by tools/release.py
|
||||||
set(SIMDJSON_LIB_VERSION "16.0.0" CACHE STRING "simdjson library version")
|
set(SIMDJSON_LIB_VERSION "18.0.0" CACHE STRING "simdjson library version")
|
||||||
set(SIMDJSON_LIB_SOVERSION "16" CACHE STRING "simdjson library soversion")
|
set(SIMDJSON_LIB_SOVERSION "18" CACHE STRING "simdjson library soversion")
|
||||||
|
|
||||||
|
option(SIMDJSON_BUILD_STATIC_LIB "Build simdjson_static library along with simdjson" OFF)
|
||||||
|
|
||||||
option(SIMDJSON_ENABLE_THREADS "Link with thread support" ON)
|
option(SIMDJSON_ENABLE_THREADS "Link with thread support" ON)
|
||||||
|
|
||||||
@@ -56,8 +58,17 @@ include(cmake/developer-options.cmake)
|
|||||||
|
|
||||||
# ---- simdjson library ----
|
# ---- simdjson library ----
|
||||||
|
|
||||||
add_library(simdjson src/simdjson.cpp)
|
set(SIMDJSON_SOURCES src/simdjson.cpp)
|
||||||
|
|
||||||
|
add_library(simdjson ${SIMDJSON_SOURCES})
|
||||||
add_library(simdjson::simdjson ALIAS simdjson)
|
add_library(simdjson::simdjson ALIAS simdjson)
|
||||||
|
set(SIMDJSON_LIBRARIES simdjson)
|
||||||
|
|
||||||
|
if(SIMDJSON_BUILD_STATIC_LIB)
|
||||||
|
add_library(simdjson_static STATIC ${SIMDJSON_SOURCES})
|
||||||
|
add_library(simdjson::simdjson_static ALIAS simdjson_static)
|
||||||
|
list(APPEND SIMDJSON_LIBRARIES simdjson_static)
|
||||||
|
endif()
|
||||||
|
|
||||||
set_target_properties(
|
set_target_properties(
|
||||||
simdjson PROPERTIES
|
simdjson PROPERTIES
|
||||||
@@ -117,6 +128,9 @@ if(SIMDJSON_ENABLE_THREADS)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
simdjson_apply_props(simdjson)
|
simdjson_apply_props(simdjson)
|
||||||
|
if(SIMDJSON_BUILD_STATIC_LIB)
|
||||||
|
simdjson_apply_props(simdjson_static)
|
||||||
|
endif()
|
||||||
|
|
||||||
# ---- Install rules ----
|
# ---- Install rules ----
|
||||||
|
|
||||||
@@ -138,7 +152,6 @@ install(
|
|||||||
ARCHIVE COMPONENT simdjson_Development
|
ARCHIVE COMPONENT simdjson_Development
|
||||||
INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
|
INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
|
||||||
)
|
)
|
||||||
|
|
||||||
configure_file(cmake/simdjson-config.cmake.in simdjson-config.cmake @ONLY)
|
configure_file(cmake/simdjson-config.cmake.in simdjson-config.cmake @ONLY)
|
||||||
|
|
||||||
write_basic_package_version_file(
|
write_basic_package_version_file(
|
||||||
@@ -167,6 +180,20 @@ install(
|
|||||||
COMPONENT simdjson_Development
|
COMPONENT simdjson_Development
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if(SIMDJSON_BUILD_STATIC_LIB)
|
||||||
|
install(
|
||||||
|
TARGETS simdjson_static
|
||||||
|
EXPORT simdjson_staticTargets
|
||||||
|
ARCHIVE COMPONENT simdjson_Development
|
||||||
|
)
|
||||||
|
install(
|
||||||
|
EXPORT simdjson_staticTargets
|
||||||
|
NAMESPACE simdjson::
|
||||||
|
DESTINATION "${SIMDJSON_INSTALL_CMAKEDIR}"
|
||||||
|
COMPONENT simdjson_Development
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
# pkg-config
|
# pkg-config
|
||||||
include(cmake/JoinPaths.cmake)
|
include(cmake/JoinPaths.cmake)
|
||||||
join_paths(PKGCONFIG_INCLUDEDIR "\${prefix}" "${CMAKE_INSTALL_INCLUDEDIR}")
|
join_paths(PKGCONFIG_INCLUDEDIR "\${prefix}" "${CMAKE_INSTALL_INCLUDEDIR}")
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ PROJECT_NAME = simdjson
|
|||||||
# could be handy for archiving the generated documentation or if some version
|
# could be handy for archiving the generated documentation or if some version
|
||||||
# control system is used.
|
# control system is used.
|
||||||
|
|
||||||
PROJECT_NUMBER = "3.2.2"
|
PROJECT_NUMBER = "3.5.0"
|
||||||
|
|
||||||
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
||||||
# for a project that appears at the top of each page and should give viewer a
|
# for a project that appears at the top of each page and should give viewer a
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
|
|
||||||
[/badge.svg)](https://simdjson.org/plots.html)
|
[/badge.svg)](https://simdjson.org/plots.html)
|
||||||

|
|
||||||
[](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:simdjson)
|
[](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:simdjson)
|
||||||

|
|
||||||
[![][license img]][license]
|
[![][license img]][license]
|
||||||
|
|
||||||
[](https://simdjson.github.io/simdjson/)
|
[](https://simdjson.github.io/simdjson/)
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
+13
-9
@@ -445,7 +445,7 @@ struct benchmarker {
|
|||||||
return 100.0 * a / b;
|
return 100.0 * a / b;
|
||||||
}
|
}
|
||||||
|
|
||||||
void print(bool tabbed_output) const {
|
void print(bool tabbed_output, bool stage1_only) const {
|
||||||
if (tabbed_output) {
|
if (tabbed_output) {
|
||||||
char* filename_copy = reinterpret_cast<char*>(malloc(strlen(filename)+1));
|
char* filename_copy = reinterpret_cast<char*>(malloc(strlen(filename)+1));
|
||||||
SIMDJSON_PUSH_DISABLE_WARNINGS
|
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));
|
stats->blocks_with_16_structurals_flipped, percent(stats->blocks_with_16_structurals_flipped, stats->blocks));
|
||||||
}
|
}
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf("All Stages (excluding allocation)\n");
|
if(!stage1_only) {
|
||||||
print_aggregate("| " , all_stages_without_allocation.best);
|
printf("All Stages (excluding allocation)\n");
|
||||||
// frequently, allocation is a tiny fraction of the running time so we omit it
|
print_aggregate("| " , all_stages_without_allocation.best);
|
||||||
if(allocate_stage.best.elapsed_sec() > 0.01 * all_stages_without_allocation.best.elapsed_sec()) {
|
// frequently, allocation is a tiny fraction of the running time so we omit it
|
||||||
printf("|- Allocation\n");
|
if(allocate_stage.best.elapsed_sec() > 0.01 * all_stages_without_allocation.best.elapsed_sec()) {
|
||||||
print_aggregate("| ", allocate_stage.best);
|
printf("|- Allocation\n");
|
||||||
|
print_aggregate("| ", allocate_stage.best);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
printf("|- Stage 1\n");
|
printf("|- Stage 1\n");
|
||||||
print_aggregate("| ", stage1.best);
|
print_aggregate("| ", stage1.best);
|
||||||
printf("|- Stage 2\n");
|
if(!stage1_only) {
|
||||||
print_aggregate("| ", stage2.best);
|
printf("|- Stage 2\n");
|
||||||
|
print_aggregate("| ", stage2.best);
|
||||||
|
}
|
||||||
if (collector.has_events()) {
|
if (collector.has_events()) {
|
||||||
double freq1 = (stage1.best.cycles() / stage1.best.elapsed_sec()) / 1000000000.0;
|
double freq1 = (stage1.best.cycles() / stage1.best.elapsed_sec()) / 1000000000.0;
|
||||||
double freq2 = (stage2.best.cycles() / stage2.best.elapsed_sec()) / 1000000000.0;
|
double freq2 = (stage2.best.cycles() / stage2.best.elapsed_sec()) / 1000000000.0;
|
||||||
|
|||||||
@@ -218,7 +218,7 @@ int main(int argc, char *argv[]) {
|
|||||||
if (!options.verbose) { progress.erase(); }
|
if (!options.verbose) { progress.erase(); }
|
||||||
|
|
||||||
for (size_t i=0; i<options.files.size(); i++) {
|
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];
|
delete benchmarkers[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,11 +34,15 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "linux-perf-events.h"
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
|
#include "linux-perf-events.h"
|
||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if __APPLE__ && __aarch64__
|
||||||
|
#include "apple/apple_arm_events.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "simdjson.h"
|
#include "simdjson.h"
|
||||||
|
|
||||||
using std::string;
|
using std::string;
|
||||||
@@ -134,7 +138,7 @@ struct event_collector {
|
|||||||
|
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
LinuxEvents<PERF_TYPE_HARDWARE> linux_events;
|
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
|
#if SIMDJSON_SIMPLE_PERFORMANCE_COUNTERS
|
||||||
PERF_COUNT_HW_CPU_CYCLES,
|
PERF_COUNT_HW_CPU_CYCLES,
|
||||||
PERF_COUNT_HW_INSTRUCTIONS,
|
PERF_COUNT_HW_INSTRUCTIONS,
|
||||||
@@ -149,8 +153,17 @@ struct event_collector {
|
|||||||
bool has_events() {
|
bool has_events() {
|
||||||
return linux_events.is_working();
|
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
|
#else
|
||||||
event_collector(simdjson_unused bool _quiet = false) {}
|
event_collector() {}
|
||||||
bool has_events() {
|
bool has_events() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -159,6 +172,8 @@ struct event_collector {
|
|||||||
simdjson_inline void start() {
|
simdjson_inline void start() {
|
||||||
#if defined(__linux)
|
#if defined(__linux)
|
||||||
linux_events.start();
|
linux_events.start();
|
||||||
|
#elif __APPLE__ && __aarch64__
|
||||||
|
if(has_events()) { diff = apple_events.get_counters(); }
|
||||||
#endif
|
#endif
|
||||||
start_clock = steady_clock::now();
|
start_clock = steady_clock::now();
|
||||||
}
|
}
|
||||||
@@ -166,6 +181,16 @@ struct event_collector {
|
|||||||
time_point<steady_clock> end_clock = steady_clock::now();
|
time_point<steady_clock> end_clock = steady_clock::now();
|
||||||
#if defined(__linux)
|
#if defined(__linux)
|
||||||
linux_events.end(count.event_counts);
|
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
|
#endif
|
||||||
count.elapsed = end_clock - start_clock;
|
count.elapsed = end_clock - start_clock;
|
||||||
return count;
|
return count;
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ void maybe_display_implementation() {
|
|||||||
template<typename B, typename R> static void run_json_benchmark(benchmark::State &state) {
|
template<typename B, typename R> static void run_json_benchmark(benchmark::State &state) {
|
||||||
maybe_display_implementation();
|
maybe_display_implementation();
|
||||||
|
|
||||||
event_collector collector(true);
|
event_collector collector;
|
||||||
event_aggregate events;
|
event_aggregate events;
|
||||||
|
|
||||||
// Warmup and equality check (make sure the data is right!)
|
// Warmup and equality check (make sure the data is right!)
|
||||||
|
|||||||
@@ -114,10 +114,14 @@ set(SIMDJSON_CXX_STANDARD 17 CACHE STRING "the C++ standard to use for simdjson"
|
|||||||
set(CMAKE_CXX_STANDARD ${SIMDJSON_CXX_STANDARD})
|
set(CMAKE_CXX_STANDARD ${SIMDJSON_CXX_STANDARD})
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||||
set(CMAKE_MACOSX_RPATH OFF)
|
|
||||||
set(CMAKE_THREAD_PREFER_PTHREAD ON)
|
set(CMAKE_THREAD_PREFER_PTHREAD ON)
|
||||||
set(THREADS_PREFER_PTHREAD_FLAG 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
|
# LTO seems to create all sorts of fun problems. Let us
|
||||||
# disable temporarily.
|
# disable temporarily.
|
||||||
#include(CheckIPOSupported)
|
#include(CheckIPOSupported)
|
||||||
|
|||||||
@@ -4,3 +4,4 @@ if("@SIMDJSON_ENABLE_THREADS@")
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
include("${CMAKE_CURRENT_LIST_DIR}/simdjsonTargets.cmake")
|
include("${CMAKE_CURRENT_LIST_DIR}/simdjsonTargets.cmake")
|
||||||
|
include("${CMAKE_CURRENT_LIST_DIR}/simdjson_staticTargets.cmake" OPTIONAL)
|
||||||
|
|||||||
+193
-37
@@ -30,6 +30,7 @@ An overview of what you need to know to use simdjson, with examples.
|
|||||||
- [Dynamic Number Types](#dynamic-number-types)
|
- [Dynamic Number Types](#dynamic-number-types)
|
||||||
- [Raw Strings](#raw-strings)
|
- [Raw Strings](#raw-strings)
|
||||||
- [General Direct Access to the Raw JSON String](#general-direct-access-to-the-raw-json-string)
|
- [General Direct Access to the Raw JSON String](#general-direct-access-to-the-raw-json-string)
|
||||||
|
- [Storing Directly into an Existing String Instance](#storing-directly-into-an-existing-string-instance)
|
||||||
- [Thread Safety](#thread-safety)
|
- [Thread Safety](#thread-safety)
|
||||||
- [Standard Compliance](#standard-compliance)
|
- [Standard Compliance](#standard-compliance)
|
||||||
- [Backwards Compatibility](#backwards-compatibility)
|
- [Backwards Compatibility](#backwards-compatibility)
|
||||||
@@ -179,8 +180,8 @@ strcpy(json, "[1]");
|
|||||||
ondemand::document doc = parser.iterate(json, strlen(json), sizeof(json));
|
ondemand::document doc = parser.iterate(json, strlen(json), sizeof(json));
|
||||||
```
|
```
|
||||||
|
|
||||||
The simdjson library will also accept `std::string` instances, as long as the `capacity()` of
|
The simdjson library will also accept `std::string` instances. If the provided
|
||||||
the string exceeds the `size()` by at least `SIMDJSON_PADDING`. You can increase the `capacity()` with the `reserve()` function of your strings.
|
reference is non-const, it will allocate padding as needed.
|
||||||
|
|
||||||
You can copy your data directly on a `simdjson::padded_string` as follows:
|
You can copy your data directly on a `simdjson::padded_string` as follows:
|
||||||
|
|
||||||
@@ -355,7 +356,7 @@ support for users who avoid exceptions. See [the simdjson error handling documen
|
|||||||
* **Field Access:** To get the value of the "foo" field in an object, use `object["foo"]`. This will
|
* **Field Access:** To get the value of the "foo" field in an object, use `object["foo"]`. This will
|
||||||
scan through the object looking for the field with the matching string, doing a character-by-character
|
scan through the object looking for the field with the matching string, doing a character-by-character
|
||||||
comparison. It may generate the error `simdjson::NO_SUCH_FIELD` if there is no such key in the object, it may throw an exception (see [Error Handling](#error-handling)). For efficiency reason, you should avoid looking up the same field repeatedly: e.g., do
|
comparison. It may generate the error `simdjson::NO_SUCH_FIELD` if there is no such key in the object, it may throw an exception (see [Error Handling](#error-handling)). For efficiency reason, you should avoid looking up the same field repeatedly: e.g., do
|
||||||
not do `object["foo"]` followed by `object["foo"]` with the same `object` instance. Keep in mind that On Demand does not buffer or save the result of the parsing: if you repeatedly access `object["foo"]`, then it must repeatedly seek the key and parse the content. The library does not provide a distinct function to check if a key is present, instead we recommend you attempt to access the key: e.g., by doing `ondemand::value val{}; if(!object["foo"].get(val)) {...}`, you have that `val` contains the requested value inside the if clause. It is your responsibility as a user to temporarily keep a reference to the value (`auto v = object["foo"]`), or to consume the content and store it in your own data structures. If you consume an
|
not do `object["foo"]` followed by `object["foo"]` with the same `object` instance. Keep in mind that On Demand does not buffer or save the result of the parsing: if you repeatedly access `object["foo"]`, then it must repeatedly seek the key and parse the content. The library does not provide a distinct function to check if a key is present, instead we recommend you attempt to access the key: e.g., by doing `ondemand::value val{}; if (!object["foo"].get(val)) {...}`, you have that `val` contains the requested value inside the if clause. It is your responsibility as a user to temporarily keep a reference to the value (`auto v = object["foo"]`), or to consume the content and store it in your own data structures. If you consume an
|
||||||
object twice: `std::string_view(object["foo"]` followed by `std::string_view(object["foo"]` then your code
|
object twice: `std::string_view(object["foo"]` followed by `std::string_view(object["foo"]` then your code
|
||||||
is in error. Furthermore, you can only consume one field at a time, on the same object. The
|
is in error. Furthermore, you can only consume one field at a time, on the same object. The
|
||||||
value instance you get from `content["bids"]` becomes invalid when you call `content["asks"]`.
|
value instance you get from `content["bids"]` becomes invalid when you call `content["asks"]`.
|
||||||
@@ -370,7 +371,11 @@ support for users who avoid exceptions. See [the simdjson error handling documen
|
|||||||
> as a key, it will not be recognized. This is not generally a problem. Nevertheless, if you do need
|
> as a key, it will not be recognized. This is not generally a problem. Nevertheless, if you do need
|
||||||
> to support escaped keys, the method `unescaped_key()` provides the desired unescaped keys by
|
> to support escaped keys, the method `unescaped_key()` provides the desired unescaped keys by
|
||||||
> parsing and writing out the unescaped keys to a string buffer and returning a `std::string_view`
|
> parsing and writing out the unescaped keys to a string buffer and returning a `std::string_view`
|
||||||
> instance. You should expect a performance penalty when using `unescaped_key()`.
|
> instance. The `unescaped_key` takes an optional Boolean value: passing it true will decode invalid
|
||||||
|
> Unicode sequences with replacement, meaning that the decoding always succeeds but bogus Unicode
|
||||||
|
> replacement characters are inserted. In general, you should expect a performance penalty
|
||||||
|
> when using `unescaped_key()` compared to `key()` because of the string processing: the `key()`
|
||||||
|
> function just points inside the source JSON document.
|
||||||
>
|
>
|
||||||
> ```c++
|
> ```c++
|
||||||
> auto json = R"({"k\u0065y": 1})"_padded;
|
> auto json = R"({"k\u0065y": 1})"_padded;
|
||||||
@@ -381,7 +386,7 @@ support for users who avoid exceptions. See [the simdjson error handling documen
|
|||||||
> // parses and writes out the key, after unescaping it,
|
> // parses and writes out the key, after unescaping it,
|
||||||
> // to a string buffer. It causes a performance penalty.
|
> // to a string buffer. It causes a performance penalty.
|
||||||
> std::string_view keyv = field.unescaped_key();
|
> std::string_view keyv = field.unescaped_key();
|
||||||
> if(keyv == "key") { std::cout << uint64_t(field.value()); }
|
> if (keyv == "key") { std::cout << uint64_t(field.value()); }
|
||||||
> }
|
> }
|
||||||
> ```
|
> ```
|
||||||
>
|
>
|
||||||
@@ -414,8 +419,10 @@ support for users who avoid exceptions. See [the simdjson error handling documen
|
|||||||
step through each value in the JSON array.
|
step through each value in the JSON array.
|
||||||
|
|
||||||
If you know the type of the value, you can cast it right there, too! `for (double value : array) { ... }`.
|
If you know the type of the value, you can cast it right there, too! `for (double value : array) { ... }`.
|
||||||
* **Object Iteration:** You can iterate through an object's fields, as well: `for (auto field : object) { ... }`
|
|
||||||
- `field.unescaped_key()` will get you the unescaped key string.
|
You may also use explicit iterators: `for(auto i = array.begin(); i != array.end(); i++) {}`. You can check that an array is empty with the condition `auto i = array.begin(); if(i == array.end()) {...}`.
|
||||||
|
* **Object Iteration:** You can iterate through an object's fields, as well: `for (auto field : object) { ... }`. You may also use explicit iterators : `for(auto i = object.begin(); i != object.end(); i++) { auto field = *i; .... }`. You can check that an object is empty with the condition `auto i = object.begin(); if(i == object.end()) {...}`.
|
||||||
|
- `field.unescaped_key()` will get you the unescaped key string. E.g., the JSON string `"\u00e1"` becomes the Unicode string `á`. Optionally, you pass `true` as a parameter to the `unescaped_key` method if you want invalid escape sequences to be replaced by a default replacement character (e.g., `\ud800\ud801\ud811`): otherwise bad escape sequences lead to an immediate error.
|
||||||
- `field.value()` will get you the value, which you can then use all these other methods on.
|
- `field.value()` will get you the value, which you can then use all these other methods on.
|
||||||
* **Array Index:** Because it is forward-only, you cannot look up an array element by index by index. Instead,
|
* **Array Index:** Because it is forward-only, you cannot look up an array element by index by index. Instead,
|
||||||
you should iterate through the array and keep an index yourself.
|
you should iterate through the array and keep an index yourself.
|
||||||
@@ -445,7 +452,7 @@ support for users who avoid exceptions. See [the simdjson error handling documen
|
|||||||
> {
|
> {
|
||||||
> ondemand::parser parser;
|
> ondemand::parser parser;
|
||||||
> for (ondemand::object car : parser.iterate(cars_json)) {
|
> for (ondemand::object car : parser.iterate(cars_json)) {
|
||||||
> if(uint64_t(car["year"]) > 2000) {
|
> if (uint64_t(car["year"]) > 2000) {
|
||||||
> arrays.push_back(simdjson::to_json_string(car["tire_pressure"]));
|
> arrays.push_back(simdjson::to_json_string(car["tire_pressure"]));
|
||||||
> }
|
> }
|
||||||
> }
|
> }
|
||||||
@@ -454,7 +461,7 @@ support for users who avoid exceptions. See [the simdjson error handling documen
|
|||||||
> std::ostringstream oss;
|
> std::ostringstream oss;
|
||||||
> oss << "[";
|
> oss << "[";
|
||||||
> for(size_t i = 0; i < arrays.size(); i++) {
|
> for(size_t i = 0; i < arrays.size(); i++) {
|
||||||
> if(i>0) { oss << ","; }
|
> if (i>0) { oss << ","; }
|
||||||
> oss << arrays[i];
|
> oss << arrays[i];
|
||||||
> }
|
> }
|
||||||
> oss << "]";
|
> oss << "]";
|
||||||
@@ -597,7 +604,7 @@ support for users who avoid exceptions. See [the simdjson error handling documen
|
|||||||
case ondemand::json_type::null:
|
case ondemand::json_type::null:
|
||||||
// We check that the value is indeed null
|
// We check that the value is indeed null
|
||||||
// otherwise: an error is thrown.
|
// otherwise: an error is thrown.
|
||||||
if(element.is_null()) {
|
if (element.is_null()) {
|
||||||
cout << "null";
|
cout << "null";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -910,11 +917,11 @@ bool simple_error_example() {
|
|||||||
ondemand::parser parser;
|
ondemand::parser parser;
|
||||||
auto json = R"({"bad number":3.14.1 })"_padded;
|
auto json = R"({"bad number":3.14.1 })"_padded;
|
||||||
ondemand::document doc;
|
ondemand::document doc;
|
||||||
if( parser.iterate(json).get(doc) != SUCCESS ) { return false; }
|
if (parser.iterate(json).get(doc) != SUCCESS) { return false; }
|
||||||
double x;
|
double x;
|
||||||
auto error = doc["bad number"].get_double().get(x);
|
auto error = doc["bad number"].get_double().get(x);
|
||||||
// returns "simdjson::NUMBER_ERROR"
|
// returns "simdjson::NUMBER_ERROR"
|
||||||
if(error != SUCCESS) {
|
if (error != SUCCESS) {
|
||||||
std::cout << error << std::endl;
|
std::cout << error << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -976,10 +983,10 @@ it selects the key `"count"` within that object.
|
|||||||
int main(void) {
|
int main(void) {
|
||||||
simdjson::ondemand::parser parser;
|
simdjson::ondemand::parser parser;
|
||||||
auto error = padded_string::load("twitter.json").get(json);
|
auto error = padded_string::load("twitter.json").get(json);
|
||||||
if(error) { std::cerr << error << std::endl; return EXIT_FAILURE; }
|
if (error) { std::cerr << error << std::endl; return EXIT_FAILURE; }
|
||||||
simdjson::ondemand::document tweets;
|
simdjson::ondemand::document tweets;
|
||||||
error = parser.iterate(json).get(tweets);
|
error = parser.iterate(json).get(tweets);
|
||||||
if( error ) { std::cerr << error << std::endl; return EXIT_FAILURE; }
|
if (error) { std::cerr << error << std::endl; return EXIT_FAILURE; }
|
||||||
simdjson::ondemand::value res;
|
simdjson::ondemand::value res;
|
||||||
error = tweets["search_metadata"]["count"].get(res);
|
error = tweets["search_metadata"]["count"].get(res);
|
||||||
if (error != SUCCESS) {
|
if (error != SUCCESS) {
|
||||||
@@ -1010,12 +1017,12 @@ int main(void) {
|
|||||||
simdjson::ondemand::document tweets;
|
simdjson::ondemand::document tweets;
|
||||||
padded_string json;
|
padded_string json;
|
||||||
auto error = padded_string::load("twitter.json").get(json);
|
auto error = padded_string::load("twitter.json").get(json);
|
||||||
if(error) { std::cerr << error << std::endl; return EXIT_FAILURE; }
|
if (error) { std::cerr << error << std::endl; return EXIT_FAILURE; }
|
||||||
error = parser.iterate(json).get(tweets);
|
error = parser.iterate(json).get(tweets);
|
||||||
if(error) { std::cerr << error << std::endl; return EXIT_FAILURE; }
|
if (error) { std::cerr << error << std::endl; return EXIT_FAILURE; }
|
||||||
uint64_t identifier;
|
uint64_t identifier;
|
||||||
error = tweets["statuses"].at(0)["id"].get(identifier);
|
error = tweets["statuses"].at(0)["id"].get(identifier);
|
||||||
if(error) { std::cerr << error << std::endl; return EXIT_FAILURE; }
|
if (error) { std::cerr << error << std::endl; return EXIT_FAILURE; }
|
||||||
std::cout << identifier << std::endl;
|
std::cout << identifier << std::endl;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -1039,40 +1046,40 @@ bool parse() {
|
|||||||
|
|
||||||
// Iterating through an array of objects
|
// Iterating through an array of objects
|
||||||
auto error = parser.iterate(cars_json).get(doc);
|
auto error = parser.iterate(cars_json).get(doc);
|
||||||
if(error) { std::cerr << error << std::endl; return false; }
|
if (error) { std::cerr << error << std::endl; return false; }
|
||||||
ondemand::array cars; // invalid until the get() succeeds
|
ondemand::array cars; // invalid until the get() succeeds
|
||||||
error = doc.get_array().get(cars);
|
error = doc.get_array().get(cars);
|
||||||
|
|
||||||
for (auto car_value : cars) {
|
for (auto car_value : cars) {
|
||||||
ondemand::object car; // invalid until the get() succeeds
|
ondemand::object car; // invalid until the get() succeeds
|
||||||
error = car_value.get_object().get(car);
|
error = car_value.get_object().get(car);
|
||||||
if(error) { std::cerr << error << std::endl; return false; }
|
if (error) { std::cerr << error << std::endl; return false; }
|
||||||
|
|
||||||
// Accessing a field by name
|
// Accessing a field by name
|
||||||
std::string_view make;
|
std::string_view make;
|
||||||
std::string_view model;
|
std::string_view model;
|
||||||
error = car["make"].get(make);
|
error = car["make"].get(make);
|
||||||
if(error) { std::cerr << error << std::endl; return false; }
|
if (error) { std::cerr << error << std::endl; return false; }
|
||||||
error = car["model"].get(model);
|
error = car["model"].get(model);
|
||||||
if(error) { std::cerr << error << std::endl; return false; }
|
if (error) { std::cerr << error << std::endl; return false; }
|
||||||
|
|
||||||
cout << "Make/Model: " << make << "/" << model << endl;
|
cout << "Make/Model: " << make << "/" << model << endl;
|
||||||
|
|
||||||
// Casting a JSON element to an integer
|
// Casting a JSON element to an integer
|
||||||
uint64_t year{};
|
uint64_t year{};
|
||||||
error = car["year"].get(year);
|
error = car["year"].get(year);
|
||||||
if(error) { std::cerr << error << std::endl; return false; }
|
if (error) { std::cerr << error << std::endl; return false; }
|
||||||
cout << "- This car is " << 2020 - year << " years old." << endl;
|
cout << "- This car is " << 2020 - year << " years old." << endl;
|
||||||
|
|
||||||
// Iterating through an array of floats
|
// Iterating through an array of floats
|
||||||
double total_tire_pressure = 0;
|
double total_tire_pressure = 0;
|
||||||
ondemand::array pressures;
|
ondemand::array pressures;
|
||||||
error = car["tire_pressure"].get_array().get(pressures);
|
error = car["tire_pressure"].get_array().get(pressures);
|
||||||
if(error) { std::cerr << error << std::endl; return false; }
|
if (error) { std::cerr << error << std::endl; return false; }
|
||||||
for (auto tire_pressure_value : pressures) {
|
for (auto tire_pressure_value : pressures) {
|
||||||
double tire_pressure;
|
double tire_pressure;
|
||||||
error = tire_pressure_value.get_double().get(tire_pressure);
|
error = tire_pressure_value.get_double().get(tire_pressure);
|
||||||
if(error) { std::cerr << error << std::endl; return false; }
|
if (error) { std::cerr << error << std::endl; return false; }
|
||||||
total_tire_pressure += tire_pressure;
|
total_tire_pressure += tire_pressure;
|
||||||
}
|
}
|
||||||
cout << "- Average tire pressure: " << (total_tire_pressure / 4) << endl;
|
cout << "- Average tire pressure: " << (total_tire_pressure / 4) << endl;
|
||||||
@@ -1088,7 +1095,7 @@ after you have initialized them and checked that there is no error:
|
|||||||
ondemand::object car; // invalid until the get() succeeds
|
ondemand::object car; // invalid until the get() succeeds
|
||||||
// the `car` instance should not use used before it is initialized
|
// the `car` instance should not use used before it is initialized
|
||||||
error = car_value.get_object().get(car);
|
error = car_value.get_object().get(car);
|
||||||
if(error) {
|
if (error) {
|
||||||
// the `car` instance should not use used
|
// the `car` instance should not use used
|
||||||
} else {
|
} else {
|
||||||
// the `car` instance can be safely used
|
// the `car` instance can be safely used
|
||||||
@@ -1102,20 +1109,20 @@ having to handle exceptions.
|
|||||||
ondemand::parser parser;
|
ondemand::parser parser;
|
||||||
ondemand::document doc;
|
ondemand::document doc;
|
||||||
auto error = parser.iterate(json).get(doc);
|
auto error = parser.iterate(json).get(doc);
|
||||||
if(error) { return false; }
|
if (error) { return false; }
|
||||||
ondemand::object object; // invalid until the get() succeeds
|
ondemand::object object; // invalid until the get() succeeds
|
||||||
error = doc.get_object().get(object);
|
error = doc.get_object().get(object);
|
||||||
if(error) { return false; }
|
if (error) { return false; }
|
||||||
for(auto field : object) {
|
for(auto field : object) {
|
||||||
// We could replace 'field.key() with field.unescaped_key(),
|
// We could replace 'field.key() with field.unescaped_key(),
|
||||||
// and ondemand::raw_json_string by std::string_view.
|
// and ondemand::raw_json_string by std::string_view.
|
||||||
ondemand::raw_json_string keyv;
|
ondemand::raw_json_string keyv;
|
||||||
error = field.key().get(keyv);
|
error = field.key().get(keyv);
|
||||||
if(error) { return false; }
|
if (error) { return false; }
|
||||||
if(keyv == "key") {
|
if (keyv == "key") {
|
||||||
uint64_t intvalue;
|
uint64_t intvalue;
|
||||||
error = field.value().get(intvalue);
|
error = field.value().get(intvalue);
|
||||||
if(error) { return false; }
|
if (error) { return false; }
|
||||||
std::cout << intvalue;
|
std::cout << intvalue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1294,7 +1301,7 @@ content.
|
|||||||
for (uint64_t values : array) {
|
for (uint64_t values : array) {
|
||||||
std::cout << values << std::endl;
|
std::cout << values << std::endl;
|
||||||
}
|
}
|
||||||
if(!doc.at_end()) {
|
if (!doc.at_end()) {
|
||||||
// In this instance, we will be left pointing at 'foo' since we have consumed the array [1,2].
|
// In this instance, we will be left pointing at 'foo' since we have consumed the array [1,2].
|
||||||
std::cerr << "trailing content at byte index " << doc.current_location() - json.data() << std::endl;
|
std::cerr << "trailing content at byte index " << doc.current_location() - json.data() << std::endl;
|
||||||
}
|
}
|
||||||
@@ -1324,7 +1331,7 @@ before printout the data.
|
|||||||
|
|
||||||
auto doc = parser.iterate(cars_json);
|
auto doc = parser.iterate(cars_json);
|
||||||
for (simdjson_unused ondemand::object car : doc) {
|
for (simdjson_unused ondemand::object car : doc) {
|
||||||
if(car["make"] == "Toyota") { count++; }
|
if (car["make"] == "Toyota") { count++; }
|
||||||
}
|
}
|
||||||
std::cout << "We have " << count << " Toyota cars.\n";
|
std::cout << "We have " << count << " Toyota cars.\n";
|
||||||
doc.rewind(); // requires simdjson 1.0 or better
|
doc.rewind(); // requires simdjson 1.0 or better
|
||||||
@@ -1392,18 +1399,18 @@ ondemand::parser parser;
|
|||||||
ondemand::document_stream stream;
|
ondemand::document_stream stream;
|
||||||
size_t counter{0};
|
size_t counter{0};
|
||||||
auto error = parser.iterate_many(json, 50).get(stream);
|
auto error = parser.iterate_many(json, 50).get(stream);
|
||||||
if( error ) { /* handle the error */ }
|
if (error) { /* handle the error */ }
|
||||||
for (auto doc: stream) {
|
for (auto doc: stream) {
|
||||||
if(counter < 6) {
|
if (counter < 6) {
|
||||||
int64_t val;
|
int64_t val;
|
||||||
error = doc.at_pointer("/4").get(val);
|
error = doc.at_pointer("/4").get(val);
|
||||||
if( error ) { /* handle the error */ }
|
if (error) { /* handle the error */ }
|
||||||
std::cout << "5 = " << val << std::endl;
|
std::cout << "5 = " << val << std::endl;
|
||||||
} else {
|
} else {
|
||||||
ondemand::value val;
|
ondemand::value val;
|
||||||
error = doc.at_pointer("/4").get(val);
|
error = doc.at_pointer("/4").get(val);
|
||||||
// error == simdjson::CAPACITY
|
// error == simdjson::CAPACITY
|
||||||
if(error) {
|
if (error) {
|
||||||
std::cerr << error << std::endl;
|
std::cerr << error << std::endl;
|
||||||
// We left 293 bytes unprocessed at the tail end of the input.
|
// We left 293 bytes unprocessed at the tail end of the input.
|
||||||
std::cout << " unprocessed bytes at the end: " << stream.truncated_bytes() << std::endl;
|
std::cout << " unprocessed bytes at the end: " << stream.truncated_bytes() << std::endl;
|
||||||
@@ -1647,7 +1654,7 @@ JSON string to a user-provided buffer:
|
|||||||
|
|
||||||
General Direct Access to the Raw JSON String
|
General Direct Access to the Raw JSON String
|
||||||
--------------------------------
|
--------------------------------
|
||||||
If your value is a string, the `raw_json_string` gives you direct access to the unprocess
|
If your value is a string, the `raw_json_string` you with `get_raw_json_string()` gives you direct access to the unprocessed
|
||||||
string. The simdjson library allows you to have access to the raw underlying JSON
|
string. The simdjson library allows you to have access to the raw underlying JSON
|
||||||
more generally.
|
more generally.
|
||||||
|
|
||||||
@@ -1716,6 +1723,82 @@ obj.reset(); // revise the object
|
|||||||
uint64_t x = obj["value"]; // gives me 123
|
uint64_t x = obj["value"]; // gives me 123
|
||||||
```
|
```
|
||||||
|
|
||||||
|
You can use `raw_json()` with the values inside an array and object. When
|
||||||
|
calling `raw_json()` on an untyped value, it acts as `raw_json()` when the
|
||||||
|
value is an array or an object. Otherwise, it acts as `raw_json_token()`.
|
||||||
|
It is useful if you do not care for the type of the value and just wants a
|
||||||
|
string representation.
|
||||||
|
|
||||||
|
```C++
|
||||||
|
auto json = R"( [1,2,"fds", {"a":1}, [1,344]] )"_padded;
|
||||||
|
ondemand::parser parser;
|
||||||
|
ondemand::document doc = parser.iterate(json);
|
||||||
|
size_t counter = 0;
|
||||||
|
for(auto array: doc) {
|
||||||
|
std::string_view raw = array.raw_json();
|
||||||
|
// will capture "1", "2", "\"fds\"", "{\"a\":1}", "[1,344]"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```C++
|
||||||
|
auto json = R"( {"key1":1,"key2":2,"key3":"fds", "key4":{"a":1}, "key5":[1,344]} )"_padded;
|
||||||
|
ondemand::parser parser;
|
||||||
|
ondemand::document doc = parser.iterate(json);
|
||||||
|
size_t counter = 0;
|
||||||
|
for(auto key_value: doc.get_object()) {
|
||||||
|
std::string_view raw = key_value.value().raw_json();
|
||||||
|
// will capture "1", "2", "\"fds\"", "{\"a\":1}", "[1,344]"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Storing Directly into an Existing String Instance
|
||||||
|
-----------------------------------------------------
|
||||||
|
|
||||||
|
The simdjson library favours the use of `std::string_view` instances because
|
||||||
|
it tends to lead to better performance due to causing fewer memory allocations.
|
||||||
|
However, they are cases where you need to store a string result in an `std::string``
|
||||||
|
instance. You can do so with a templated version of the `to_string()` method which takes as
|
||||||
|
a parameter a reference to an `std::string`.
|
||||||
|
|
||||||
|
```C++
|
||||||
|
auto json = R"({
|
||||||
|
"name": "Daniel",
|
||||||
|
"age": 42
|
||||||
|
})"_padded;
|
||||||
|
ondemand::parser parser;
|
||||||
|
ondemand::document doc = parser.iterate(json);
|
||||||
|
std::string name;
|
||||||
|
doc["name"].get_string(name);
|
||||||
|
```
|
||||||
|
|
||||||
|
The same routine can be written without exceptions handling:
|
||||||
|
|
||||||
|
```C++
|
||||||
|
std::string name;
|
||||||
|
auto err = doc["name"].get_string(name);
|
||||||
|
if(err) { /* handle error */ }
|
||||||
|
```
|
||||||
|
|
||||||
|
The `std::string` instance, once created, is independent. Unlike our `std::string_view` instances,
|
||||||
|
it does not point at data that is within our `parser` instance. The same caveat applies: you should
|
||||||
|
only consume a JSON string once.
|
||||||
|
|
||||||
|
Because `get_string()` is a template that requires a type that can be assigned an `std::string`, you
|
||||||
|
can use it with features such as `std::optional`:
|
||||||
|
|
||||||
|
```C++
|
||||||
|
auto json = R"({ "foo1": "3.1416" } )"_padded;
|
||||||
|
ondemand::parser parser;
|
||||||
|
ondemand::document doc = parser.iterate(json);
|
||||||
|
std::optional<std::string> value;
|
||||||
|
if(doc["foo1"].get_string(value)) { /* error */ }
|
||||||
|
// value was populated with "3.1416"
|
||||||
|
```
|
||||||
|
|
||||||
|
You should be mindful of the trade-off: allocating multiple
|
||||||
|
`std::string` instances can become expensive.
|
||||||
|
|
||||||
Thread Safety
|
Thread Safety
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
@@ -1944,6 +2027,79 @@ bool example() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
* Example 3: CRT
|
||||||
|
|
||||||
|
```C++
|
||||||
|
|
||||||
|
bool example() {
|
||||||
|
padded_string padded_input_json = R"([
|
||||||
|
{ "monitor": [
|
||||||
|
{ "id": "monitor", "type": "toggle", "label": "monitor" },
|
||||||
|
{ "id": "profile", "type": "selector", "label": "collection" },
|
||||||
|
{ "id": "overlay", "type": "selector", "label": "overlay" },
|
||||||
|
{ "id": "zoom", "type": "toggleSlider", "label": "zoom" }
|
||||||
|
] },
|
||||||
|
|
||||||
|
{ "crt": [
|
||||||
|
{ "id": "system", "type": "multi", "label": "system", "choices": "PAL, NTSC" },
|
||||||
|
{ "type": "spacer" },
|
||||||
|
{ "id": "brightness", "type": "slider", "icon": "brightness" },
|
||||||
|
{ "id": "contrast", "type": "slider", "icon": "contrast" },
|
||||||
|
{ "id": "saturation", "type": "slider", "icon": "saturation" },
|
||||||
|
{ "type": "spacer" },
|
||||||
|
{ "id": "overscan", "type": "toggleSlider", "label": "overscan" },
|
||||||
|
{ "type": "spacer" },
|
||||||
|
{ "id": "emulation", "type": "toggle", "label": "CRT emulation" },
|
||||||
|
{ "type": "spacer" },
|
||||||
|
{ "id": "curve", "type": "toggleSlider", "label": "curve" },
|
||||||
|
{ "id": "bleed", "type": "toggleSlider", "label": "bleed" },
|
||||||
|
{ "id": "vignette", "type": "toggleSlider", "label": "vignette" },
|
||||||
|
{ "id": "scanlines", "type": "toggleSlider", "label": "scanlines" },
|
||||||
|
{ "id": "gridlines", "type": "toggleSlider", "label": "gridlines" },
|
||||||
|
{ "id": "glow", "type": "toggleSlider", "label": "glow" },
|
||||||
|
{ "id": "flicker", "type": "toggleSlider", "label": "flicker" },
|
||||||
|
{ "id": "noise", "type": "toggleSlider", "label": "noise" },
|
||||||
|
{}
|
||||||
|
] }
|
||||||
|
])"_padded;
|
||||||
|
auto parser = ondemand::parser{};
|
||||||
|
auto doc = parser.iterate(padded_input_json);
|
||||||
|
auto root_array = doc.get_array();
|
||||||
|
// the root should be an object, not an array, but that's the JSON we are
|
||||||
|
// given.
|
||||||
|
for (ondemand::object node : root_array) {
|
||||||
|
// We know that we are going to have just one element in the object.
|
||||||
|
for (auto field : node) {
|
||||||
|
std::cout << "\n\ntop level:" << field.key() << std::endl;
|
||||||
|
// You can get a proper std::string_view for the key with:
|
||||||
|
// std::string_view key = field.unescaped_key();
|
||||||
|
// and second for-range loop to get child-elements here
|
||||||
|
for (ondemand::object inner_object : field.value()) {
|
||||||
|
auto i = inner_object.begin();
|
||||||
|
if (i == inner_object.end()) {
|
||||||
|
std::cout << "empty object" << std::endl;
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
for (; i != inner_object.end(); ++i) {
|
||||||
|
auto inner_field = *i;
|
||||||
|
std::cout << '"' << inner_field.key()
|
||||||
|
<< "\" : " << inner_field.value() << ", ";
|
||||||
|
// You can get proper std::string_view for the key and value with:
|
||||||
|
// std::string_view inner_key = field.unescaped_key();
|
||||||
|
// std::string_view value_str = field.value();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::cout << std::endl;
|
||||||
|
}
|
||||||
|
// You can break here if you only want just the first element.
|
||||||
|
// break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Performance Tips
|
Performance Tips
|
||||||
--------
|
--------
|
||||||
|
|||||||
+2
-2
@@ -329,10 +329,10 @@ int main(void) {
|
|||||||
simdjson::dom::parser parser;
|
simdjson::dom::parser parser;
|
||||||
simdjson::dom::element tweets; // invalid until the get() succeeds
|
simdjson::dom::element tweets; // invalid until the get() succeeds
|
||||||
auto error = parser.load("twitter.json").get(tweets);
|
auto error = parser.load("twitter.json").get(tweets);
|
||||||
if(error) { std::cerr << error << std::endl; return EXIT_FAILURE; }
|
if (error) { std::cerr << error << std::endl; return EXIT_FAILURE; }
|
||||||
uint64_t identifier;
|
uint64_t identifier;
|
||||||
error = tweets["statuses"].at(0)["id"].get(identifier);
|
error = tweets["statuses"].at(0)["id"].get(identifier);
|
||||||
if(error) { std::cerr << error << std::endl; return EXIT_FAILURE; }
|
if (error) { std::cerr << error << std::endl; return EXIT_FAILURE; }
|
||||||
std::cout << identifier << std::endl;
|
std::cout << identifier << std::endl;
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -101,8 +101,8 @@ by comparing it with the null pointer.
|
|||||||
|
|
||||||
```c++
|
```c++
|
||||||
auto my_implementation = simdjson::get_available_implementations()["haswell"];
|
auto my_implementation = simdjson::get_available_implementations()["haswell"];
|
||||||
if(! my_implementation) { exit(1); }
|
if (! my_implementation) { exit(1); }
|
||||||
if(! my_implementation->supported_by_runtime_system()) { exit(1); }
|
if (! my_implementation->supported_by_runtime_system()) { exit(1); }
|
||||||
simdjson::get_active_implementation() = my_implementation;
|
simdjson::get_active_implementation() = my_implementation;
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -113,7 +113,7 @@ You should call `supported_by_runtime_system()` to compare the processor's featu
|
|||||||
|
|
||||||
```c++
|
```c++
|
||||||
for (auto implementation : simdjson::get_available_implementations()) {
|
for (auto implementation : simdjson::get_available_implementations()) {
|
||||||
if(implementation->supported_by_runtime_system()) {
|
if (implementation->supported_by_runtime_system()) {
|
||||||
cout << implementation->name() << ": " << implementation->description() << endl;
|
cout << implementation->name() << ": " << implementation->description() << endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-4
@@ -17,6 +17,9 @@ Contents
|
|||||||
|
|
||||||
- [Motivations](#motivations)
|
- [Motivations](#motivations)
|
||||||
- [How it works](#how-it-works)
|
- [How it works](#how-it-works)
|
||||||
|
- [Context](#context)
|
||||||
|
- [Design](#design)
|
||||||
|
- [Threads](#threads)
|
||||||
- [Support](#support)
|
- [Support](#support)
|
||||||
- [API](#api)
|
- [API](#api)
|
||||||
- [Use cases](#use-cases)
|
- [Use cases](#use-cases)
|
||||||
@@ -193,12 +196,12 @@ Let us illustrate the idea with code:
|
|||||||
simdjson::ondemand::parser parser;
|
simdjson::ondemand::parser parser;
|
||||||
simdjson::ondemand::document_stream stream;
|
simdjson::ondemand::document_stream stream;
|
||||||
auto error = parser.iterate_many(json).get(stream);
|
auto error = parser.iterate_many(json).get(stream);
|
||||||
if( error ) { /* do something */ }
|
if (error) { /* do something */ }
|
||||||
auto i = stream.begin();
|
auto i = stream.begin();
|
||||||
size_t count{0};
|
size_t count{0};
|
||||||
for(; i != stream.end(); ++i) {
|
for(; i != stream.end(); ++i) {
|
||||||
auto doc = *i;
|
auto doc = *i;
|
||||||
if(!i.error()) {
|
if (!i.error()) {
|
||||||
std::cout << "got full document at " << i.current_index() << std::endl;
|
std::cout << "got full document at " << i.current_index() << std::endl;
|
||||||
std::cout << i.source() << std::endl;
|
std::cout << i.source() << std::endl;
|
||||||
count++;
|
count++;
|
||||||
@@ -234,7 +237,7 @@ Consider the following example where a truncated document (`{"key":"intentionall
|
|||||||
simdjson::ondemand::parser parser;
|
simdjson::ondemand::parser parser;
|
||||||
simdjson::ondemand::document_stream stream;
|
simdjson::ondemand::document_stream stream;
|
||||||
auto error = parser.iterate_many(json,json.size()).get(stream);
|
auto error = parser.iterate_many(json,json.size()).get(stream);
|
||||||
if(error) { std::cerr << error << std::endl; return; }
|
if (error) { std::cerr << error << std::endl; return; }
|
||||||
for(auto i = stream.begin(); i != stream.end(); ++i) {
|
for(auto i = stream.begin(); i != stream.end(); ++i) {
|
||||||
std::cout << i.source() << std::endl;
|
std::cout << i.source() << std::endl;
|
||||||
}
|
}
|
||||||
@@ -266,7 +269,7 @@ Example:
|
|||||||
// we pass 'true' to the allow_comma parameter, the batch size will be set to at least
|
// we pass 'true' to the allow_comma parameter, the batch size will be set to at least
|
||||||
// the document size.
|
// the document size.
|
||||||
auto error = parser.iterate_many(json, 32, true).get(doc_stream);
|
auto error = parser.iterate_many(json, 32, true).get(doc_stream);
|
||||||
if(error) { std::cerr << error << std::endl; return; }
|
if (error) { std::cerr << error << std::endl; return; }
|
||||||
for (auto doc : doc_stream) {
|
for (auto doc : doc_stream) {
|
||||||
std::cout << doc.type() << std::endl;
|
std::cout << doc.type() << std::endl;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -679,11 +679,11 @@ in production systems:
|
|||||||
ondemand::object c1 = parent["child1"];
|
ondemand::object c1 = parent["child1"];
|
||||||
// c1 owns the focus
|
// c1 owns the focus
|
||||||
//
|
//
|
||||||
if(std::string_view(c1["name"]) != "John") { ... }
|
if (std::string_view(c1["name"]) != "John") { ... }
|
||||||
// c2 attempts to grab the focus from parent but fails
|
// c2 attempts to grab the focus from parent but fails
|
||||||
ondemand::object c2 = parent["child2"];
|
ondemand::object c2 = parent["child2"];
|
||||||
// c2 is now in an unsafe state and the following line would be unsafe
|
// c2 is now in an unsafe state and the following line would be unsafe
|
||||||
// if(std::string_view(c2["name"]) != "Daniel") { return false; }
|
// if (std::string_view(c2["name"]) != "Daniel") { return false; }
|
||||||
```
|
```
|
||||||
|
|
||||||
A correct usage is given by the following example:
|
A correct usage is given by the following example:
|
||||||
@@ -697,7 +697,7 @@ in production systems:
|
|||||||
{
|
{
|
||||||
ondemand::object c1 = parent["child1"];
|
ondemand::object c1 = parent["child1"];
|
||||||
// c1 grabbed the focus from parent
|
// c1 grabbed the focus from parent
|
||||||
if(std::string_view(c1["name"]) != "John") { return false; }
|
if (std::string_view(c1["name"]) != "John") { return false; }
|
||||||
}
|
}
|
||||||
// c1 went out of scope, so its destructor was called and the focus
|
// c1 went out of scope, so its destructor was called and the focus
|
||||||
// was handed back to parent.
|
// was handed back to parent.
|
||||||
@@ -705,7 +705,7 @@ in production systems:
|
|||||||
ondemand::object c2 = parent["child2"];
|
ondemand::object c2 = parent["child2"];
|
||||||
// c2 grabbed the focus from parent
|
// c2 grabbed the focus from parent
|
||||||
// the following is safe:
|
// the following is safe:
|
||||||
if(std::string_view(c2["name"]) != "Daniel") { return false; }
|
if (std::string_view(c2["name"]) != "Daniel") { return false; }
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -184,12 +184,12 @@ Let us illustrate the idea with code:
|
|||||||
simdjson::dom::parser parser;
|
simdjson::dom::parser parser;
|
||||||
simdjson::dom::document_stream stream;
|
simdjson::dom::document_stream stream;
|
||||||
auto error = parser.parse_many(json).get(stream);
|
auto error = parser.parse_many(json).get(stream);
|
||||||
if( error ) { /* do something */ }
|
if (error) { /* do something */ }
|
||||||
auto i = stream.begin();
|
auto i = stream.begin();
|
||||||
size_t count{0};
|
size_t count{0};
|
||||||
for(; i != stream.end(); ++i) {
|
for(; i != stream.end(); ++i) {
|
||||||
auto doc = *i;
|
auto doc = *i;
|
||||||
if(!doc.error()) {
|
if (!doc.error()) {
|
||||||
std::cout << "got full document at " << i.current_index() << std::endl;
|
std::cout << "got full document at " << i.current_index() << std::endl;
|
||||||
std::cout << i.source() << std::endl;
|
std::cout << i.source() << std::endl;
|
||||||
count++;
|
count++;
|
||||||
@@ -225,7 +225,7 @@ Consider the following example where a truncated document (`{"key":"intentionall
|
|||||||
simdjson::dom::parser parser;
|
simdjson::dom::parser parser;
|
||||||
simdjson::dom::document_stream stream;
|
simdjson::dom::document_stream stream;
|
||||||
auto error = parser.parse_many(json,json.size()).get(stream);
|
auto error = parser.parse_many(json,json.size()).get(stream);
|
||||||
if(error) { std::cerr << error << std::endl; return; }
|
if (error) { std::cerr << error << std::endl; return; }
|
||||||
for(auto doc : stream) {
|
for(auto doc : stream) {
|
||||||
std::cout << doc << std::endl;
|
std::cout << doc << std::endl;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,4 +32,12 @@
|
|||||||
#error simdjson requires a compiler compliant with the C++11 standard
|
#error simdjson requires a compiler compliant with the C++11 standard
|
||||||
#endif
|
#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
|
#endif // SIMDJSON_COMPILER_CHECK_H
|
||||||
|
|||||||
@@ -410,6 +410,12 @@ inline simdjson_result<element> element::at_key(std::string_view key) const noex
|
|||||||
inline simdjson_result<element> element::at_key_case_insensitive(std::string_view key) const noexcept {
|
inline simdjson_result<element> element::at_key_case_insensitive(std::string_view key) const noexcept {
|
||||||
return get<object>().at_key_case_insensitive(key);
|
return get<object>().at_key_case_insensitive(key);
|
||||||
}
|
}
|
||||||
|
inline bool element::operator<(const element &other) const noexcept {
|
||||||
|
return tape.json_index < other.tape.json_index;
|
||||||
|
}
|
||||||
|
inline bool element::operator==(const element &other) const noexcept {
|
||||||
|
return tape.json_index == other.tape.json_index;
|
||||||
|
}
|
||||||
|
|
||||||
inline bool element::dump_raw_tape(std::ostream &out) const noexcept {
|
inline bool element::dump_raw_tape(std::ostream &out) const noexcept {
|
||||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||||
|
|||||||
@@ -211,7 +211,11 @@ public:
|
|||||||
inline simdjson_result<T> get() const noexcept {
|
inline simdjson_result<T> get() const noexcept {
|
||||||
// Unless the simdjson library provides an inline implementation, calling this method should
|
// Unless the simdjson library provides an inline implementation, calling this method should
|
||||||
// immediately fail.
|
// immediately fail.
|
||||||
static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library.");
|
static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. "
|
||||||
|
"The supported types are Boolean (bool), numbers (double, uint64_t, int64_t), "
|
||||||
|
"strings (std::string_view, const char *), arrays (dom::array) and objects (dom::object). "
|
||||||
|
"We recommand you use get_double(), get_bool(), get_uint64(), get_int64(), "
|
||||||
|
"get_object(), get_array() or get_string() instead of the get template.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -451,6 +455,22 @@ public:
|
|||||||
*/
|
*/
|
||||||
inline simdjson_result<element> at_key_case_insensitive(std::string_view key) const noexcept;
|
inline simdjson_result<element> at_key_case_insensitive(std::string_view key) const noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* operator< defines a total order for element allowing to use them in
|
||||||
|
* ordered C++ STL containers
|
||||||
|
*
|
||||||
|
* @return TRUE if the key appears before the other one in the tape
|
||||||
|
*/
|
||||||
|
inline bool operator<(const element &other) const noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* operator== allows to verify if two element values reference the
|
||||||
|
* same JSON item
|
||||||
|
*
|
||||||
|
* @return TRUE if the two values references the same JSON element
|
||||||
|
*/
|
||||||
|
inline bool operator==(const element &other) const noexcept;
|
||||||
|
|
||||||
/** @private for debugging. Prints out the root element. */
|
/** @private for debugging. Prints out the root element. */
|
||||||
inline bool dump_raw_tape(std::ostream &out) const noexcept;
|
inline bool dump_raw_tape(std::ostream &out) const noexcept;
|
||||||
|
|
||||||
|
|||||||
@@ -186,8 +186,7 @@ simdjson_inline bool compute_float_64(int64_t power, uint64_t i, bool negative,
|
|||||||
// power_of_five_128[index]. Usually, that's good enough to approximate i * 5^q
|
// power_of_five_128[index]. Usually, that's good enough to approximate i * 5^q
|
||||||
// to the desired approximation using one multiplication. Sometimes it does not suffice.
|
// to the desired approximation using one multiplication. Sometimes it does not suffice.
|
||||||
// Then we store the next most significant 64 bits in power_of_five_128[index + 1], and
|
// Then we store the next most significant 64 bits in power_of_five_128[index + 1], and
|
||||||
// then we get a better approximation to i * 5^q. In very rare cases, even that
|
// then we get a better approximation to i * 5^q.
|
||||||
// will not suffice, though it is seemingly very hard to find such a scenario.
|
|
||||||
//
|
//
|
||||||
// That's for when q>=0. The logic for q<0 is somewhat similar but it is somewhat
|
// That's for when q>=0. The logic for q<0 is somewhat similar but it is somewhat
|
||||||
// more complicated.
|
// more complicated.
|
||||||
@@ -202,12 +201,9 @@ simdjson_inline bool compute_float_64(int64_t power, uint64_t i, bool negative,
|
|||||||
simdjson::internal::value128 secondproduct = full_multiplication(i, simdjson::internal::power_of_five_128[index + 1]);
|
simdjson::internal::value128 secondproduct = full_multiplication(i, simdjson::internal::power_of_five_128[index + 1]);
|
||||||
firstproduct.low += secondproduct.high;
|
firstproduct.low += secondproduct.high;
|
||||||
if(secondproduct.high > firstproduct.low) { firstproduct.high++; }
|
if(secondproduct.high > firstproduct.low) { firstproduct.high++; }
|
||||||
// At this point, we might need to add at most one to firstproduct, but this
|
// As it has been proven by Noble Mushtak and Daniel Lemire in "Fast Number Parsing Without
|
||||||
// can only change the value of firstproduct.high if firstproduct.low is maximal.
|
// Fallback" (https://arxiv.org/abs/2212.06644), at this point we are sure that the product
|
||||||
if(simdjson_unlikely(firstproduct.low == 0xFFFFFFFFFFFFFFFF)) {
|
// is sufficiently accurate, and more computation is not needed.
|
||||||
// This is very unlikely, but if so, we need to do much more work!
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
uint64_t lower = firstproduct.low;
|
uint64_t lower = firstproduct.low;
|
||||||
uint64_t upper = firstproduct.high;
|
uint64_t upper = firstproduct.high;
|
||||||
|
|||||||
@@ -128,6 +128,10 @@ simdjson_inline simdjson_result<double> document::get_double_in_string() noexcep
|
|||||||
simdjson_inline simdjson_result<std::string_view> document::get_string(bool allow_replacement) noexcept {
|
simdjson_inline simdjson_result<std::string_view> document::get_string(bool allow_replacement) noexcept {
|
||||||
return get_root_value_iterator().get_root_string(true, allow_replacement);
|
return get_root_value_iterator().get_root_string(true, allow_replacement);
|
||||||
}
|
}
|
||||||
|
template <typename string_type>
|
||||||
|
simdjson_inline error_code document::get_string(string_type& receiver, bool allow_replacement) noexcept {
|
||||||
|
return get_root_value_iterator().get_root_string(receiver, true, allow_replacement);
|
||||||
|
}
|
||||||
simdjson_inline simdjson_result<std::string_view> document::get_wobbly_string() noexcept {
|
simdjson_inline simdjson_result<std::string_view> document::get_wobbly_string() noexcept {
|
||||||
return get_root_value_iterator().get_root_wobbly_string(true);
|
return get_root_value_iterator().get_root_wobbly_string(true);
|
||||||
}
|
}
|
||||||
@@ -397,6 +401,11 @@ simdjson_inline simdjson_result<std::string_view> simdjson_result<SIMDJSON_IMPLE
|
|||||||
if (error()) { return error(); }
|
if (error()) { return error(); }
|
||||||
return first.get_string(allow_replacement);
|
return first.get_string(allow_replacement);
|
||||||
}
|
}
|
||||||
|
template <typename string_type>
|
||||||
|
simdjson_inline error_code simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::get_string(string_type& receiver, bool allow_replacement) noexcept {
|
||||||
|
if (error()) { return error(); }
|
||||||
|
return first.get_string(receiver, allow_replacement);
|
||||||
|
}
|
||||||
simdjson_inline simdjson_result<std::string_view> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::get_wobbly_string() noexcept {
|
simdjson_inline simdjson_result<std::string_view> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::get_wobbly_string() noexcept {
|
||||||
if (error()) { return error(); }
|
if (error()) { return error(); }
|
||||||
return first.get_wobbly_string();
|
return first.get_wobbly_string();
|
||||||
@@ -583,6 +592,8 @@ simdjson_inline simdjson_result<int64_t> document_reference::get_int64_in_string
|
|||||||
simdjson_inline simdjson_result<double> document_reference::get_double() noexcept { return doc->get_root_value_iterator().get_root_double(false); }
|
simdjson_inline simdjson_result<double> document_reference::get_double() noexcept { return doc->get_root_value_iterator().get_root_double(false); }
|
||||||
simdjson_inline simdjson_result<double> document_reference::get_double_in_string() noexcept { return doc->get_root_value_iterator().get_root_double(false); }
|
simdjson_inline simdjson_result<double> document_reference::get_double_in_string() noexcept { return doc->get_root_value_iterator().get_root_double(false); }
|
||||||
simdjson_inline simdjson_result<std::string_view> document_reference::get_string(bool allow_replacement) noexcept { return doc->get_root_value_iterator().get_root_string(false, allow_replacement); }
|
simdjson_inline simdjson_result<std::string_view> document_reference::get_string(bool allow_replacement) noexcept { return doc->get_root_value_iterator().get_root_string(false, allow_replacement); }
|
||||||
|
template <typename string_type>
|
||||||
|
simdjson_inline error_code document_reference::get_string(string_type& receiver, bool allow_replacement) noexcept { return doc->get_root_value_iterator().get_root_string(receiver, false, allow_replacement); }
|
||||||
simdjson_inline simdjson_result<std::string_view> document_reference::get_wobbly_string() noexcept { return doc->get_root_value_iterator().get_root_wobbly_string(false); }
|
simdjson_inline simdjson_result<std::string_view> document_reference::get_wobbly_string() noexcept { return doc->get_root_value_iterator().get_root_wobbly_string(false); }
|
||||||
simdjson_inline simdjson_result<raw_json_string> document_reference::get_raw_json_string() noexcept { return doc->get_root_value_iterator().get_root_raw_json_string(false); }
|
simdjson_inline simdjson_result<raw_json_string> document_reference::get_raw_json_string() noexcept { return doc->get_root_value_iterator().get_root_raw_json_string(false); }
|
||||||
simdjson_inline simdjson_result<bool> document_reference::get_bool() noexcept { return doc->get_root_value_iterator().get_root_bool(false); }
|
simdjson_inline simdjson_result<bool> document_reference::get_bool() noexcept { return doc->get_root_value_iterator().get_root_bool(false); }
|
||||||
@@ -719,6 +730,11 @@ simdjson_inline simdjson_result<std::string_view> simdjson_result<SIMDJSON_IMPLE
|
|||||||
if (error()) { return error(); }
|
if (error()) { return error(); }
|
||||||
return first.get_string(allow_replacement);
|
return first.get_string(allow_replacement);
|
||||||
}
|
}
|
||||||
|
template <typename string_type>
|
||||||
|
simdjson_inline error_code simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::get_string(string_type& receiver, bool allow_replacement) noexcept {
|
||||||
|
if (error()) { return error(); }
|
||||||
|
return first.get_string(receiver, allow_replacement);
|
||||||
|
}
|
||||||
simdjson_inline simdjson_result<std::string_view> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::get_wobbly_string() noexcept {
|
simdjson_inline simdjson_result<std::string_view> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::get_wobbly_string() noexcept {
|
||||||
if (error()) { return error(); }
|
if (error()) { return error(); }
|
||||||
return first.get_wobbly_string();
|
return first.get_wobbly_string();
|
||||||
|
|||||||
@@ -100,6 +100,21 @@ public:
|
|||||||
* @returns INCORRECT_TYPE if the JSON value is not a string.
|
* @returns INCORRECT_TYPE if the JSON value is not a string.
|
||||||
*/
|
*/
|
||||||
simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement = false) noexcept;
|
simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement = false) noexcept;
|
||||||
|
/**
|
||||||
|
* Attempts to fill the provided std::string reference with the parsed value of the current string.
|
||||||
|
*
|
||||||
|
* The string is guaranteed to be valid UTF-8.
|
||||||
|
*
|
||||||
|
* Important: a value should be consumed once. Calling get_string() twice on the same value
|
||||||
|
* is an error.
|
||||||
|
*
|
||||||
|
* Performance: This method may be slower than get_string() or get_string(bool) because it may need to allocate memory.
|
||||||
|
* We recommend you avoid allocating an std::string unless you need to.
|
||||||
|
*
|
||||||
|
* @returns INCORRECT_TYPE if the JSON value is not a string. Otherwise, we return SUCCESS.
|
||||||
|
*/
|
||||||
|
template <typename string_type>
|
||||||
|
simdjson_inline error_code get_string(string_type& receiver, bool allow_replacement = false) noexcept;
|
||||||
/**
|
/**
|
||||||
* Cast this JSON value to a string.
|
* Cast this JSON value to a string.
|
||||||
*
|
*
|
||||||
@@ -160,13 +175,19 @@ public:
|
|||||||
template<typename T> simdjson_inline simdjson_result<T> get() & noexcept {
|
template<typename T> simdjson_inline simdjson_result<T> get() & noexcept {
|
||||||
// Unless the simdjson library provides an inline implementation, calling this method should
|
// Unless the simdjson library provides an inline implementation, calling this method should
|
||||||
// immediately fail.
|
// immediately fail.
|
||||||
static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library.");
|
static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. "
|
||||||
|
"The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, "
|
||||||
|
"int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), "
|
||||||
|
" get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template.");
|
||||||
}
|
}
|
||||||
/** @overload template<typename T> simdjson_result<T> get() & noexcept */
|
/** @overload template<typename T> simdjson_result<T> get() & noexcept */
|
||||||
template<typename T> simdjson_inline simdjson_result<T> get() && noexcept {
|
template<typename T> simdjson_inline simdjson_result<T> get() && noexcept {
|
||||||
// Unless the simdjson library provides an inline implementation, calling this method should
|
// Unless the simdjson library provides an inline implementation, calling this method should
|
||||||
// immediately fail.
|
// immediately fail.
|
||||||
static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library.");
|
static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. "
|
||||||
|
"The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, "
|
||||||
|
"int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), "
|
||||||
|
" get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -618,6 +639,8 @@ public:
|
|||||||
simdjson_inline simdjson_result<double> get_double() noexcept;
|
simdjson_inline simdjson_result<double> get_double() noexcept;
|
||||||
simdjson_inline simdjson_result<double> get_double_in_string() noexcept;
|
simdjson_inline simdjson_result<double> get_double_in_string() noexcept;
|
||||||
simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement = false) noexcept;
|
simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement = false) noexcept;
|
||||||
|
template <typename string_type>
|
||||||
|
simdjson_inline error_code get_string(string_type& receiver, bool allow_replacement = false) noexcept;
|
||||||
simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept;
|
simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept;
|
||||||
simdjson_inline simdjson_result<raw_json_string> get_raw_json_string() noexcept;
|
simdjson_inline simdjson_result<raw_json_string> get_raw_json_string() noexcept;
|
||||||
simdjson_inline simdjson_result<bool> get_bool() noexcept;
|
simdjson_inline simdjson_result<bool> get_bool() noexcept;
|
||||||
@@ -687,6 +710,8 @@ public:
|
|||||||
simdjson_inline simdjson_result<double> get_double() noexcept;
|
simdjson_inline simdjson_result<double> get_double() noexcept;
|
||||||
simdjson_inline simdjson_result<double> get_double_in_string() noexcept;
|
simdjson_inline simdjson_result<double> get_double_in_string() noexcept;
|
||||||
simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement = false) noexcept;
|
simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement = false) noexcept;
|
||||||
|
template <typename string_type>
|
||||||
|
simdjson_inline error_code get_string(string_type& receiver, bool allow_replacement = false) noexcept;
|
||||||
simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept;
|
simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept;
|
||||||
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string> get_raw_json_string() noexcept;
|
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string> get_raw_json_string() noexcept;
|
||||||
simdjson_inline simdjson_result<bool> get_bool() noexcept;
|
simdjson_inline simdjson_result<bool> get_bool() noexcept;
|
||||||
@@ -759,6 +784,8 @@ public:
|
|||||||
simdjson_inline simdjson_result<double> get_double() noexcept;
|
simdjson_inline simdjson_result<double> get_double() noexcept;
|
||||||
simdjson_inline simdjson_result<double> get_double_in_string() noexcept;
|
simdjson_inline simdjson_result<double> get_double_in_string() noexcept;
|
||||||
simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement = false) noexcept;
|
simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement = false) noexcept;
|
||||||
|
template <typename string_type>
|
||||||
|
simdjson_inline error_code get_string(string_type& receiver, bool allow_replacement = false) noexcept;
|
||||||
simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept;
|
simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept;
|
||||||
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string> get_raw_json_string() noexcept;
|
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string> get_raw_json_string() noexcept;
|
||||||
simdjson_inline simdjson_result<bool> get_bool() noexcept;
|
simdjson_inline simdjson_result<bool> get_bool() noexcept;
|
||||||
|
|||||||
@@ -254,6 +254,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
simdjson_inline simdjson_result<std::string_view> unescape(raw_json_string in, bool allow_replacement) noexcept;
|
simdjson_inline simdjson_result<std::string_view> unescape(raw_json_string in, bool allow_replacement) noexcept;
|
||||||
simdjson_inline simdjson_result<std::string_view> unescape_wobbly(raw_json_string in) noexcept;
|
simdjson_inline simdjson_result<std::string_view> unescape_wobbly(raw_json_string in) noexcept;
|
||||||
|
|
||||||
simdjson_inline void reenter_child(token_position position, depth_t child_depth) noexcept;
|
simdjson_inline void reenter_child(token_position position, depth_t child_depth) noexcept;
|
||||||
|
|
||||||
simdjson_inline error_code consume_character(char c) noexcept;
|
simdjson_inline error_code consume_character(char c) noexcept;
|
||||||
|
|||||||
@@ -68,6 +68,13 @@ simdjson_warn_unused simdjson_inline simdjson_result<document> parser::iterate(s
|
|||||||
return iterate(padded_string_view(json, allocated));
|
return iterate(padded_string_view(json, allocated));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
simdjson_warn_unused simdjson_inline simdjson_result<document> parser::iterate(std::string &json) & noexcept {
|
||||||
|
if(json.capacity() - json.size() < SIMDJSON_PADDING) {
|
||||||
|
json.reserve(json.size() + SIMDJSON_PADDING);
|
||||||
|
}
|
||||||
|
return iterate(padded_string_view(json));
|
||||||
|
}
|
||||||
|
|
||||||
simdjson_warn_unused simdjson_inline simdjson_result<document> parser::iterate(const std::string &json) & noexcept {
|
simdjson_warn_unused simdjson_inline simdjson_result<document> parser::iterate(const std::string &json) & noexcept {
|
||||||
return iterate(padded_string_view(json));
|
return iterate(padded_string_view(json));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -107,6 +107,8 @@ public:
|
|||||||
/** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
|
/** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
|
||||||
simdjson_warn_unused simdjson_result<document> iterate(const std::string &json) & noexcept;
|
simdjson_warn_unused simdjson_result<document> iterate(const std::string &json) & noexcept;
|
||||||
/** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
|
/** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
|
||||||
|
simdjson_warn_unused simdjson_result<document> iterate(std::string &json) & noexcept;
|
||||||
|
/** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
|
||||||
simdjson_warn_unused simdjson_result<document> iterate(const simdjson_result<padded_string> &json) & noexcept;
|
simdjson_warn_unused simdjson_result<document> iterate(const simdjson_result<padded_string> &json) & noexcept;
|
||||||
/** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
|
/** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
|
||||||
simdjson_warn_unused simdjson_result<document> iterate(const simdjson_result<padded_string_view> &json) & noexcept;
|
simdjson_warn_unused simdjson_result<document> iterate(const simdjson_result<padded_string_view> &json) & noexcept;
|
||||||
|
|||||||
@@ -47,6 +47,10 @@ simdjson_inline simdjson_result<raw_json_string> value::get_raw_json_string() no
|
|||||||
simdjson_inline simdjson_result<std::string_view> value::get_string(bool allow_replacement) noexcept {
|
simdjson_inline simdjson_result<std::string_view> value::get_string(bool allow_replacement) noexcept {
|
||||||
return iter.get_string(allow_replacement);
|
return iter.get_string(allow_replacement);
|
||||||
}
|
}
|
||||||
|
template <typename string_type>
|
||||||
|
simdjson_inline error_code value::get_string(string_type& receiver, bool allow_replacement) noexcept {
|
||||||
|
return iter.get_string(receiver, allow_replacement);
|
||||||
|
}
|
||||||
simdjson_inline simdjson_result<std::string_view> value::get_wobbly_string() noexcept {
|
simdjson_inline simdjson_result<std::string_view> value::get_wobbly_string() noexcept {
|
||||||
return iter.get_wobbly_string();
|
return iter.get_wobbly_string();
|
||||||
}
|
}
|
||||||
@@ -193,6 +197,26 @@ simdjson_inline std::string_view value::raw_json_token() noexcept {
|
|||||||
return std::string_view(reinterpret_cast<const char*>(iter.peek_start()), iter.peek_start_length());
|
return std::string_view(reinterpret_cast<const char*>(iter.peek_start()), iter.peek_start_length());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
simdjson_inline simdjson_result<std::string_view> value::raw_json() noexcept {
|
||||||
|
json_type t;
|
||||||
|
SIMDJSON_TRY(type().get(t));
|
||||||
|
switch (t)
|
||||||
|
{
|
||||||
|
case json_type::array: {
|
||||||
|
ondemand::array array;
|
||||||
|
SIMDJSON_TRY(get_array().get(array));
|
||||||
|
return array.raw_json();
|
||||||
|
}
|
||||||
|
case json_type::object: {
|
||||||
|
ondemand::object object;
|
||||||
|
SIMDJSON_TRY(get_object().get(object));
|
||||||
|
return object.raw_json();
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return raw_json_token();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
simdjson_inline simdjson_result<const char *> value::current_location() noexcept {
|
simdjson_inline simdjson_result<const char *> value::current_location() noexcept {
|
||||||
return iter.json_iter().current_location();
|
return iter.json_iter().current_location();
|
||||||
}
|
}
|
||||||
@@ -319,6 +343,11 @@ simdjson_inline simdjson_result<std::string_view> simdjson_result<SIMDJSON_IMPLE
|
|||||||
if (error()) { return error(); }
|
if (error()) { return error(); }
|
||||||
return first.get_string(allow_replacement);
|
return first.get_string(allow_replacement);
|
||||||
}
|
}
|
||||||
|
template <typename string_type>
|
||||||
|
simdjson_inline error_code simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::get_string(string_type& receiver, bool allow_replacement) noexcept {
|
||||||
|
if (error()) { return error(); }
|
||||||
|
return first.get_string(receiver, allow_replacement);
|
||||||
|
}
|
||||||
simdjson_inline simdjson_result<std::string_view> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::get_wobbly_string() noexcept {
|
simdjson_inline simdjson_result<std::string_view> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::get_wobbly_string() noexcept {
|
||||||
if (error()) { return error(); }
|
if (error()) { return error(); }
|
||||||
return first.get_wobbly_string();
|
return first.get_wobbly_string();
|
||||||
@@ -419,6 +448,11 @@ simdjson_inline simdjson_result<std::string_view> simdjson_result<SIMDJSON_IMPLE
|
|||||||
return first.raw_json_token();
|
return first.raw_json_token();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
simdjson_inline simdjson_result<std::string_view> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::raw_json() noexcept {
|
||||||
|
if (error()) { return error(); }
|
||||||
|
return first.raw_json();
|
||||||
|
}
|
||||||
|
|
||||||
simdjson_inline simdjson_result<const char *> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::current_location() noexcept {
|
simdjson_inline simdjson_result<const char *> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::current_location() noexcept {
|
||||||
if (error()) { return error(); }
|
if (error()) { return error(); }
|
||||||
return first.current_location();
|
return first.current_location();
|
||||||
|
|||||||
@@ -38,7 +38,10 @@ public:
|
|||||||
template<typename T> simdjson_inline simdjson_result<T> get() noexcept {
|
template<typename T> simdjson_inline simdjson_result<T> get() noexcept {
|
||||||
// Unless the simdjson library provides an inline implementation, calling this method should
|
// Unless the simdjson library provides an inline implementation, calling this method should
|
||||||
// immediately fail.
|
// immediately fail.
|
||||||
static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library.");
|
static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. "
|
||||||
|
"The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, "
|
||||||
|
"int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), "
|
||||||
|
" get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -132,6 +135,21 @@ public:
|
|||||||
*/
|
*/
|
||||||
simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement = false) noexcept;
|
simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement = false) noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempts to fill the provided std::string reference with the parsed value of the current string.
|
||||||
|
*
|
||||||
|
* The string is guaranteed to be valid UTF-8.
|
||||||
|
*
|
||||||
|
* Important: a value should be consumed once. Calling get_string() twice on the same value
|
||||||
|
* is an error.
|
||||||
|
*
|
||||||
|
* Performance: This method may be slower than get_string() or get_string(bool) because it may need to allocate memory.
|
||||||
|
* We recommend you avoid allocating an std::string unless you need to.
|
||||||
|
*
|
||||||
|
* @returns INCORRECT_TYPE if the JSON value is not a string. Otherwise, we return SUCCESS.
|
||||||
|
*/
|
||||||
|
template <typename string_type>
|
||||||
|
simdjson_inline error_code get_string(string_type& receiver, bool allow_replacement = false) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cast this JSON value to a "wobbly" string.
|
* Cast this JSON value to a "wobbly" string.
|
||||||
@@ -475,9 +493,21 @@ public:
|
|||||||
* - true
|
* - true
|
||||||
* - false
|
* - false
|
||||||
* - null
|
* - null
|
||||||
|
*
|
||||||
|
* See also value::raw_json().
|
||||||
*/
|
*/
|
||||||
simdjson_inline std::string_view raw_json_token() noexcept;
|
simdjson_inline std::string_view raw_json_token() noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a string_view pointing at this value in the JSON document.
|
||||||
|
* If this element is an array or an object, it consumes the array or the object
|
||||||
|
* and returns a string_view instance corresponding to the
|
||||||
|
* array as represented in JSON. It points inside the original document.
|
||||||
|
* If this element is a scalar (string, number, Boolean, null), it returns what
|
||||||
|
* raw_json_token() would return.
|
||||||
|
*/
|
||||||
|
simdjson_inline simdjson_result<std::string_view> raw_json() noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the current location in the document if in bounds.
|
* Returns the current location in the document if in bounds.
|
||||||
*/
|
*/
|
||||||
@@ -602,6 +632,8 @@ public:
|
|||||||
simdjson_inline simdjson_result<double> get_double() noexcept;
|
simdjson_inline simdjson_result<double> get_double() noexcept;
|
||||||
simdjson_inline simdjson_result<double> get_double_in_string() noexcept;
|
simdjson_inline simdjson_result<double> get_double_in_string() noexcept;
|
||||||
simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement = false) noexcept;
|
simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement = false) noexcept;
|
||||||
|
template <typename string_type>
|
||||||
|
simdjson_inline error_code get_string(string_type& receiver, bool allow_replacement = false) noexcept;
|
||||||
simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept;
|
simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept;
|
||||||
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string> get_raw_json_string() noexcept;
|
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string> get_raw_json_string() noexcept;
|
||||||
simdjson_inline simdjson_result<bool> get_bool() noexcept;
|
simdjson_inline simdjson_result<bool> get_bool() noexcept;
|
||||||
@@ -694,6 +726,7 @@ public:
|
|||||||
|
|
||||||
/** @copydoc simdjson_inline std::string_view value::raw_json_token() const noexcept */
|
/** @copydoc simdjson_inline std::string_view value::raw_json_token() const noexcept */
|
||||||
simdjson_inline simdjson_result<std::string_view> raw_json_token() noexcept;
|
simdjson_inline simdjson_result<std::string_view> raw_json_token() noexcept;
|
||||||
|
simdjson_inline simdjson_result<std::string_view> raw_json() noexcept;
|
||||||
|
|
||||||
/** @copydoc simdjson_inline simdjson_result<const char *> current_location() noexcept */
|
/** @copydoc simdjson_inline simdjson_result<const char *> current_location() noexcept */
|
||||||
simdjson_inline simdjson_result<const char *> current_location() noexcept;
|
simdjson_inline simdjson_result<const char *> current_location() noexcept;
|
||||||
|
|||||||
@@ -513,6 +513,14 @@ simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::parse
|
|||||||
simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> value_iterator::get_string(bool allow_replacement) noexcept {
|
simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> value_iterator::get_string(bool allow_replacement) noexcept {
|
||||||
return get_raw_json_string().unescape(json_iter(), allow_replacement);
|
return get_raw_json_string().unescape(json_iter(), allow_replacement);
|
||||||
}
|
}
|
||||||
|
template <typename string_type>
|
||||||
|
simdjson_warn_unused simdjson_inline error_code value_iterator::get_string(string_type& receiver, bool allow_replacement) noexcept {
|
||||||
|
std::string_view content;
|
||||||
|
auto err = get_string(allow_replacement).get(content);
|
||||||
|
if (err) { return err; }
|
||||||
|
receiver = content;
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> value_iterator::get_wobbly_string() noexcept {
|
simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> value_iterator::get_wobbly_string() noexcept {
|
||||||
return get_raw_json_string().unescape_wobbly(json_iter());
|
return get_raw_json_string().unescape_wobbly(json_iter());
|
||||||
}
|
}
|
||||||
@@ -636,6 +644,14 @@ simdjson_inline simdjson_result<number> value_iterator::get_root_number(bool che
|
|||||||
simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> value_iterator::get_root_string(bool check_trailing, bool allow_replacement) noexcept {
|
simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> value_iterator::get_root_string(bool check_trailing, bool allow_replacement) noexcept {
|
||||||
return get_root_raw_json_string(check_trailing).unescape(json_iter(), allow_replacement);
|
return get_root_raw_json_string(check_trailing).unescape(json_iter(), allow_replacement);
|
||||||
}
|
}
|
||||||
|
template <typename string_type>
|
||||||
|
simdjson_warn_unused simdjson_inline error_code value_iterator::get_root_string(string_type& receiver, bool check_trailing, bool allow_replacement) noexcept {
|
||||||
|
std::string_view content;
|
||||||
|
auto err = get_root_string(check_trailing, allow_replacement).get(content);
|
||||||
|
if (err) { return err; }
|
||||||
|
receiver = content;
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> value_iterator::get_root_wobbly_string(bool check_trailing) noexcept {
|
simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> value_iterator::get_root_wobbly_string(bool check_trailing) noexcept {
|
||||||
return get_root_raw_json_string(check_trailing).unescape_wobbly(json_iter());
|
return get_root_raw_json_string(check_trailing).unescape_wobbly(json_iter());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -296,6 +296,8 @@ public:
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement) noexcept;
|
simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement) noexcept;
|
||||||
|
template <typename string_type>
|
||||||
|
simdjson_warn_unused simdjson_inline error_code get_string(string_type& receiver, bool allow_replacement) noexcept;
|
||||||
simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept;
|
simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept;
|
||||||
simdjson_warn_unused simdjson_inline simdjson_result<raw_json_string> get_raw_json_string() noexcept;
|
simdjson_warn_unused simdjson_inline simdjson_result<raw_json_string> get_raw_json_string() noexcept;
|
||||||
simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> get_uint64() noexcept;
|
simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> get_uint64() noexcept;
|
||||||
@@ -312,7 +314,9 @@ public:
|
|||||||
simdjson_warn_unused simdjson_inline simdjson_result<number> get_number() noexcept;
|
simdjson_warn_unused simdjson_inline simdjson_result<number> get_number() noexcept;
|
||||||
|
|
||||||
simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> get_root_string(bool check_trailing, bool allow_replacement) noexcept;
|
simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> get_root_string(bool check_trailing, bool allow_replacement) noexcept;
|
||||||
simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> get_root_wobbly_string(bool check_trailing) noexcept;
|
template <typename string_type>
|
||||||
|
simdjson_warn_unused simdjson_inline error_code get_root_string(string_type& receiver, bool check_trailing, bool allow_replacement) noexcept;
|
||||||
|
simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> get_root_wobbly_string(bool check_trailing) noexcept;
|
||||||
simdjson_warn_unused simdjson_inline simdjson_result<raw_json_string> get_root_raw_json_string(bool check_trailing) noexcept;
|
simdjson_warn_unused simdjson_inline simdjson_result<raw_json_string> get_root_raw_json_string(bool check_trailing) noexcept;
|
||||||
simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> get_root_uint64(bool check_trailing) noexcept;
|
simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> get_root_uint64(bool check_trailing) noexcept;
|
||||||
simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> get_root_uint64_in_string(bool check_trailing) noexcept;
|
simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> get_root_uint64_in_string(bool check_trailing) noexcept;
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ using namespace simd;
|
|||||||
// Holds backslashes and quotes locations.
|
// Holds backslashes and quotes locations.
|
||||||
struct backslash_and_quote {
|
struct backslash_and_quote {
|
||||||
public:
|
public:
|
||||||
static constexpr uint32_t BYTES_PROCESSED = 32;
|
static constexpr uint32_t BYTES_PROCESSED = 64;
|
||||||
simdjson_inline static backslash_and_quote copy_and_find(const uint8_t *src, uint8_t *dst);
|
simdjson_inline static backslash_and_quote copy_and_find(const uint8_t *src, uint8_t *dst);
|
||||||
|
|
||||||
simdjson_inline bool has_quote_first() { return ((bs_bits - 1) & quote_bits) != 0; }
|
simdjson_inline bool has_quote_first() { return ((bs_bits - 1) & quote_bits) != 0; }
|
||||||
|
|||||||
@@ -58,11 +58,8 @@
|
|||||||
|
|
||||||
#if SIMDJSON_IS_32BITS
|
#if SIMDJSON_IS_32BITS
|
||||||
#ifndef SIMDJSON_NO_PORTABILITY_WARNING
|
#ifndef SIMDJSON_NO_PORTABILITY_WARNING
|
||||||
#pragma message("The simdjson library is designed \
|
// In the future, we should allow programmers
|
||||||
for 64-bit processors and it seems that you are not \
|
// to get warning.
|
||||||
compiling for a known 64-bit platform. All fast kernels \
|
|
||||||
will be disabled and performance may be poor. Please \
|
|
||||||
use a 64-bit target such as x64, 64-bit ARM or 64-bit PPC.")
|
|
||||||
#endif // SIMDJSON_NO_PORTABILITY_WARNING
|
#endif // SIMDJSON_NO_PORTABILITY_WARNING
|
||||||
#endif // SIMDJSON_IS_32BITS
|
#endif // SIMDJSON_IS_32BITS
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
#define SIMDJSON_SIMDJSON_VERSION_H
|
#define SIMDJSON_SIMDJSON_VERSION_H
|
||||||
|
|
||||||
/** The version of simdjson being used (major.minor.revision) */
|
/** The version of simdjson being used (major.minor.revision) */
|
||||||
#define SIMDJSON_VERSION "3.2.2"
|
#define SIMDJSON_VERSION "3.5.0"
|
||||||
|
|
||||||
namespace simdjson {
|
namespace simdjson {
|
||||||
enum {
|
enum {
|
||||||
@@ -15,11 +15,11 @@ enum {
|
|||||||
/**
|
/**
|
||||||
* The minor version (major.MINOR.revision) of simdjson being used.
|
* The minor version (major.MINOR.revision) of simdjson being used.
|
||||||
*/
|
*/
|
||||||
SIMDJSON_VERSION_MINOR = 2,
|
SIMDJSON_VERSION_MINOR = 5,
|
||||||
/**
|
/**
|
||||||
* The revision (major.minor.REVISION) of simdjson being used.
|
* The revision (major.minor.REVISION) of simdjson being used.
|
||||||
*/
|
*/
|
||||||
SIMDJSON_VERSION_REVISION = 2
|
SIMDJSON_VERSION_REVISION = 0
|
||||||
};
|
};
|
||||||
} // namespace simdjson
|
} // namespace simdjson
|
||||||
|
|
||||||
|
|||||||
+409
-506
File diff suppressed because it is too large
Load Diff
+931
-84
File diff suppressed because it is too large
Load Diff
@@ -27,6 +27,58 @@ public:
|
|||||||
|
|
||||||
simdjson_inline bit_indexer(uint32_t *index_buf) : tail(index_buf) {}
|
simdjson_inline bit_indexer(uint32_t *index_buf) : tail(index_buf) {}
|
||||||
|
|
||||||
|
#if SIMDJSON_PREFER_REVERSE_BITS
|
||||||
|
/**
|
||||||
|
* ARM lacks a fast trailing zero instruction, but it has a fast
|
||||||
|
* bit reversal instruction and a fast leading zero instruction.
|
||||||
|
* Thus it may be profitable to reverse the bits (once) and then
|
||||||
|
* to rely on a sequence of instructions that call the leading
|
||||||
|
* zero instruction.
|
||||||
|
*
|
||||||
|
* Performance notes:
|
||||||
|
* The chosen routine is not optimal in terms of data dependency
|
||||||
|
* since zero_leading_bit might require two instructions. However,
|
||||||
|
* it tends to minimize the total number of instructions which is
|
||||||
|
* beneficial.
|
||||||
|
*/
|
||||||
|
simdjson_inline void write_index(uint32_t idx, uint64_t& rev_bits, int i) {
|
||||||
|
int lz = leading_zeroes(rev_bits);
|
||||||
|
this->tail[i] = static_cast<uint32_t>(idx) + lz;
|
||||||
|
rev_bits = zero_leading_bit(rev_bits, lz);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
/**
|
||||||
|
* Under recent x64 systems, we often have both a fast trailing zero
|
||||||
|
* instruction and a fast 'clear-lower-bit' instruction so the following
|
||||||
|
* algorithm can be competitive.
|
||||||
|
*/
|
||||||
|
|
||||||
|
simdjson_inline void write_index(uint32_t idx, uint64_t& bits, int i) {
|
||||||
|
this->tail[i] = idx + trailing_zeroes(bits);
|
||||||
|
bits = clear_lowest_bit(bits);
|
||||||
|
}
|
||||||
|
#endif // SIMDJSON_PREFER_REVERSE_BITS
|
||||||
|
|
||||||
|
template <int START, int N>
|
||||||
|
simdjson_inline int write_indexes(uint32_t idx, uint64_t& bits) {
|
||||||
|
write_index(idx, bits, START);
|
||||||
|
SIMDJSON_IF_CONSTEXPR (N > 1) {
|
||||||
|
write_indexes<(N-1>0?START+1:START), (N-1>=0?N-1:1)>(idx, bits);
|
||||||
|
}
|
||||||
|
return START+N;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <int START, int END, int STEP>
|
||||||
|
simdjson_inline int write_indexes_stepped(uint32_t idx, uint64_t& bits, int cnt) {
|
||||||
|
write_indexes<START, STEP>(idx, bits);
|
||||||
|
SIMDJSON_IF_CONSTEXPR ((START+STEP) < END) {
|
||||||
|
if (simdjson_unlikely((START+STEP) < cnt)) {
|
||||||
|
write_indexes_stepped<(START+STEP<END?START+STEP:END), END, STEP>(idx, bits, cnt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ((END-START) % STEP) == 0 ? END : (END-START) - ((END-START) % STEP) + STEP;
|
||||||
|
}
|
||||||
|
|
||||||
// flatten out values in 'bits' assuming that they are are to have values of idx
|
// flatten out values in 'bits' assuming that they are are to have values of idx
|
||||||
// plus their position in the bitvector, and store these indexes at
|
// plus their position in the bitvector, and store these indexes at
|
||||||
// base_ptr[base] incrementing base as we go
|
// base_ptr[base] incrementing base as we go
|
||||||
@@ -44,91 +96,29 @@ public:
|
|||||||
// it helps tremendously.
|
// it helps tremendously.
|
||||||
if (bits == 0)
|
if (bits == 0)
|
||||||
return;
|
return;
|
||||||
#if SIMDJSON_PREFER_REVERSE_BITS
|
|
||||||
/**
|
|
||||||
* ARM lacks a fast trailing zero instruction, but it has a fast
|
|
||||||
* bit reversal instruction and a fast leading zero instruction.
|
|
||||||
* Thus it may be profitable to reverse the bits (once) and then
|
|
||||||
* to rely on a sequence of instructions that call the leading
|
|
||||||
* zero instruction.
|
|
||||||
*
|
|
||||||
* Performance notes:
|
|
||||||
* The chosen routine is not optimal in terms of data dependency
|
|
||||||
* since zero_leading_bit might require two instructions. However,
|
|
||||||
* it tends to minimize the total number of instructions which is
|
|
||||||
* beneficial.
|
|
||||||
*/
|
|
||||||
|
|
||||||
uint64_t rev_bits = reverse_bits(bits);
|
|
||||||
int cnt = static_cast<int>(count_ones(bits));
|
int cnt = static_cast<int>(count_ones(bits));
|
||||||
int i = 0;
|
|
||||||
// Do the first 8 all together
|
|
||||||
for (; i<8; i++) {
|
|
||||||
int lz = leading_zeroes(rev_bits);
|
|
||||||
this->tail[i] = static_cast<uint32_t>(idx) + lz;
|
|
||||||
rev_bits = zero_leading_bit(rev_bits, lz);
|
|
||||||
}
|
|
||||||
// Do the next 8 all together (we hope in most cases it won't happen at all
|
|
||||||
// and the branch is easily predicted).
|
|
||||||
if (simdjson_unlikely(cnt > 8)) {
|
|
||||||
i = 8;
|
|
||||||
for (; i<16; i++) {
|
|
||||||
int lz = leading_zeroes(rev_bits);
|
|
||||||
this->tail[i] = static_cast<uint32_t>(idx) + lz;
|
|
||||||
rev_bits = zero_leading_bit(rev_bits, lz);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
#if SIMDJSON_PREFER_REVERSE_BITS
|
||||||
|
bits = reverse_bits(bits);
|
||||||
|
#endif
|
||||||
|
#ifdef SIMDJSON_STRUCTURAL_INDEXER_STEP
|
||||||
|
static constexpr const int STEP = SIMDJSON_STRUCTURAL_INDEXER_STEP;
|
||||||
|
#else
|
||||||
|
static constexpr const int STEP = 4;
|
||||||
|
#endif
|
||||||
|
static constexpr const int STEP_UNTIL = 24;
|
||||||
|
|
||||||
// Most files don't have 16+ structurals per block, so we take several basically guaranteed
|
write_indexes_stepped<0, STEP_UNTIL, STEP>(idx, bits, cnt);
|
||||||
// branch mispredictions here. 16+ structurals per block means either punctuation ({} [] , :)
|
SIMDJSON_IF_CONSTEXPR (STEP_UNTIL < 64) {
|
||||||
// or the start of a value ("abc" true 123) every four characters.
|
if (simdjson_unlikely(STEP_UNTIL < cnt)) {
|
||||||
if (simdjson_unlikely(cnt > 16)) {
|
for (int i=STEP_UNTIL; i<cnt; i++) {
|
||||||
i = 16;
|
write_index(idx, bits, i);
|
||||||
while (rev_bits != 0) {
|
|
||||||
int lz = leading_zeroes(rev_bits);
|
|
||||||
this->tail[i++] = static_cast<uint32_t>(idx) + lz;
|
|
||||||
rev_bits = zero_leading_bit(rev_bits, lz);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this->tail += cnt;
|
|
||||||
#else // SIMDJSON_PREFER_REVERSE_BITS
|
|
||||||
/**
|
|
||||||
* Under recent x64 systems, we often have both a fast trailing zero
|
|
||||||
* instruction and a fast 'clear-lower-bit' instruction so the following
|
|
||||||
* algorithm can be competitive.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int cnt = static_cast<int>(count_ones(bits));
|
|
||||||
// Do the first 8 all together
|
|
||||||
for (int i=0; i<8; i++) {
|
|
||||||
this->tail[i] = idx + trailing_zeroes(bits);
|
|
||||||
bits = clear_lowest_bit(bits);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do the next 8 all together (we hope in most cases it won't happen at all
|
|
||||||
// and the branch is easily predicted).
|
|
||||||
if (simdjson_unlikely(cnt > 8)) {
|
|
||||||
for (int i=8; i<16; i++) {
|
|
||||||
this->tail[i] = idx + trailing_zeroes(bits);
|
|
||||||
bits = clear_lowest_bit(bits);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Most files don't have 16+ structurals per block, so we take several basically guaranteed
|
|
||||||
// branch mispredictions here. 16+ structurals per block means either punctuation ({} [] , :)
|
|
||||||
// or the start of a value ("abc" true 123) every four characters.
|
|
||||||
if (simdjson_unlikely(cnt > 16)) {
|
|
||||||
int i = 16;
|
|
||||||
do {
|
|
||||||
this->tail[i] = idx + trailing_zeroes(bits);
|
|
||||||
bits = clear_lowest_bit(bits);
|
|
||||||
i++;
|
|
||||||
} while (i < cnt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this->tail += cnt;
|
this->tail += cnt;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
#endif // SIMDJSON_GENERIC_JSON_STRUCTURAL_INDEXER_CUSTOM_BIT_INDEXER
|
#endif // SIMDJSON_GENERIC_JSON_STRUCTURAL_INDEXER_CUSTOM_BIT_INDEXER
|
||||||
|
|
||||||
|
|||||||
@@ -170,14 +170,6 @@ using namespace simd;
|
|||||||
this->error |= this->prev_incomplete;
|
this->error |= this->prev_incomplete;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef SIMDJSON_IF_CONSTEXPR
|
|
||||||
#if SIMDJSON_CPLUSPLUS17
|
|
||||||
#define SIMDJSON_IF_CONSTEXPR if constexpr
|
|
||||||
#else
|
|
||||||
#define SIMDJSON_IF_CONSTEXPR if
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
simdjson_inline void check_next_input(const simd8x64<uint8_t>& input) {
|
simdjson_inline void check_next_input(const simd8x64<uint8_t>& input) {
|
||||||
if(simdjson_likely(is_ascii(input))) {
|
if(simdjson_likely(is_ascii(input))) {
|
||||||
this->error |= this->prev_incomplete;
|
this->error |= this->prev_incomplete;
|
||||||
|
|||||||
@@ -303,15 +303,17 @@ simdjson_warn_unused simdjson_inline error_code json_iterator::visit_root_primit
|
|||||||
}
|
}
|
||||||
template<typename V>
|
template<typename V>
|
||||||
simdjson_warn_unused simdjson_inline error_code json_iterator::visit_primitive(V &visitor, const uint8_t *value) noexcept {
|
simdjson_warn_unused simdjson_inline error_code json_iterator::visit_primitive(V &visitor, const uint8_t *value) noexcept {
|
||||||
|
// Use the fact that most scalars are going to be either strings or numbers.
|
||||||
|
if(*value == '"') {
|
||||||
|
return visitor.visit_string(*this, value);
|
||||||
|
} else if (((*value - '0') < 10) || (*value == '-')) {
|
||||||
|
return visitor.visit_number(*this, value);
|
||||||
|
}
|
||||||
|
// true, false, null are uncommon.
|
||||||
switch (*value) {
|
switch (*value) {
|
||||||
case '"': return visitor.visit_string(*this, value);
|
|
||||||
case 't': return visitor.visit_true_atom(*this, value);
|
case 't': return visitor.visit_true_atom(*this, value);
|
||||||
case 'f': return visitor.visit_false_atom(*this, value);
|
case 'f': return visitor.visit_false_atom(*this, value);
|
||||||
case 'n': return visitor.visit_null_atom(*this, value);
|
case 'n': return visitor.visit_null_atom(*this, value);
|
||||||
case '-':
|
|
||||||
case '0': case '1': case '2': case '3': case '4':
|
|
||||||
case '5': case '6': case '7': case '8': case '9':
|
|
||||||
return visitor.visit_number(*this, value);
|
|
||||||
default:
|
default:
|
||||||
log_error("Non-value found when value was expected!");
|
log_error("Non-value found when value was expected!");
|
||||||
return TAPE_ERROR;
|
return TAPE_ERROR;
|
||||||
|
|||||||
@@ -51,6 +51,10 @@ namespace document_tests {
|
|||||||
simdjson::dom::array array;
|
simdjson::dom::array array;
|
||||||
ASSERT_SUCCESS( parser.parse(smalljson).get(array) );
|
ASSERT_SUCCESS( parser.parse(smalljson).get(array) );
|
||||||
ASSERT_EQUAL( array.size(), 3 );
|
ASSERT_EQUAL( array.size(), 3 );
|
||||||
|
ASSERT_EQUAL( *array.begin() < *array.end(), true );
|
||||||
|
ASSERT_EQUAL( *array.end() < *array.begin(), false );
|
||||||
|
ASSERT_EQUAL( *array.begin() == *array.begin(), true );
|
||||||
|
ASSERT_EQUAL( *array.begin() == *array.end(), false );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool count_object_example() {
|
bool count_object_example() {
|
||||||
@@ -60,6 +64,10 @@ namespace document_tests {
|
|||||||
simdjson::dom::object object;
|
simdjson::dom::object object;
|
||||||
ASSERT_SUCCESS( parser.parse(smalljson).get(object) );
|
ASSERT_SUCCESS( parser.parse(smalljson).get(object) );
|
||||||
ASSERT_EQUAL( object.size(), 3 );
|
ASSERT_EQUAL( object.size(), 3 );
|
||||||
|
ASSERT_EQUAL( (*object.begin()).value < (*object.end()).value, true );
|
||||||
|
ASSERT_EQUAL( (*object.end()).value < (*object.begin()).value, false );
|
||||||
|
ASSERT_EQUAL( (*object.begin()).value == (*object.begin()).value, true );
|
||||||
|
ASSERT_EQUAL( (*object.begin()).value == (*object.end()).value, false );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool padded_with_open_bracket() {
|
bool padded_with_open_bracket() {
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ static bool parse_and_validate(const std::string src, T expected) {
|
|||||||
const padded_string pstr{src};
|
const padded_string pstr{src};
|
||||||
simdjson::dom::parser parser;
|
simdjson::dom::parser parser;
|
||||||
|
|
||||||
if constexpr (std::is_same<int64_t, T>::value) {
|
SIMDJSON_IF_CONSTEXPR (std::is_same<int64_t, T>::value) {
|
||||||
int64_t actual{};
|
int64_t actual{};
|
||||||
ASSERT_SUCCESS( parser.parse(pstr)["key"].get(actual) );
|
ASSERT_SUCCESS( parser.parse(pstr)["key"].get(actual) );
|
||||||
std::cout << std::boolalpha << "test: " << (expected == actual) << std::endl;
|
std::cout << std::boolalpha << "test: " << (expected == actual) << std::endl;
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ add_cpp_test(ondemand_ordering_tests LABELS ondemand acceptance per_impl
|
|||||||
add_cpp_test(ondemand_parse_api_tests LABELS ondemand acceptance per_implementation)
|
add_cpp_test(ondemand_parse_api_tests LABELS ondemand acceptance per_implementation)
|
||||||
add_cpp_test(ondemand_readme_examples LABELS ondemand acceptance per_implementation)
|
add_cpp_test(ondemand_readme_examples LABELS ondemand acceptance per_implementation)
|
||||||
add_cpp_test(ondemand_scalar_tests LABELS ondemand acceptance per_implementation)
|
add_cpp_test(ondemand_scalar_tests LABELS ondemand acceptance per_implementation)
|
||||||
|
add_cpp_test(ondemand_to_string LABELS ondemand acceptance per_implementation)
|
||||||
add_cpp_test(ondemand_twitter_tests LABELS ondemand acceptance per_implementation)
|
add_cpp_test(ondemand_twitter_tests LABELS ondemand acceptance per_implementation)
|
||||||
add_cpp_test(ondemand_wrong_type_error_tests LABELS ondemand acceptance per_implementation)
|
add_cpp_test(ondemand_wrong_type_error_tests LABELS ondemand acceptance per_implementation)
|
||||||
add_cpp_test(ondemand_iterate_many_csv LABELS ondemand acceptance per_implementation)
|
add_cpp_test(ondemand_iterate_many_csv LABELS ondemand acceptance per_implementation)
|
||||||
|
|||||||
@@ -144,14 +144,20 @@ namespace parse_api_tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
std::string json = "12";
|
std::string json = "12345642314123421321321321321321312321321321321312";
|
||||||
json.shrink_to_fit();
|
json.shrink_to_fit();
|
||||||
cout << "- string, 0 padding" << endl;
|
cout << "- string, 0 padding" << endl;
|
||||||
ASSERT_ERROR( parser.iterate(json), INSUFFICIENT_PADDING );
|
ASSERT_SUCCESS( parser.iterate(json) );
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
std::string json = "12345642314123421321321321321321312321321321321312";
|
||||||
|
json.shrink_to_fit();
|
||||||
|
cout << "- string, 0 padding" << endl;
|
||||||
|
ASSERT_ERROR( parser.iterate((const std::string&)json), INSUFFICIENT_PADDING );
|
||||||
// It's actually kind of hard to allocate "just enough" capacity, since the string tends
|
// It's actually kind of hard to allocate "just enough" capacity, since the string tends
|
||||||
// to grow more than you tell it to.
|
// to grow more than you tell it to.
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_SUCCEED();
|
TEST_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
#include "simdjson.h"
|
#include "simdjson.h"
|
||||||
#include "test_ondemand.h"
|
#include "test_ondemand.h"
|
||||||
|
#if __cpp_lib_optional >= 201606L
|
||||||
|
#include <optional>
|
||||||
|
#endif
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace simdjson;
|
using namespace simdjson;
|
||||||
using error_code=simdjson::error_code;
|
using error_code=simdjson::error_code;
|
||||||
@@ -20,7 +22,39 @@ bool string2() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool to_string_example_no_except() {
|
||||||
|
TEST_START();
|
||||||
|
auto json = R"({
|
||||||
|
"name": "Daniel",
|
||||||
|
"age": 42
|
||||||
|
})"_padded;
|
||||||
|
ondemand::parser parser;
|
||||||
|
ondemand::document doc;
|
||||||
|
auto err = parser.iterate(json).get(doc);
|
||||||
|
if(err) { return false; }
|
||||||
|
std::string name;
|
||||||
|
err = doc["name"].get_string(name);
|
||||||
|
if(err) { return false; }
|
||||||
|
TEST_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
#if SIMDJSON_EXCEPTIONS
|
#if SIMDJSON_EXCEPTIONS
|
||||||
|
|
||||||
|
|
||||||
|
bool to_string_example() {
|
||||||
|
TEST_START();
|
||||||
|
auto json = R"({
|
||||||
|
"name": "Daniel",
|
||||||
|
"age": 42
|
||||||
|
})"_padded;
|
||||||
|
ondemand::parser parser;
|
||||||
|
ondemand::document doc = parser.iterate(json);
|
||||||
|
std::string name;
|
||||||
|
doc["name"].get_string(name);
|
||||||
|
ASSERT_EQUAL(name, "Daniel");
|
||||||
|
TEST_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
bool gen_raw1() {
|
bool gen_raw1() {
|
||||||
TEST_START();
|
TEST_START();
|
||||||
simdjson::ondemand::parser parser;
|
simdjson::ondemand::parser parser;
|
||||||
@@ -73,6 +107,144 @@ bool at_end() {
|
|||||||
TEST_SUCCEED();
|
TEST_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool examplecrt() {
|
||||||
|
TEST_START();
|
||||||
|
padded_string padded_input_json = R"([
|
||||||
|
{ "monitor": [
|
||||||
|
{ "id": "monitor", "type": "toggle", "label": "monitor" },
|
||||||
|
{ "id": "profile", "type": "selector", "label": "collection" },
|
||||||
|
{ "id": "overlay", "type": "selector", "label": "overlay" },
|
||||||
|
{ "id": "zoom", "type": "toggleSlider", "label": "zoom" }
|
||||||
|
] },
|
||||||
|
|
||||||
|
{ "crt": [
|
||||||
|
{ "id": "system", "type": "multi", "label": "system", "choices": "PAL, NTSC" },
|
||||||
|
{ "type": "spacer" },
|
||||||
|
{ "id": "brightness", "type": "slider", "icon": "brightness" },
|
||||||
|
{ "id": "contrast", "type": "slider", "icon": "contrast" },
|
||||||
|
{ "id": "saturation", "type": "slider", "icon": "saturation" },
|
||||||
|
{ "type": "spacer" },
|
||||||
|
{ "id": "overscan", "type": "toggleSlider", "label": "overscan" },
|
||||||
|
{ "type": "spacer" },
|
||||||
|
{ "id": "emulation", "type": "toggle", "label": "CRT emulation" },
|
||||||
|
{ "type": "spacer" },
|
||||||
|
{ "id": "curve", "type": "toggleSlider", "label": "curve" },
|
||||||
|
{ "id": "bleed", "type": "toggleSlider", "label": "bleed" },
|
||||||
|
{ "id": "vignette", "type": "toggleSlider", "label": "vignette" },
|
||||||
|
{ "id": "scanlines", "type": "toggleSlider", "label": "scanlines" },
|
||||||
|
{ "id": "gridlines", "type": "toggleSlider", "label": "gridlines" },
|
||||||
|
{ "id": "glow", "type": "toggleSlider", "label": "glow" },
|
||||||
|
{ "id": "flicker", "type": "toggleSlider", "label": "flicker" },
|
||||||
|
{ "id": "noise", "type": "toggleSlider", "label": "noise" },
|
||||||
|
{}
|
||||||
|
] }
|
||||||
|
])"_padded;
|
||||||
|
auto parser = ondemand::parser{};
|
||||||
|
auto doc = parser.iterate(padded_input_json);
|
||||||
|
auto root_array = doc.get_array();
|
||||||
|
// the root should be an object, not an array, but that's the JSON we are
|
||||||
|
// given.
|
||||||
|
for (ondemand::object node : root_array) {
|
||||||
|
// We know that we are going to have just one element in the object.
|
||||||
|
for (auto field : node) {
|
||||||
|
std::cout << "\n\ntop level:" << field.key() << std::endl;
|
||||||
|
// You can get a proper std::string_view for the key with:
|
||||||
|
// std::string_view key = field.unescaped_key();
|
||||||
|
// and second for-range loop to get child-elements here
|
||||||
|
for (ondemand::object inner_object : field.value()) {
|
||||||
|
auto i = inner_object.begin();
|
||||||
|
if (i == inner_object.end()) {
|
||||||
|
std::cout << "empty object" << std::endl;
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
for (; i != inner_object.end(); ++i) {
|
||||||
|
auto inner_field = *i;
|
||||||
|
std::cout << '"' << inner_field.key()
|
||||||
|
<< "\" : " << inner_field.value() << ", ";
|
||||||
|
// You can get proper std::string_view for the key and value with:
|
||||||
|
// std::string_view inner_key = field.unescaped_key();
|
||||||
|
// std::string_view value_str = field.value();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::cout << std::endl;
|
||||||
|
}
|
||||||
|
// You can break here if you only want just the first element.
|
||||||
|
// break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TEST_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool examplecrt_realloc() {
|
||||||
|
TEST_START();
|
||||||
|
std::string unpadded_input_json = R"([
|
||||||
|
{ "monitor": [
|
||||||
|
{ "id": "monitor", "type": "toggle", "label": "monitor" },
|
||||||
|
{ "id": "profile", "type": "selector", "label": "collection" },
|
||||||
|
{ "id": "overlay", "type": "selector", "label": "overlay" },
|
||||||
|
{ "id": "zoom", "type": "toggleSlider", "label": "zoom" }
|
||||||
|
] },
|
||||||
|
|
||||||
|
{ "crt": [
|
||||||
|
{ "id": "system", "type": "multi", "label": "system", "choices": "PAL, NTSC" },
|
||||||
|
{ "type": "spacer" },
|
||||||
|
{ "id": "brightness", "type": "slider", "icon": "brightness" },
|
||||||
|
{ "id": "contrast", "type": "slider", "icon": "contrast" },
|
||||||
|
{ "id": "saturation", "type": "slider", "icon": "saturation" },
|
||||||
|
{ "type": "spacer" },
|
||||||
|
{ "id": "overscan", "type": "toggleSlider", "label": "overscan" },
|
||||||
|
{ "type": "spacer" },
|
||||||
|
{ "id": "emulation", "type": "toggle", "label": "CRT emulation" },
|
||||||
|
{ "type": "spacer" },
|
||||||
|
{ "id": "curve", "type": "toggleSlider", "label": "curve" },
|
||||||
|
{ "id": "bleed", "type": "toggleSlider", "label": "bleed" },
|
||||||
|
{ "id": "vignette", "type": "toggleSlider", "label": "vignette" },
|
||||||
|
{ "id": "scanlines", "type": "toggleSlider", "label": "scanlines" },
|
||||||
|
{ "id": "gridlines", "type": "toggleSlider", "label": "gridlines" },
|
||||||
|
{ "id": "glow", "type": "toggleSlider", "label": "glow" },
|
||||||
|
{ "id": "flicker", "type": "toggleSlider", "label": "flicker" },
|
||||||
|
{ "id": "noise", "type": "toggleSlider", "label": "noise" },
|
||||||
|
{}
|
||||||
|
] }
|
||||||
|
])";
|
||||||
|
unpadded_input_json.shrink_to_fit();
|
||||||
|
auto parser = ondemand::parser{};
|
||||||
|
auto doc = parser.iterate(unpadded_input_json);
|
||||||
|
auto root_array = doc.get_array();
|
||||||
|
// the root should be an object, not an array, but that's the JSON we are
|
||||||
|
// given.
|
||||||
|
for (ondemand::object node : root_array) {
|
||||||
|
// We know that we are going to have just one element in the object.
|
||||||
|
for (auto field : node) {
|
||||||
|
std::cout << "\n\ntop level:" << field.key() << std::endl;
|
||||||
|
// You can get a proper std::string_view for the key with:
|
||||||
|
// std::string_view key = field.unescaped_key();
|
||||||
|
// and second for-range loop to get child-elements here
|
||||||
|
for (ondemand::object inner_object : field.value()) {
|
||||||
|
auto i = inner_object.begin();
|
||||||
|
if (i == inner_object.end()) {
|
||||||
|
std::cout << "empty object" << std::endl;
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
for (; i != inner_object.end(); ++i) {
|
||||||
|
auto inner_field = *i;
|
||||||
|
std::cout << '"' << inner_field.key()
|
||||||
|
<< "\" : " << inner_field.value() << ", ";
|
||||||
|
// You can get proper std::string_view for the key and value with:
|
||||||
|
// std::string_view inner_key = field.unescaped_key();
|
||||||
|
// std::string_view value_str = field.value();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::cout << std::endl;
|
||||||
|
}
|
||||||
|
// You can break here if you only want just the first element.
|
||||||
|
// break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TEST_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
bool number_tests() {
|
bool number_tests() {
|
||||||
TEST_START();
|
TEST_START();
|
||||||
ondemand::parser parser;
|
ondemand::parser parser;
|
||||||
@@ -1309,10 +1481,60 @@ bool example1958() {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool to_optional() {
|
||||||
|
TEST_START();
|
||||||
|
auto json = R"({ "foo1": "3.1416" } )"_padded;
|
||||||
|
ondemand::parser parser;
|
||||||
|
ondemand::document doc = parser.iterate(json);
|
||||||
|
#if __cpp_lib_optional >= 201606L
|
||||||
|
std::optional<std::string> value;
|
||||||
|
ASSERT_SUCCESS(doc["foo1"].get_string(value));
|
||||||
|
std::cout << value.value() << std::endl;
|
||||||
|
#else
|
||||||
|
std::string value;
|
||||||
|
ASSERT_SUCCESS(doc["foo1"].get_string(value));
|
||||||
|
std::cout << value << std::endl;
|
||||||
|
#endif
|
||||||
|
TEST_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool value_raw_json_array() {
|
||||||
|
TEST_START();
|
||||||
|
auto json = R"( [1,2,"fds", {"a":1}, [1,344]] )"_padded;
|
||||||
|
ondemand::parser parser;
|
||||||
|
ondemand::document doc = parser.iterate(json);
|
||||||
|
std::string_view expected[] = {"1", "2", "\"fds\"", "{\"a\":1}", "[1,344]"};
|
||||||
|
size_t counter = 0;
|
||||||
|
for(auto array: doc) {
|
||||||
|
std::string_view raw = array.raw_json();
|
||||||
|
ASSERT_EQUAL(raw, expected[counter++]);
|
||||||
|
}
|
||||||
|
TEST_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool value_raw_json_object() {
|
||||||
|
TEST_START();
|
||||||
|
auto json = R"( {"key1":1,"key2":2,"key3":"fds", "key4":{"a":1}, "key5":[1,344]} )"_padded;
|
||||||
|
ondemand::parser parser;
|
||||||
|
ondemand::document doc = parser.iterate(json);
|
||||||
|
std::string_view expected[] = {"1", "2", "\"fds\"", "{\"a\":1}", "[1,344]"};
|
||||||
|
size_t counter = 0;
|
||||||
|
for(auto key_value: doc.get_object()) {
|
||||||
|
std::string_view raw = key_value.value().raw_json();
|
||||||
|
ASSERT_EQUAL(raw, expected[counter++]);
|
||||||
|
}
|
||||||
|
TEST_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
bool run() {
|
bool run() {
|
||||||
return true
|
return true
|
||||||
#if SIMDJSON_EXCEPTIONS
|
#if SIMDJSON_EXCEPTIONS
|
||||||
|
&& to_optional()
|
||||||
|
&& value_raw_json_array() && value_raw_json_object()
|
||||||
&& gen_raw1() && gen_raw2() && gen_raw3()
|
&& gen_raw1() && gen_raw2() && gen_raw3()
|
||||||
&& at_end()
|
&& at_end()
|
||||||
&& example1956() && example1958()
|
&& example1956() && example1958()
|
||||||
@@ -1352,10 +1574,14 @@ bool run() {
|
|||||||
&& current_location_user_error()
|
&& current_location_user_error()
|
||||||
&& current_location_out_of_bounds()
|
&& current_location_out_of_bounds()
|
||||||
&& current_location_no_error()
|
&& current_location_no_error()
|
||||||
|
&& to_string_example_no_except()
|
||||||
#if SIMDJSON_EXCEPTIONS
|
#if SIMDJSON_EXCEPTIONS
|
||||||
|
&& to_string_example()
|
||||||
&& raw_string()
|
&& raw_string()
|
||||||
&& number_tests()
|
&& number_tests()
|
||||||
&& current_location_tape_error_with_except()
|
&& current_location_tape_error_with_except()
|
||||||
|
&& examplecrt()
|
||||||
|
&& examplecrt_realloc()
|
||||||
#endif
|
#endif
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,210 @@
|
|||||||
|
#include "simdjson.h"
|
||||||
|
#include "test_ondemand.h"
|
||||||
|
|
||||||
|
using namespace simdjson;
|
||||||
|
|
||||||
|
namespace json_package_tests {
|
||||||
|
using namespace std;
|
||||||
|
bool baby() {
|
||||||
|
TEST_START();
|
||||||
|
auto json = R"({
|
||||||
|
"name": "Daniel",
|
||||||
|
"age": 42
|
||||||
|
})"_padded;
|
||||||
|
ondemand::parser parser;
|
||||||
|
ondemand::document doc;
|
||||||
|
ASSERT_SUCCESS(parser.iterate(json).get(doc));
|
||||||
|
|
||||||
|
simdjson::ondemand::object main_object;
|
||||||
|
ASSERT_SUCCESS(doc.get_object().get(main_object));
|
||||||
|
std::string name;
|
||||||
|
ASSERT_SUCCESS(main_object["name"].get_string(name));
|
||||||
|
ASSERT_EQUAL(name, "Daniel");
|
||||||
|
uint64_t age;
|
||||||
|
ASSERT_SUCCESS(main_object["age"].get_uint64().get(age));
|
||||||
|
ASSERT_EQUAL(age, 42);
|
||||||
|
TEST_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool thirtysecondsofcode() {
|
||||||
|
TEST_START();
|
||||||
|
auto json = R"({
|
||||||
|
"name": "30-seconds-of-code",
|
||||||
|
"private": true,
|
||||||
|
"version": "10.0.0",
|
||||||
|
"description": "30 seconds of code website.",
|
||||||
|
"exports": "./index.js",
|
||||||
|
"author": "chalarangelo",
|
||||||
|
"type": "module",
|
||||||
|
"devDependencies": {
|
||||||
|
"@jsiqle/core": "^3.0.0",
|
||||||
|
"astro": "^3.2.0",
|
||||||
|
"chalk": "^5.3.0",
|
||||||
|
"eslint": "^8.50.0",
|
||||||
|
"eslint-config-prettier": "^9.0.0",
|
||||||
|
"front-matter": "^4.0.2",
|
||||||
|
"fs-extra": "^11.1.1",
|
||||||
|
"glob": "^10.3.10",
|
||||||
|
"hast-util-to-html": "^9.0.0",
|
||||||
|
"js-yaml": "^4.1.0",
|
||||||
|
"mdast-util-to-hast": "^13.0.2",
|
||||||
|
"prettier": "^3.0.3",
|
||||||
|
"prettier-plugin-astro": "^0.12.0",
|
||||||
|
"prismjs": "^1.29.0",
|
||||||
|
"remark": "^15.0.1",
|
||||||
|
"remark-gfm": "^4.0.0",
|
||||||
|
"sass": "^1.68.0",
|
||||||
|
"sharp": "^0.32.6",
|
||||||
|
"unist-util-select": "^5.0.0",
|
||||||
|
"unist-util-visit": "^5.0.0",
|
||||||
|
"unist-util-visit-parents": "^6.0.1",
|
||||||
|
"webfonts-generator": "^0.4.0"
|
||||||
|
},
|
||||||
|
"imports": {
|
||||||
|
"#blocks/*": "./src/blocks/*.js",
|
||||||
|
"#components/*": "./src/components/*.astro",
|
||||||
|
"#layouts/*": "./src/layouts/*.astro",
|
||||||
|
"#settings/*": "./src/settings/*.js",
|
||||||
|
"#prefabs": "./src/prefabs/index.js",
|
||||||
|
"#utils": "./src/utils/index.js",
|
||||||
|
"#utils/search": "./src/utils/search.js"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"predev": "NODE_ENV=development node ./src/scripts/develop.js",
|
||||||
|
"dev": "astro dev --port 8000",
|
||||||
|
"start": "astro dev --port 8000",
|
||||||
|
"prebuild": "NODE_ENV=production node ./src/scripts/build.js",
|
||||||
|
"build": "astro build",
|
||||||
|
"preview": "astro preview --port 9000",
|
||||||
|
"watch": "NODE_ENV=development node ./src/scripts/watch.js",
|
||||||
|
"console": "NODE_ENV=production node ./src/scripts/console.js",
|
||||||
|
"create": "NODE_ENV=production node ./src/scripts/create.js",
|
||||||
|
"icons": "NODE_ENV=production node ./src/scripts/icons.js",
|
||||||
|
"manifest": "NODE_ENV=production node ./src/scripts/manifest.js"
|
||||||
|
},
|
||||||
|
"license": "MIT",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/30-seconds/30-seconds-of-code"
|
||||||
|
},
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/30-seconds/30-seconds-of-code/issues"
|
||||||
|
},
|
||||||
|
"browserslist": [
|
||||||
|
"> 0.5% and last 4 versions and not dead and not ie>0 and not op_mini all and not and_uc>0 and not edge<79"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18.14.2"
|
||||||
|
}
|
||||||
|
})"_padded;
|
||||||
|
ondemand::parser parser;
|
||||||
|
ondemand::document doc;
|
||||||
|
ASSERT_SUCCESS(parser.iterate(json).get(doc));
|
||||||
|
|
||||||
|
simdjson::ondemand::object main_object;
|
||||||
|
ASSERT_SUCCESS(doc.get_object().get(main_object));
|
||||||
|
|
||||||
|
simdjson::ondemand::raw_json_string key;
|
||||||
|
simdjson::ondemand::value value;
|
||||||
|
|
||||||
|
for (auto field : main_object) {
|
||||||
|
// Throw error if getting key or value fails.
|
||||||
|
ASSERT_SUCCESS(field.key().get(key));
|
||||||
|
ASSERT_SUCCESS(field.value().get(value));
|
||||||
|
|
||||||
|
if (key == "name") {
|
||||||
|
std::string name;
|
||||||
|
ASSERT_SUCCESS(value.get_string(name));
|
||||||
|
ASSERT_EQUAL(name, "30-seconds-of-code");
|
||||||
|
} else if (key == "main") {
|
||||||
|
std::string main;
|
||||||
|
ASSERT_SUCCESS(value.get_string(main));
|
||||||
|
// unused
|
||||||
|
} else if (key == "exports") {
|
||||||
|
simdjson::ondemand::json_type exports_type;
|
||||||
|
if (!value.type().get(exports_type)) {
|
||||||
|
std::string_view exports;
|
||||||
|
switch (exports_type) {
|
||||||
|
case simdjson::ondemand::json_type::object: {
|
||||||
|
simdjson::ondemand::object exports_object;
|
||||||
|
if (!value.get_object().get(exports_object) &&
|
||||||
|
!exports_object.raw_json().get(exports)) {
|
||||||
|
// unused
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case simdjson::ondemand::json_type::array: {
|
||||||
|
simdjson::ondemand::array exports_array;
|
||||||
|
if (!value.get_array().get(exports_array) &&
|
||||||
|
!exports_array.raw_json().get(exports)) {
|
||||||
|
// unused
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case simdjson::ondemand::json_type::string: {
|
||||||
|
if (!value.get_string().get(exports)) {
|
||||||
|
ASSERT_EQUAL(exports, "./index.js");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (key == "imports") {
|
||||||
|
simdjson::ondemand::json_type imports_type;
|
||||||
|
if (!value.type().get(imports_type)) {
|
||||||
|
std::string_view imports;
|
||||||
|
switch (imports_type) {
|
||||||
|
case simdjson::ondemand::json_type::object: {
|
||||||
|
simdjson::ondemand::object imports_object;
|
||||||
|
if (!value.get_object().get(imports_object) &&
|
||||||
|
!imports_object.raw_json().get(imports)) {
|
||||||
|
ASSERT_EQUAL(imports, R"({
|
||||||
|
"#blocks/*": "./src/blocks/*.js",
|
||||||
|
"#components/*": "./src/components/*.astro",
|
||||||
|
"#layouts/*": "./src/layouts/*.astro",
|
||||||
|
"#settings/*": "./src/settings/*.js",
|
||||||
|
"#prefabs": "./src/prefabs/index.js",
|
||||||
|
"#utils": "./src/utils/index.js",
|
||||||
|
"#utils/search": "./src/utils/search.js"
|
||||||
|
})");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case simdjson::ondemand::json_type::array: {
|
||||||
|
simdjson::ondemand::array imports_array;
|
||||||
|
if (!value.get_array().get(imports_array) &&
|
||||||
|
!imports_array.raw_json().get(imports)) {
|
||||||
|
// unused
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case simdjson::ondemand::json_type::string: {
|
||||||
|
if (!value.get_string().get(imports)) {
|
||||||
|
// unused
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (key == "type") {
|
||||||
|
std::string_view type;
|
||||||
|
if (!value.get_string().get(type) &&
|
||||||
|
(type == "commonjs" || type == "module")) {
|
||||||
|
ASSERT_EQUAL(type, "module");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TEST_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool run() { return thirtysecondsofcode() && baby(); }
|
||||||
|
|
||||||
|
} // namespace json_package_tests
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
return test_main(argc, argv, json_package_tests::run);
|
||||||
|
}
|
||||||
@@ -167,8 +167,6 @@ print("the commandline is {}".format(cp.args))
|
|||||||
if(cp.returncode != 0):
|
if(cp.returncode != 0):
|
||||||
print("Failed to run doxygen")
|
print("Failed to run doxygen")
|
||||||
|
|
||||||
#ipe = subprocess.Popen(["doxygen"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, cwd=maindir)
|
|
||||||
#doxygenresult = pipe.communicate()[0].decode().strip()
|
|
||||||
|
|
||||||
pattern = re.compile("https://simdjson.org/api/(\d+\.\d+\.\d+)/index.html")
|
pattern = re.compile("https://simdjson.org/api/(\d+\.\d+\.\d+)/index.html")
|
||||||
readmefile = maindir + os.sep + "README.md"
|
readmefile = maindir + os.sep + "README.md"
|
||||||
|
|||||||
Reference in New Issue
Block a user