mirror of
https://github.com/simdjson/simdjson
synced 2026-06-08 17:27:07 +00:00
Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5be57348c4 | |||
| 8955c2c6d5 | |||
| 73e69a5e84 | |||
| fb83b114ef | |||
| 542cd7af71 | |||
| 769364abb2 | |||
| f25d5f9fc2 | |||
| 12fb30ae9c | |||
| c0a952687d | |||
| 307ddd4415 | |||
| 21657455ed | |||
| afb1c9f4b1 | |||
| 9973f7b3a3 | |||
| 18d612df15 | |||
| bddb23177e | |||
| 2c5de6c6ed | |||
| 844e5eac23 | |||
| 45caa861cd | |||
| 50bf372d3f |
@@ -22,4 +22,4 @@ jobs:
|
|||||||
- name: Build
|
- name: Build
|
||||||
run: cmake --build build -j=2
|
run: cmake --build build -j=2
|
||||||
- name: Test
|
- name: Test
|
||||||
run: ctest --output-on-failure --test-dir build
|
run: ctest --output-on-failure --test-dir build
|
||||||
|
|||||||
+135
-90
@@ -12,7 +12,7 @@ endif()
|
|||||||
project(
|
project(
|
||||||
simdjson
|
simdjson
|
||||||
# The version number is modified by tools/release.py
|
# The version number is modified by tools/release.py
|
||||||
VERSION 4.4.2
|
VERSION 4.6.1
|
||||||
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
|
||||||
@@ -29,8 +29,8 @@ 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 "31.0.0" CACHE STRING "simdjson library version")
|
set(SIMDJSON_LIB_VERSION "33.0.0" CACHE STRING "simdjson library version")
|
||||||
set(SIMDJSON_LIB_SOVERSION "31" CACHE STRING "simdjson library soversion")
|
set(SIMDJSON_LIB_SOVERSION "33" CACHE STRING "simdjson library soversion")
|
||||||
|
|
||||||
option(SIMDJSON_BUILD_STATIC_LIB "Build simdjson_static library along with simdjson (only makes sense if BUILD_SHARED_LIBS=ON)" OFF)
|
option(SIMDJSON_BUILD_STATIC_LIB "Build simdjson_static library along with simdjson (only makes sense if BUILD_SHARED_LIBS=ON)" OFF)
|
||||||
if(SIMDJSON_BUILD_STATIC_LIB AND NOT BUILD_SHARED_LIBS)
|
if(SIMDJSON_BUILD_STATIC_LIB AND NOT BUILD_SHARED_LIBS)
|
||||||
@@ -76,9 +76,12 @@ if(SIMDJSON_DEVELOPMENT_CHECKS)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(is_top_project)
|
if(is_top_project)
|
||||||
|
option(SIMDJSON_INSTALL "Enable target install" ON)
|
||||||
option(SIMDJSON_DEVELOPER_MODE "Enable targets for developing simdjson" OFF)
|
option(SIMDJSON_DEVELOPER_MODE "Enable targets for developing simdjson" OFF)
|
||||||
option(BUILD_SHARED_LIBS "Build simdjson as a shared library" OFF)
|
option(BUILD_SHARED_LIBS "Build simdjson as a shared library" OFF)
|
||||||
option(SIMDJSON_SINGLEHEADER "Disable singleheader generation" ON)
|
option(SIMDJSON_SINGLEHEADER "Disable singleheader generation" ON)
|
||||||
|
else()
|
||||||
|
option(SIMDJSON_INSTALL "Enable target install" ${BUILD_SHARED_LIBS})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
include(cmake/handle-deprecations.cmake)
|
include(cmake/handle-deprecations.cmake)
|
||||||
@@ -92,13 +95,16 @@ add_library(simdjson ${SIMDJSON_SOURCES})
|
|||||||
add_library(simdjson::simdjson ALIAS simdjson)
|
add_library(simdjson::simdjson ALIAS simdjson)
|
||||||
set(SIMDJSON_LIBRARIES simdjson)
|
set(SIMDJSON_LIBRARIES simdjson)
|
||||||
|
|
||||||
|
# Check for <bit> header compatibility
|
||||||
|
include(CheckIncludeFileCXX)
|
||||||
|
check_include_file_cxx(bit SIMDJSON_HAS_BIT_HEADER)
|
||||||
|
|
||||||
# Enable precompiled headers for faster builds
|
# Enable precompiled headers for faster builds
|
||||||
if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.16")
|
if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.16")
|
||||||
target_precompile_headers(simdjson PRIVATE
|
set(SIMDJSON_PRECOMPILE_HEADERS
|
||||||
<algorithm>
|
<algorithm>
|
||||||
<array>
|
<array>
|
||||||
<atomic>
|
<atomic>
|
||||||
<bit>
|
|
||||||
<cassert>
|
<cassert>
|
||||||
<cctype>
|
<cctype>
|
||||||
<cerrno>
|
<cerrno>
|
||||||
@@ -111,6 +117,12 @@ if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.16")
|
|||||||
<utility>
|
<utility>
|
||||||
<vector>
|
<vector>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if(SIMDJSON_HAS_BIT_HEADER)
|
||||||
|
list(APPEND SIMDJSON_PRECOMPILE_HEADERS <bit>)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
target_precompile_headers(simdjson PRIVATE ${SIMDJSON_PRECOMPILE_HEADERS})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(SIMDJSON_BUILD_STATIC_LIB)
|
if(SIMDJSON_BUILD_STATIC_LIB)
|
||||||
@@ -155,13 +167,37 @@ if(MSVC)
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if(SIMDJSON_STATIC_REFLECTION)
|
if(SIMDJSON_STATIC_REFLECTION)
|
||||||
|
|
||||||
|
|
||||||
|
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_CXX_COMPILER_VERSION MATCHES "^21")
|
||||||
|
execute_process(
|
||||||
|
COMMAND ${CMAKE_CXX_COMPILER} --version
|
||||||
|
OUTPUT_VARIABLE CLANG_VERSION_OUTPUT
|
||||||
|
ERROR_VARIABLE CLANG_VERSION_ERROR
|
||||||
|
RESULT_VARIABLE CLANG_VERSION_RESULT
|
||||||
|
)
|
||||||
|
if(CLANG_VERSION_RESULT EQUAL 0 AND CLANG_VERSION_OUTPUT MATCHES "https://github.com/bloomberg/clang-p2996.git")
|
||||||
|
set(IS_BLOOMBERG_P2996_CLANG ON)
|
||||||
|
message(STATUS "Using Bloomberg P2996 Clang fork")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
# We would like to require C++26, but no compiler supports that!
|
# We would like to require C++26, but no compiler supports that!
|
||||||
# This is a hack:
|
# This is a hack:
|
||||||
|
if(IS_BLOOMBERG_P2996_CLANG)
|
||||||
simdjson_add_props(
|
simdjson_add_props(
|
||||||
target_compile_options PUBLIC
|
target_compile_options PUBLIC
|
||||||
-freflection -fexpansion-statements -stdlib=libc++ -std=c++26
|
-freflection -fexpansion-statements -stdlib=libc++ -std=c++26
|
||||||
)
|
)
|
||||||
|
else()
|
||||||
|
simdjson_add_props(
|
||||||
|
target_compile_options PUBLIC
|
||||||
|
-freflection -std=c++26
|
||||||
|
)
|
||||||
|
endif()
|
||||||
else()
|
else()
|
||||||
simdjson_add_props(target_compile_features PUBLIC cxx_std_11)
|
simdjson_add_props(target_compile_features PUBLIC cxx_std_11)
|
||||||
endif()
|
endif()
|
||||||
@@ -216,87 +252,89 @@ endif()
|
|||||||
|
|
||||||
# ---- Install rules ----
|
# ---- Install rules ----
|
||||||
|
|
||||||
include(CMakePackageConfigHelpers)
|
if(SIMDJSON_INSTALL)
|
||||||
include(GNUInstallDirs)
|
include(CMakePackageConfigHelpers)
|
||||||
|
include(GNUInstallDirs)
|
||||||
|
|
||||||
if(SIMDJSON_SINGLEHEADER)
|
if(SIMDJSON_SINGLEHEADER)
|
||||||
install(
|
install(
|
||||||
FILES singleheader/simdjson.h
|
FILES singleheader/simdjson.h
|
||||||
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
|
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
|
||||||
COMPONENT simdjson_Development
|
COMPONENT simdjson_Development
|
||||||
)
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
install(
|
||||||
|
TARGETS simdjson
|
||||||
|
EXPORT simdjsonTargets
|
||||||
|
RUNTIME COMPONENT simdjson_Runtime
|
||||||
|
LIBRARY COMPONENT simdjson_Runtime
|
||||||
|
NAMELINK_COMPONENT simdjson_Development
|
||||||
|
ARCHIVE COMPONENT simdjson_Development
|
||||||
|
INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
|
||||||
|
)
|
||||||
|
configure_file(cmake/simdjson-config.cmake.in simdjson-config.cmake @ONLY)
|
||||||
|
|
||||||
|
write_basic_package_version_file(
|
||||||
|
simdjson-config-version.cmake
|
||||||
|
COMPATIBILITY SameMinorVersion
|
||||||
|
)
|
||||||
|
|
||||||
|
set(
|
||||||
|
SIMDJSON_INSTALL_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/cmake/simdjson"
|
||||||
|
CACHE STRING "CMake package config location relative to the install prefix"
|
||||||
|
)
|
||||||
|
mark_as_advanced(SIMDJSON_INSTALL_CMAKEDIR)
|
||||||
|
|
||||||
|
install(
|
||||||
|
FILES
|
||||||
|
"${PROJECT_BINARY_DIR}/simdjson-config.cmake"
|
||||||
|
"${PROJECT_BINARY_DIR}/simdjson-config-version.cmake"
|
||||||
|
DESTINATION "${SIMDJSON_INSTALL_CMAKEDIR}"
|
||||||
|
COMPONENT simdjson_Development
|
||||||
|
)
|
||||||
|
|
||||||
|
install(
|
||||||
|
EXPORT simdjsonTargets
|
||||||
|
NAMESPACE simdjson::
|
||||||
|
DESTINATION "${SIMDJSON_INSTALL_CMAKEDIR}"
|
||||||
|
COMPONENT simdjson_Development
|
||||||
|
)
|
||||||
|
|
||||||
|
if(SIMDJSON_BUILD_STATIC_LIB)
|
||||||
|
install(
|
||||||
|
TARGETS simdjson_static
|
||||||
|
EXPORT simdjson_staticTargets
|
||||||
|
ARCHIVE COMPONENT simdjson_Development
|
||||||
|
INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
|
||||||
|
)
|
||||||
|
install(
|
||||||
|
EXPORT simdjson_staticTargets
|
||||||
|
NAMESPACE simdjson::
|
||||||
|
DESTINATION "${SIMDJSON_INSTALL_CMAKEDIR}"
|
||||||
|
COMPONENT simdjson_Development
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# pkg-config
|
||||||
|
include(cmake/JoinPaths.cmake)
|
||||||
|
join_paths(PKGCONFIG_INCLUDEDIR "\${prefix}" "${CMAKE_INSTALL_INCLUDEDIR}")
|
||||||
|
join_paths(PKGCONFIG_LIBDIR "\${prefix}" "${CMAKE_INSTALL_LIBDIR}")
|
||||||
|
|
||||||
|
if(SIMDJSON_ENABLE_THREADS)
|
||||||
|
set(PKGCONFIG_CFLAGS "-DSIMDJSON_THREADS_ENABLED=1")
|
||||||
|
if(CMAKE_THREAD_LIBS_INIT)
|
||||||
|
set(PKGCONFIG_LIBS_PRIVATE "Libs.private: ${CMAKE_THREAD_LIBS_INIT}")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
configure_file("simdjson.pc.in" "simdjson.pc" @ONLY)
|
||||||
|
install(
|
||||||
|
FILES "${CMAKE_CURRENT_BINARY_DIR}/simdjson.pc"
|
||||||
|
DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig"
|
||||||
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
install(
|
|
||||||
TARGETS simdjson
|
|
||||||
EXPORT simdjsonTargets
|
|
||||||
RUNTIME COMPONENT simdjson_Runtime
|
|
||||||
LIBRARY COMPONENT simdjson_Runtime
|
|
||||||
NAMELINK_COMPONENT simdjson_Development
|
|
||||||
ARCHIVE COMPONENT simdjson_Development
|
|
||||||
INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
|
|
||||||
)
|
|
||||||
configure_file(cmake/simdjson-config.cmake.in simdjson-config.cmake @ONLY)
|
|
||||||
|
|
||||||
write_basic_package_version_file(
|
|
||||||
simdjson-config-version.cmake
|
|
||||||
COMPATIBILITY SameMinorVersion
|
|
||||||
)
|
|
||||||
|
|
||||||
set(
|
|
||||||
SIMDJSON_INSTALL_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/cmake/simdjson"
|
|
||||||
CACHE STRING "CMake package config location relative to the install prefix"
|
|
||||||
)
|
|
||||||
mark_as_advanced(SIMDJSON_INSTALL_CMAKEDIR)
|
|
||||||
|
|
||||||
install(
|
|
||||||
FILES
|
|
||||||
"${PROJECT_BINARY_DIR}/simdjson-config.cmake"
|
|
||||||
"${PROJECT_BINARY_DIR}/simdjson-config-version.cmake"
|
|
||||||
DESTINATION "${SIMDJSON_INSTALL_CMAKEDIR}"
|
|
||||||
COMPONENT simdjson_Development
|
|
||||||
)
|
|
||||||
|
|
||||||
install(
|
|
||||||
EXPORT simdjsonTargets
|
|
||||||
NAMESPACE simdjson::
|
|
||||||
DESTINATION "${SIMDJSON_INSTALL_CMAKEDIR}"
|
|
||||||
COMPONENT simdjson_Development
|
|
||||||
)
|
|
||||||
|
|
||||||
if(SIMDJSON_BUILD_STATIC_LIB)
|
|
||||||
install(
|
|
||||||
TARGETS simdjson_static
|
|
||||||
EXPORT simdjson_staticTargets
|
|
||||||
ARCHIVE COMPONENT simdjson_Development
|
|
||||||
INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
|
|
||||||
)
|
|
||||||
install(
|
|
||||||
EXPORT simdjson_staticTargets
|
|
||||||
NAMESPACE simdjson::
|
|
||||||
DESTINATION "${SIMDJSON_INSTALL_CMAKEDIR}"
|
|
||||||
COMPONENT simdjson_Development
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# pkg-config
|
|
||||||
include(cmake/JoinPaths.cmake)
|
|
||||||
join_paths(PKGCONFIG_INCLUDEDIR "\${prefix}" "${CMAKE_INSTALL_INCLUDEDIR}")
|
|
||||||
join_paths(PKGCONFIG_LIBDIR "\${prefix}" "${CMAKE_INSTALL_LIBDIR}")
|
|
||||||
|
|
||||||
if(SIMDJSON_ENABLE_THREADS)
|
|
||||||
set(PKGCONFIG_CFLAGS "-DSIMDJSON_THREADS_ENABLED=1")
|
|
||||||
if(CMAKE_THREAD_LIBS_INIT)
|
|
||||||
set(PKGCONFIG_LIBS_PRIVATE "Libs.private: ${CMAKE_THREAD_LIBS_INIT}")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
configure_file("simdjson.pc.in" "simdjson.pc" @ONLY)
|
|
||||||
install(
|
|
||||||
FILES "${CMAKE_CURRENT_BINARY_DIR}/simdjson.pc"
|
|
||||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig"
|
|
||||||
)
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# CPack
|
# CPack
|
||||||
#
|
#
|
||||||
@@ -373,18 +411,25 @@ add_subdirectory(fuzz)
|
|||||||
#
|
#
|
||||||
# Source files should be just ASCII
|
# Source files should be just ASCII
|
||||||
#
|
#
|
||||||
find_program(FIND find)
|
find_program(FIND_CMD find)
|
||||||
find_program(FILE file)
|
find_program(FILE_CMD file)
|
||||||
find_program(GREP grep)
|
find_program(GREP_CMD grep)
|
||||||
if(FIND AND FILE AND GREP)
|
if(FIND_CMD AND FILE_CMD AND GREP_CMD)
|
||||||
add_test(
|
add_test(
|
||||||
NAME just_ascii
|
NAME just_ascii
|
||||||
COMMAND sh -c "\
|
COMMAND sh -c "\
|
||||||
${FIND} include src windows tools singleheader tests examples benchmark \
|
non_ascii=$(${FIND_CMD} include src windows tools singleheader tests examples benchmark \
|
||||||
-path benchmark/checkperf-reference -prune -name '*.h' -o -name '*.cpp' \
|
-path benchmark/checkperf-reference -prune -name '*.h' -o -name '*.cpp' \
|
||||||
-type f -exec ${FILE} '{}' \; | ${GREP} -qv ASCII || exit 0 && exit 1"
|
-type f -exec ${FILE_CMD} '{}' \; | ${GREP_CMD} -v ASCII); \
|
||||||
|
if [ -n \"$non_ascii\" ]; then \
|
||||||
|
echo 'The following files contain non-ASCII characters:'; \
|
||||||
|
echo \"$non_ascii\"; \
|
||||||
|
exit 1; \
|
||||||
|
fi"
|
||||||
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}"
|
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}"
|
||||||
)
|
)
|
||||||
|
else()
|
||||||
|
message(WARNING "just_ascii test disabled because required tools were not found: find='${FIND_CMD}', file='${FILE_CMD}', grep='${GREP_CMD}'")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
##
|
##
|
||||||
|
|||||||
@@ -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 = "4.4.2"
|
PROJECT_NUMBER = "4.6.1"
|
||||||
|
|
||||||
# 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
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ Real-world usage
|
|||||||
- [GreptimeDB](https://github.com/GreptimeTeam/greptimedb)
|
- [GreptimeDB](https://github.com/GreptimeTeam/greptimedb)
|
||||||
- [mamba](https://github.com/mamba-org/mamba)
|
- [mamba](https://github.com/mamba-org/mamba)
|
||||||
- [Ladybird Browser](https://ladybird.org)
|
- [Ladybird Browser](https://ladybird.org)
|
||||||
|
- [SereneDB](https://github.com/serenedb/serenedb)
|
||||||
|
|
||||||
|
|
||||||
If you are planning to use simdjson in a product, please work from one of our releases.
|
If you are planning to use simdjson in a product, please work from one of our releases.
|
||||||
@@ -211,10 +212,16 @@ We have an in-depth paper focused on the UTF-8 validation:
|
|||||||
|
|
||||||
We also have an informal [blog post providing some background and context](https://branchfree.org/2019/02/25/paper-parsing-gigabytes-of-json-per-second/).
|
We also have an informal [blog post providing some background and context](https://branchfree.org/2019/02/25/paper-parsing-gigabytes-of-json-per-second/).
|
||||||
|
|
||||||
For the video inclined, <br />
|
For the video inclined, we had a talk at QCon San Francisco 2019<br />
|
||||||
[](http://www.youtube.com/watch?v=wlvKAT7SZIQ)<br />
|
[](http://www.youtube.com/watch?v=wlvKAT7SZIQ)<br />
|
||||||
(It was the best voted talk, we're kinda proud of it.)
|
(It was the best voted talk, we're kinda proud of it.)
|
||||||
|
|
||||||
|
We also had a CppCon 2025 talk. We show how C++26 reflection allows for one-line serialization (to_json(player)) or deserialization—without invasive macros or manual mapping—using nothing but the C++ standard library. Whether you’re a performance junkie or simply interested in the roadmap for the next decade of C++ development, watch our full talk!
|
||||||
|
|
||||||
|
[](http://www.youtube.com/watch?v=Mcgk3CxHYMs)<br />
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Citing this work
|
Citing this work
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ namespace partial_tweets {
|
|||||||
// {
|
// {
|
||||||
// "created_at": "Sun Aug 31 00:29:15 +0000 2014",
|
// "created_at": "Sun Aug 31 00:29:15 +0000 2014",
|
||||||
// "id": 505874924095815700,
|
// "id": 505874924095815700,
|
||||||
// "text": "@aym0566x \n\n名前:前田あゆみ\n第一印象:なんか怖っ!\n今の印象:とりあえずキモい。噛み合わない\n好きなところ:ぶすでキモいとこ😋✨✨\n思い出:んーーー、ありすぎ😊❤️\nLINE交換できる?:あぁ……ごめん✋\nトプ画をみて:照れますがな😘✨\n一言:お前は一生もんのダチ💖",
|
// "text": "@aym0566x ...",
|
||||||
// "in_reply_to_status_id": null,
|
// "in_reply_to_status_id": null,
|
||||||
// "user": {
|
// "user": {
|
||||||
// "id": 1186275104,
|
// "id": 1186275104,
|
||||||
|
|||||||
Vendored
+1
-1
@@ -12,7 +12,7 @@ cmake_dependent_option(SIMDJSON_GOOGLE_BENCHMARKS "compile the Google Benchmark
|
|||||||
if(SIMDJSON_GOOGLE_BENCHMARKS)
|
if(SIMDJSON_GOOGLE_BENCHMARKS)
|
||||||
CPMAddPackage(
|
CPMAddPackage(
|
||||||
NAME google_benchmarks
|
NAME google_benchmarks
|
||||||
URL https://github.com/google/benchmark/archive/refs/tags/v1.9.4.zip
|
URL https://github.com/google/benchmark/archive/refs/tags/v1.9.5.zip
|
||||||
OPTIONS
|
OPTIONS
|
||||||
"BENCHMARK_ENABLE_TESTING OFF"
|
"BENCHMARK_ENABLE_TESTING OFF"
|
||||||
"BENCHMARK_ENABLE_INSTALL OFF"
|
"BENCHMARK_ENABLE_INSTALL OFF"
|
||||||
|
|||||||
+5
-7
@@ -379,6 +379,8 @@ tracking explicitly potential programming mistakes. Thus you should not relying
|
|||||||
size (`sizeof`) of our data structures to be constant: they may change depending on the
|
size (`sizeof`) of our data structures to be constant: they may change depending on the
|
||||||
compiler settings.
|
compiler settings.
|
||||||
|
|
||||||
|
When `SIMDJSON_DEVELOPMENT_CHECKS` is set at compile time, the global variable `simdjson_development_checks_enabled` is defined as true. It is false otherwise.
|
||||||
|
|
||||||
Once your code has been tested, you can then run it in
|
Once your code has been tested, you can then run it in
|
||||||
Release mode: under Visual Studio, it means having the `_DEBUG` macro undefined, and, for other
|
Release mode: under Visual Studio, it means having the `_DEBUG` macro undefined, and, for other
|
||||||
compilers, it means setting `__OPTIMIZE__` to a positive integer. You can also forcefully
|
compilers, it means setting `__OPTIMIZE__` to a positive integer. You can also forcefully
|
||||||
@@ -436,7 +438,7 @@ support for users who avoid exceptions. See [the simdjson error handling documen
|
|||||||
* **Extracting Values:** You can cast a JSON element to a native type:
|
* **Extracting Values:** You can cast a JSON element to a native type:
|
||||||
`double(element)`. This works for `std::string_view`, double, uint64_t, int64_t, bool,
|
`double(element)`. This works for `std::string_view`, double, uint64_t, int64_t, bool,
|
||||||
ondemand::object and ondemand::array. We also have explicit methods such as `get_string()`, `get_double()`,
|
ondemand::object and ondemand::array. We also have explicit methods such as `get_string()`, `get_double()`,
|
||||||
`get_uint64()`, `get_int64()`, `get_bool()`, `get_object()` and `get_array()`. After a cast or an explicit method,
|
`get_uint64()`, `get_int64()`, `get_uint32()`, `get_int32()`, `get_bool()`, `get_object()` and `get_array()`. After a cast or an explicit method,
|
||||||
the number, string or boolean will be parsed, or the initial `{` or `[` will be verified for `ondemand::object` and `ondemand::array`. An exception may be thrown if
|
the number, string or boolean will be parsed, or the initial `{` or `[` will be verified for `ondemand::object` and `ondemand::array`. An exception may be thrown if
|
||||||
the cast is not possible: the error code is `simdjson::INCORRECT_TYPE` (see [Error handling](#error-handling)). Importantly, when getting an ondemand::object or ondemand::array instance, its content is
|
the cast is not possible: the error code is `simdjson::INCORRECT_TYPE` (see [Error handling](#error-handling)). Importantly, when getting an ondemand::object or ondemand::array instance, its content is
|
||||||
not validated: you are only guaranteed that the corresponding initial character (`{` or `[`) is present. Thus,
|
not validated: you are only guaranteed that the corresponding initial character (`{` or `[`) is present. Thus,
|
||||||
@@ -446,8 +448,8 @@ support for users who avoid exceptions. See [the simdjson error handling documen
|
|||||||
pass `true` (`get_string(true)`) as a parameter to get replacement characters where errors
|
pass `true` (`get_string(true)`) as a parameter to get replacement characters where errors
|
||||||
occur. If you somehow need to access non-UTF-8 strings in a lossless manner
|
occur. If you somehow need to access non-UTF-8 strings in a lossless manner
|
||||||
(e.g., if you strings contain unpaired surrogates), you may use the `get_wobbly_string()` function to get a string in the [WTF-8 format](https://simonsapin.github.io/wtf-8).
|
(e.g., if you strings contain unpaired surrogates), you may use the `get_wobbly_string()` function to get a string in the [WTF-8 format](https://simonsapin.github.io/wtf-8).
|
||||||
When calling `get_uint64()` and `get_int64()`, if the number does not fit in a corresponding
|
When calling `get_uint64()`, `get_int64()`, `get_uint32()` or `get_int32()`, if the number does not fit in the
|
||||||
64-bit integer type, it is also considered an error. When parsing numbers or other scalar values, the library checks
|
corresponding integer type, it is also considered an error (`NUMBER_OUT_OF_RANGE`). When parsing numbers or other scalar values, the library checks
|
||||||
that the value is followed by an expected character, thus you *may* get a number parsing error when accessing the digits
|
that the value is followed by an expected character, thus you *may* get a number parsing error when accessing the digits
|
||||||
as an integer in the following strings: `{"number":12332a`, `{"number":12332\0`, `{"number":12332` (the digits appear at the end). We always abide by the [RFC 8259](https://www.tbray.org/ongoing/When/201x/2017/12/14/rfc8259.html) JSON specification so that, for example, numbers prefixed by the `+` sign are in error.
|
as an integer in the following strings: `{"number":12332a`, `{"number":12332\0`, `{"number":12332` (the digits appear at the end). We always abide by the [RFC 8259](https://www.tbray.org/ongoing/When/201x/2017/12/14/rfc8259.html) JSON specification so that, for example, numbers prefixed by the `+` sign are in error.
|
||||||
|
|
||||||
@@ -1300,10 +1302,6 @@ You can also use the custom `Car` type as part of a template such as `std::vecto
|
|||||||
simdjson::ondemand::parser parser;
|
simdjson::ondemand::parser parser;
|
||||||
simdjson::ondemand::document doc = parser.iterate(json);
|
simdjson::ondemand::document doc = parser.iterate(json);
|
||||||
std::vector<Car> cars(doc);
|
std::vector<Car> cars(doc);
|
||||||
// visual studio users need an explicit call:
|
|
||||||
// std::vector<Car> cars = doc.get<std::vector<Car>>();
|
|
||||||
// because the compiler does not know whether to convert
|
|
||||||
// doc to an unsigned int or to a vector.
|
|
||||||
for(Car& c : cars) {
|
for(Car& c : cars) {
|
||||||
std::cout << c.year << std::endl;
|
std::cout << c.year << std::endl;
|
||||||
}
|
}
|
||||||
|
|||||||
+18
-1
@@ -168,6 +168,23 @@ Once you have an element, you can navigate it with idiomatic C++ iterators, oper
|
|||||||
`SIMDJSON_MINUS_ZERO_AS_FLOAT` to `1` when building simdjson, you can get that `-0` is mapped to `-0.0`
|
`SIMDJSON_MINUS_ZERO_AS_FLOAT` to `1` when building simdjson, you can get that `-0` is mapped to `-0.0`
|
||||||
as in JavaScript. You can get the desired effect by building simdjson with cmake setting the
|
as in JavaScript. You can get the desired effect by building simdjson with cmake setting the
|
||||||
`SIMDJSON_MINUS_ZERO_AS_FLOAT` to on: `cmake -B build -D SIMDJSON_MINUS_ZERO_AS_FLOAT=ON`.
|
`SIMDJSON_MINUS_ZERO_AS_FLOAT` to on: `cmake -B build -D SIMDJSON_MINUS_ZERO_AS_FLOAT=ON`.
|
||||||
|
* **Big Integer Support (opt-in):** By default, integers that exceed the 64-bit range cause parsing to fail with `BIGINT_ERROR`. You can opt in to big integer support so that these numbers are stored as raw digit strings on the tape instead:
|
||||||
|
```cpp
|
||||||
|
simdjson::dom::parser parser;
|
||||||
|
parser.number_as_string(true); // opt-in, default false
|
||||||
|
simdjson::dom::element doc;
|
||||||
|
auto error = parser.parse("[1, 123456789012345678901]"_padded).get(doc);
|
||||||
|
if (error) { std::cerr << error << std::endl; return EXIT_FAILURE; }
|
||||||
|
for (simdjson::dom::element elem : doc) {
|
||||||
|
if (elem.is_bigint()) {
|
||||||
|
std::string_view digits;
|
||||||
|
error = elem.get_bigint().get(digits);
|
||||||
|
if (error) { std::cerr << error << std::endl; return EXIT_FAILURE; }
|
||||||
|
std::cout << "big integer: " << digits << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
When enabled, big integers have type `element_type::BIGINT`. Calling `get_int64()`, `get_uint64()`, or `get_double()` on a big integer returns `INCORRECT_TYPE`. Normal numbers (int64, uint64, double) are unaffected.
|
||||||
* **Field Access:** To get the value of the "foo" field in an object, use `object["foo"]`.
|
* **Field Access:** To get the value of the "foo" field in an object, use `object["foo"]`.
|
||||||
* **Array Iteration:** To iterate through an array, use `for (auto value : array) { ... }`. If you
|
* **Array Iteration:** To iterate through an array, use `for (auto value : array) { ... }`. If you
|
||||||
know the type of the value, you can cast it right there, too! `for (double value : array) { ... }`
|
know the type of the value, you can cast it right there, too! `for (double value : array) { ... }`
|
||||||
@@ -180,7 +197,7 @@ Once you have an element, you can navigate it with idiomatic C++ iterators, oper
|
|||||||
* **Array and Object size** Given an array or an object, you can get its size (number of elements or keys)
|
* **Array and Object size** Given an array or an object, you can get its size (number of elements or keys)
|
||||||
with the `size()` method.
|
with the `size()` method.
|
||||||
* **Checking an Element Type:** You can check an element's type with `element.type()`. It
|
* **Checking an Element Type:** You can check an element's type with `element.type()`. It
|
||||||
returns an `element_type` with values such as `simdjson::dom::element_type::ARRAY`, `simdjson::dom::element_type::OBJECT`, `simdjson::dom::element_type::INT64`, `simdjson::dom::element_type::UINT64`,`simdjson::dom::element_type::DOUBLE`, `simdjson::dom::element_type::STRING`, `simdjson::dom::element_type::BOOL` or, `simdjson::dom::element_type::NULL_VALUE`.
|
returns an `element_type` with values such as `simdjson::dom::element_type::ARRAY`, `simdjson::dom::element_type::OBJECT`, `simdjson::dom::element_type::INT64`, `simdjson::dom::element_type::UINT64`,`simdjson::dom::element_type::DOUBLE`, `simdjson::dom::element_type::STRING`, `simdjson::dom::element_type::BOOL`, `simdjson::dom::element_type::NULL_VALUE` or, `simdjson::dom::element_type::BIGINT` (when big integer support is enabled).
|
||||||
* **Output to streams and strings:** Given a document or an element (or node) out of a JSON document, you can output a minified string version using the C++ stream idiom (`out << element`). You can also request the construction of a minified string version (`simdjson::minify(element)`) or a prettified string version (`simdjson::prettify(element)`). Numbers are serialized as 64-bit floating-point numbers (`double`).
|
* **Output to streams and strings:** Given a document or an element (or node) out of a JSON document, you can output a minified string version using the C++ stream idiom (`out << element`). You can also request the construction of a minified string version (`simdjson::minify(element)`) or a prettified string version (`simdjson::prettify(element)`). Numbers are serialized as 64-bit floating-point numbers (`double`).
|
||||||
|
|
||||||
### Examples
|
### Examples
|
||||||
|
|||||||
@@ -93,6 +93,14 @@ Float values are represented as two 64-bit tape elements:
|
|||||||
|
|
||||||
Performance consideration: We store numbers of the main tape because we believe that locality of reference is helpful for performance.
|
Performance consideration: We store numbers of the main tape because we believe that locality of reference is helpful for performance.
|
||||||
|
|
||||||
|
## Big Integers
|
||||||
|
|
||||||
|
When a JSON integer exceeds the 64-bit range (both signed and unsigned), it is classified as a big integer. By default, parsing returns `BIGINT_ERROR`. When `parser.number_as_string(true)` is set, the raw digits are stored on the string tape using the same format as strings (4-byte little-endian length prefix, followed by the UTF-8 digit bytes, followed by a null terminator).
|
||||||
|
|
||||||
|
A big integer is represented on the main tape as the 64-bit tape element `('Z' << 56) + x` where the payload `x` is the location on the string tape of the null-terminated digit string.
|
||||||
|
|
||||||
|
For example, the JSON value `99999999999999999999` would be stored as the string `"99999999999999999999"` on the string tape, with a `'Z'` tag on the main tape. Negative big integers include the leading minus sign.
|
||||||
|
|
||||||
## Root node
|
## Root node
|
||||||
|
|
||||||
Each JSON document will have two special 64-bit tape elements representing a root node, one at the beginning and one at the end.
|
Each JSON document will have two special 64-bit tape elements representing a root node, one at the beginning and one at the end.
|
||||||
|
|||||||
@@ -54,6 +54,9 @@ static void print_json(std::ostream& os, simdjson::dom::element element) noexcep
|
|||||||
case simdjson::dom::element_type::NULL_VALUE:
|
case simdjson::dom::element_type::NULL_VALUE:
|
||||||
os << "null" << endl;
|
os << "null" << endl;
|
||||||
break;
|
break;
|
||||||
|
case simdjson::dom::element_type::BIGINT:
|
||||||
|
os << element.get_bigint().value_unsafe() << endl;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
|
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
|
||||||
|
|||||||
@@ -297,6 +297,15 @@ namespace std {
|
|||||||
#endif // _MSC_VER
|
#endif // _MSC_VER
|
||||||
#endif // SIMDJSON_DEVELOPMENT_CHECKS
|
#endif // SIMDJSON_DEVELOPMENT_CHECKS
|
||||||
|
|
||||||
|
|
||||||
|
// Prevent ODR violations for the simdjson_development_checks_enabled variable.
|
||||||
|
#if SIMDJSON_DEVELOPMENT_CHECKS
|
||||||
|
extern const bool simdjson_development_checks_enabled = true;
|
||||||
|
#else
|
||||||
|
extern const bool simdjson_development_checks_enabled = false;
|
||||||
|
#endif // SIMDJSON_DEVELOPMENT_CHECKS
|
||||||
|
|
||||||
|
|
||||||
// The SIMDJSON_CHECK_EOF macro is a feature flag for the "don't require padding"
|
// The SIMDJSON_CHECK_EOF macro is a feature flag for the "don't require padding"
|
||||||
// feature.
|
// feature.
|
||||||
|
|
||||||
|
|||||||
@@ -266,6 +266,12 @@ consteval std::pair<double, size_t> parse_double(const char *src,
|
|||||||
}
|
}
|
||||||
} // namespace number_parsing
|
} // namespace number_parsing
|
||||||
|
|
||||||
|
consteval auto make_data_member_options(auto&& name_str) {
|
||||||
|
std::meta::data_member_options options{};
|
||||||
|
options.name = std::forward<decltype(name_str)>(name_str);
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
// JSON string may contain embedded nulls, and C++26 reflection does not yet
|
// JSON string may contain embedded nulls, and C++26 reflection does not yet
|
||||||
// support std::string_view as a data member type. As a workaround, we define
|
// support std::string_view as a data member type. As a workaround, we define
|
||||||
// a custom type that holds a const char* and a size.
|
// a custom type that holds a const char* and a size.
|
||||||
@@ -320,7 +326,8 @@ using class_type = type_builder<meta_info...>::constructed_type;
|
|||||||
/**
|
/**
|
||||||
* @brief Variable template for constructing instances with values
|
* @brief Variable template for constructing instances with values
|
||||||
*/
|
*/
|
||||||
template <typename T, auto... Vs> constexpr auto construct_from = T{Vs...};
|
template <typename T, auto... Vs> constexpr T construct_from = T{Vs...};
|
||||||
|
|
||||||
|
|
||||||
// in JSON, there are only a few whitespace characters that are allowed
|
// in JSON, there are only a few whitespace characters that are allowed
|
||||||
// outside of objects, arrays, strings, and numbers.
|
// outside of objects, arrays, strings, and numbers.
|
||||||
@@ -410,7 +417,7 @@ parse_number(std::string_view json,
|
|||||||
std::from_chars(json.data(), json.data() + json.size(), int_value);
|
std::from_chars(json.data(), json.data() + json.size(), int_value);
|
||||||
if (res.ec == std::errc()) {
|
if (res.ec == std::errc()) {
|
||||||
out = int_value;
|
out = int_value;
|
||||||
if ((res.ptr - json.data()) != scope) {
|
if (static_cast<std::size_t>(res.ptr - json.data()) != scope) {
|
||||||
simdjson_consteval_error(
|
simdjson_consteval_error(
|
||||||
"Internal error: cannot agree on the character range of the float");
|
"Internal error: cannot agree on the character range of the float");
|
||||||
}
|
}
|
||||||
@@ -424,7 +431,7 @@ parse_number(std::string_view json,
|
|||||||
std::from_chars(json.data(), json.data() + json.size(), uint_value);
|
std::from_chars(json.data(), json.data() + json.size(), uint_value);
|
||||||
if (res.ec == std::errc()) {
|
if (res.ec == std::errc()) {
|
||||||
out = uint_value;
|
out = uint_value;
|
||||||
if ((res.ptr - json.data()) != scope) {
|
if (static_cast<std::size_t>(res.ptr - json.data()) != scope) {
|
||||||
simdjson_consteval_error(
|
simdjson_consteval_error(
|
||||||
"Internal error: cannot agree on the character range of the float");
|
"Internal error: cannot agree on the character range of the float");
|
||||||
}
|
}
|
||||||
@@ -533,7 +540,7 @@ parse_string(std::string_view json) {
|
|||||||
// present, we have an error (isolated high surrogate), which we
|
// present, we have an error (isolated high surrogate), which we
|
||||||
// tolerate by substituting the substitution_code_point.
|
// tolerate by substituting the substitution_code_point.
|
||||||
if (end - cursor < 6 || *cursor != '\\' ||
|
if (end - cursor < 6 || *cursor != '\\' ||
|
||||||
*(cursor + 1) != 'u' > 0xFFFF) {
|
*(cursor + 1) != 'u') {
|
||||||
code_point = substitution_code_point;
|
code_point = substitution_code_point;
|
||||||
} else { // we have \u following the high surrogate
|
} else { // we have \u following the high surrogate
|
||||||
cursor += 2; // skip \u
|
cursor += 2; // skip \u
|
||||||
@@ -887,10 +894,19 @@ parse_json_array_impl(const std::string_view json) {
|
|||||||
std::size_t count = values.size() - 1;
|
std::size_t count = values.size() - 1;
|
||||||
// We assume all elements have the same type as the first element.
|
// We assume all elements have the same type as the first element.
|
||||||
// However, if the array is heterogeneous, we should use std::variant.
|
// However, if the array is heterogeneous, we should use std::variant.
|
||||||
|
auto elem_type = std::meta::type_of(values[1]);
|
||||||
|
// String literals reflected via reflect_constant_string have type const
|
||||||
|
// char[N], but when passed as template auto parameters they decay to
|
||||||
|
// const char*. Use const char* as the element type so that
|
||||||
|
// construct_from can aggregate-initialize the array.
|
||||||
|
if (std::meta::is_array_type(elem_type) &&
|
||||||
|
std::meta::remove_all_extents(elem_type) == ^^const char) {
|
||||||
|
elem_type = ^^const char *;
|
||||||
|
}
|
||||||
auto array_type = std::meta::substitute(
|
auto array_type = std::meta::substitute(
|
||||||
^^std::array,
|
^^std::array,
|
||||||
{
|
{
|
||||||
std::meta::type_of(values[1]), std::meta::reflect_constant(count)});
|
elem_type, std::meta::reflect_constant(count)});
|
||||||
|
|
||||||
// Create array instance with values
|
// Create array instance with values
|
||||||
values[0] = array_type;
|
values[0] = array_type;
|
||||||
@@ -957,8 +973,7 @@ parse_json_object_impl(std::string_view json) {
|
|||||||
simdjson_consteval_error("Expected '}'");
|
simdjson_consteval_error("Expected '}'");
|
||||||
}
|
}
|
||||||
cursor += object_size;
|
cursor += object_size;
|
||||||
auto dms = std::meta::data_member_spec(std::meta::type_of(parsed),
|
auto dms = std::meta::data_member_spec(std::meta::type_of(parsed), make_data_member_options(field_name));
|
||||||
{.name = field_name});
|
|
||||||
members.push_back(std::meta::reflect_constant(dms));
|
members.push_back(std::meta::reflect_constant(dms));
|
||||||
values.push_back(parsed);
|
values.push_back(parsed);
|
||||||
|
|
||||||
@@ -967,8 +982,7 @@ parse_json_object_impl(std::string_view json) {
|
|||||||
case '[': {
|
case '[': {
|
||||||
std::string_view value(cursor, end);
|
std::string_view value(cursor, end);
|
||||||
auto [parsed, array_size] = parse_json_array_impl(value);
|
auto [parsed, array_size] = parse_json_array_impl(value);
|
||||||
auto dms = std::meta::data_member_spec(std::meta::type_of(parsed),
|
auto dms = std::meta::data_member_spec(std::meta::type_of(parsed), make_data_member_options(field_name));
|
||||||
{.name = field_name});
|
|
||||||
members.push_back(std::meta::reflect_constant(dms));
|
members.push_back(std::meta::reflect_constant(dms));
|
||||||
values.push_back(parsed);
|
values.push_back(parsed);
|
||||||
if (*(cursor + array_size - 1) != ']') {
|
if (*(cursor + array_size - 1) != ']') {
|
||||||
@@ -989,8 +1003,7 @@ parse_json_object_impl(std::string_view json) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto dms =
|
auto dms =
|
||||||
std::meta::data_member_spec(^^const char *, {
|
std::meta::data_member_spec(^^const char *, make_data_member_options(field_name));
|
||||||
.name = field_name});
|
|
||||||
members.push_back(std::meta::reflect_constant(dms));
|
members.push_back(std::meta::reflect_constant(dms));
|
||||||
values.push_back(std::meta::reflect_constant_string(value));
|
values.push_back(std::meta::reflect_constant_string(value));
|
||||||
break;
|
break;
|
||||||
@@ -1001,8 +1014,7 @@ parse_json_object_impl(std::string_view json) {
|
|||||||
}
|
}
|
||||||
cursor += 4;
|
cursor += 4;
|
||||||
|
|
||||||
auto dms = std::meta::data_member_spec(^^bool, {
|
auto dms = std::meta::data_member_spec(^^bool, make_data_member_options(field_name));
|
||||||
.name = field_name});
|
|
||||||
members.push_back(std::meta::reflect_constant(dms));
|
members.push_back(std::meta::reflect_constant(dms));
|
||||||
values.push_back(std::meta::reflect_constant(true));
|
values.push_back(std::meta::reflect_constant(true));
|
||||||
break;
|
break;
|
||||||
@@ -1013,8 +1025,7 @@ parse_json_object_impl(std::string_view json) {
|
|||||||
}
|
}
|
||||||
cursor += 5;
|
cursor += 5;
|
||||||
|
|
||||||
auto dms = std::meta::data_member_spec(^^bool, {
|
auto dms = std::meta::data_member_spec(^^bool, make_data_member_options(field_name));
|
||||||
.name = field_name});
|
|
||||||
members.push_back(std::meta::reflect_constant(dms));
|
members.push_back(std::meta::reflect_constant(dms));
|
||||||
values.push_back(std::meta::reflect_constant(false));
|
values.push_back(std::meta::reflect_constant(false));
|
||||||
break;
|
break;
|
||||||
@@ -1025,9 +1036,7 @@ parse_json_object_impl(std::string_view json) {
|
|||||||
}
|
}
|
||||||
cursor += 4;
|
cursor += 4;
|
||||||
|
|
||||||
auto dms = std::meta::data_member_spec(^^std::nullptr_t,
|
auto dms = std::meta::data_member_spec(^^std::nullptr_t, make_data_member_options(field_name));
|
||||||
{
|
|
||||||
.name = field_name});
|
|
||||||
members.push_back(std::meta::reflect_constant(dms));
|
members.push_back(std::meta::reflect_constant(dms));
|
||||||
values.push_back(std::meta::reflect_constant(nullptr));
|
values.push_back(std::meta::reflect_constant(nullptr));
|
||||||
break;
|
break;
|
||||||
@@ -1051,22 +1060,19 @@ parse_json_object_impl(std::string_view json) {
|
|||||||
if (std::holds_alternative<int64_t>(out)) {
|
if (std::holds_alternative<int64_t>(out)) {
|
||||||
int64_t int_value = std::get<int64_t>(out);
|
int64_t int_value = std::get<int64_t>(out);
|
||||||
auto dms =
|
auto dms =
|
||||||
std::meta::data_member_spec(^^int64_t, {
|
std::meta::data_member_spec(^^int64_t, make_data_member_options(field_name));
|
||||||
.name = field_name});
|
|
||||||
members.push_back(std::meta::reflect_constant(dms));
|
members.push_back(std::meta::reflect_constant(dms));
|
||||||
values.push_back(std::meta::reflect_constant(int_value));
|
values.push_back(std::meta::reflect_constant(int_value));
|
||||||
} else if (std::holds_alternative<uint64_t>(out)) {
|
} else if (std::holds_alternative<uint64_t>(out)) {
|
||||||
uint64_t uint_value = std::get<uint64_t>(out);
|
uint64_t uint_value = std::get<uint64_t>(out);
|
||||||
auto dms =
|
auto dms =
|
||||||
std::meta::data_member_spec(^^uint64_t, {
|
std::meta::data_member_spec(^^uint64_t, make_data_member_options(field_name));
|
||||||
.name = field_name});
|
|
||||||
members.push_back(std::meta::reflect_constant(dms));
|
members.push_back(std::meta::reflect_constant(dms));
|
||||||
values.push_back(std::meta::reflect_constant(uint_value));
|
values.push_back(std::meta::reflect_constant(uint_value));
|
||||||
} else {
|
} else {
|
||||||
double float_value = std::get<double>(out);
|
double float_value = std::get<double>(out);
|
||||||
auto dms =
|
auto dms =
|
||||||
std::meta::data_member_spec(^^double, {
|
std::meta::data_member_spec(^^double, make_data_member_options(field_name));
|
||||||
.name = field_name});
|
|
||||||
members.push_back(std::meta::reflect_constant(dms));
|
members.push_back(std::meta::reflect_constant(dms));
|
||||||
values.push_back(std::meta::reflect_constant(float_value));
|
values.push_back(std::meta::reflect_constant(float_value));
|
||||||
}
|
}
|
||||||
@@ -1111,16 +1117,11 @@ template <constevalutil::fixed_string json_str> consteval auto parse_json() {
|
|||||||
"Only JSON objects and arrays are supported at the top level, this "
|
"Only JSON objects and arrays are supported at the top level, this "
|
||||||
"limitation will be lifted in the future.");*/
|
"limitation will be lifted in the future.");*/
|
||||||
|
|
||||||
constexpr auto result = json.front() == '['
|
if constexpr (json.front() == '[') {
|
||||||
? parse_json_array_impl(json)
|
return [: parse_json_array_impl(json).first :];
|
||||||
: parse_json_object_impl(json);
|
} else {
|
||||||
return [: result.first :];
|
return [: parse_json_object_impl(json).first :];
|
||||||
/*
|
}
|
||||||
if(json.front() == '[') {
|
|
||||||
return [:parse_json_array_impl(json).first:];
|
|
||||||
} else if(json.front() == '{') {
|
|
||||||
// return [:parse_json_object_impl(json).first:];
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace compile_time
|
} // namespace compile_time
|
||||||
|
|||||||
@@ -58,6 +58,11 @@ struct fixed_string {
|
|||||||
data[i] = str[i];
|
data[i] = str[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
constexpr fixed_string(const unsigned char (&str)[N]) {
|
||||||
|
for (std::size_t i = 0; i < N; ++i) {
|
||||||
|
data[i] = static_cast<char>(str[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
char data[N];
|
char data[N];
|
||||||
constexpr std::string_view view() const { return {data, N - 1}; }
|
constexpr std::string_view view() const { return {data, N - 1}; }
|
||||||
constexpr size_t size() const { return N ; }
|
constexpr size_t size() const { return N ; }
|
||||||
|
|||||||
@@ -141,6 +141,15 @@ inline bool document::dump_raw_tape(std::ostream &os) const noexcept {
|
|||||||
case 'r': // we start and end with the root node
|
case 'r': // we start and end with the root node
|
||||||
// should we be hitting the root node?
|
// should we be hitting the root node?
|
||||||
return false;
|
return false;
|
||||||
|
case 'Z': // we have a big integer
|
||||||
|
os << "bigint ";
|
||||||
|
std::memcpy(&string_length, string_buf.get() + payload, sizeof(uint32_t));
|
||||||
|
os << std::string_view(
|
||||||
|
reinterpret_cast<const char *>(string_buf.get() + payload + sizeof(uint32_t)),
|
||||||
|
string_length
|
||||||
|
);
|
||||||
|
os << '\n';
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,6 +81,10 @@ simdjson_inline simdjson_result<bool> simdjson_result<dom::element>::get_bool()
|
|||||||
if (error()) { return error(); }
|
if (error()) { return error(); }
|
||||||
return first.get_bool();
|
return first.get_bool();
|
||||||
}
|
}
|
||||||
|
simdjson_inline simdjson_result<std::string_view> simdjson_result<dom::element>::get_bigint() const noexcept {
|
||||||
|
if (error()) { return error(); }
|
||||||
|
return first.get_bigint();
|
||||||
|
}
|
||||||
|
|
||||||
simdjson_inline bool simdjson_result<dom::element>::is_array() const noexcept {
|
simdjson_inline bool simdjson_result<dom::element>::is_array() const noexcept {
|
||||||
return !error() && first.is_array();
|
return !error() && first.is_array();
|
||||||
@@ -110,6 +114,9 @@ simdjson_inline bool simdjson_result<dom::element>::is_bool() const noexcept {
|
|||||||
simdjson_inline bool simdjson_result<dom::element>::is_null() const noexcept {
|
simdjson_inline bool simdjson_result<dom::element>::is_null() const noexcept {
|
||||||
return !error() && first.is_null();
|
return !error() && first.is_null();
|
||||||
}
|
}
|
||||||
|
simdjson_inline bool simdjson_result<dom::element>::is_bigint() const noexcept {
|
||||||
|
return !error() && first.is_bigint();
|
||||||
|
}
|
||||||
|
|
||||||
simdjson_inline simdjson_result<dom::element> simdjson_result<dom::element>::operator[](std::string_view key) const noexcept {
|
simdjson_inline simdjson_result<dom::element> simdjson_result<dom::element>::operator[](std::string_view key) const noexcept {
|
||||||
if (error()) { return error(); }
|
if (error()) { return error(); }
|
||||||
@@ -218,6 +225,15 @@ inline simdjson_result<bool> element::get_bool() const noexcept {
|
|||||||
}
|
}
|
||||||
return INCORRECT_TYPE;
|
return INCORRECT_TYPE;
|
||||||
}
|
}
|
||||||
|
inline simdjson_result<std::string_view> element::get_bigint() const noexcept {
|
||||||
|
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable());
|
||||||
|
switch (tape.tape_ref_type()) {
|
||||||
|
case internal::tape_type::BIGINT:
|
||||||
|
return tape.get_string_view();
|
||||||
|
default:
|
||||||
|
return INCORRECT_TYPE;
|
||||||
|
}
|
||||||
|
}
|
||||||
inline simdjson_result<const char *> element::get_c_str() const noexcept {
|
inline simdjson_result<const char *> element::get_c_str() 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
|
||||||
switch (tape.tape_ref_type()) {
|
switch (tape.tape_ref_type()) {
|
||||||
@@ -360,6 +376,10 @@ inline bool element::is_null() const noexcept {
|
|||||||
return tape.is_null_on_tape();
|
return tape.is_null_on_tape();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool element::is_bigint() const noexcept {
|
||||||
|
return tape.tape_ref_type() == internal::tape_type::BIGINT;
|
||||||
|
}
|
||||||
|
|
||||||
#if SIMDJSON_EXCEPTIONS
|
#if SIMDJSON_EXCEPTIONS
|
||||||
|
|
||||||
inline element::operator bool() const noexcept(false) { return get<bool>(); }
|
inline element::operator bool() const noexcept(false) { return get<bool>(); }
|
||||||
@@ -492,6 +512,8 @@ inline std::ostream& operator<<(std::ostream& out, element_type type) {
|
|||||||
return out << "bool";
|
return out << "bool";
|
||||||
case element_type::NULL_VALUE:
|
case element_type::NULL_VALUE:
|
||||||
return out << "null";
|
return out << "null";
|
||||||
|
case element_type::BIGINT:
|
||||||
|
return out << "bigint";
|
||||||
default:
|
default:
|
||||||
return out << "unexpected content!!!"; // abort() usage is forbidden in the library
|
return out << "unexpected content!!!"; // abort() usage is forbidden in the library
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,8 @@ enum class element_type {
|
|||||||
DOUBLE = 'd', ///< double: Any number with a "." or "e" that fits in double.
|
DOUBLE = 'd', ///< double: Any number with a "." or "e" that fits in double.
|
||||||
STRING = '"', ///< std::string_view
|
STRING = '"', ///< std::string_view
|
||||||
BOOL = 't', ///< bool
|
BOOL = 't', ///< bool
|
||||||
NULL_VALUE = 'n' ///< null
|
NULL_VALUE = 'n', ///< null
|
||||||
|
BIGINT = 'Z' ///< std::string_view: big integer stored as raw digit string
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -120,6 +121,14 @@ public:
|
|||||||
*/
|
*/
|
||||||
inline simdjson_result<bool> get_bool() const noexcept;
|
inline simdjson_result<bool> get_bool() const noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read this element as a big integer (raw digit string).
|
||||||
|
*
|
||||||
|
* @returns A string_view of the raw digits, or:
|
||||||
|
* INCORRECT_TYPE if the JSON element is not a big integer.
|
||||||
|
*/
|
||||||
|
inline simdjson_result<std::string_view> get_bigint() const noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether this element is a json array.
|
* Whether this element is a json array.
|
||||||
*
|
*
|
||||||
@@ -175,6 +184,11 @@ public:
|
|||||||
*/
|
*/
|
||||||
inline bool is_null() const noexcept;
|
inline bool is_null() const noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether this element is a big integer (number exceeding 64-bit range).
|
||||||
|
*/
|
||||||
|
inline bool is_bigint() const noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tell whether the value can be cast to provided type (T).
|
* Tell whether the value can be cast to provided type (T).
|
||||||
*
|
*
|
||||||
@@ -533,6 +547,7 @@ public:
|
|||||||
simdjson_inline simdjson_result<uint64_t> get_uint64() const noexcept;
|
simdjson_inline simdjson_result<uint64_t> get_uint64() const noexcept;
|
||||||
simdjson_inline simdjson_result<double> get_double() const noexcept;
|
simdjson_inline simdjson_result<double> get_double() const noexcept;
|
||||||
simdjson_inline simdjson_result<bool> get_bool() const noexcept;
|
simdjson_inline simdjson_result<bool> get_bool() const noexcept;
|
||||||
|
simdjson_inline simdjson_result<std::string_view> get_bigint() const noexcept;
|
||||||
|
|
||||||
simdjson_inline bool is_array() const noexcept;
|
simdjson_inline bool is_array() const noexcept;
|
||||||
simdjson_inline bool is_object() const noexcept;
|
simdjson_inline bool is_object() const noexcept;
|
||||||
@@ -543,6 +558,7 @@ public:
|
|||||||
simdjson_inline bool is_number() const noexcept;
|
simdjson_inline bool is_number() const noexcept;
|
||||||
simdjson_inline bool is_bool() const noexcept;
|
simdjson_inline bool is_bool() const noexcept;
|
||||||
simdjson_inline bool is_null() const noexcept;
|
simdjson_inline bool is_null() const noexcept;
|
||||||
|
simdjson_inline bool is_bigint() const noexcept;
|
||||||
|
|
||||||
simdjson_inline simdjson_result<dom::element> operator[](std::string_view key) const noexcept;
|
simdjson_inline simdjson_result<dom::element> operator[](std::string_view key) const noexcept;
|
||||||
simdjson_inline simdjson_result<dom::element> operator[](const char *key) const noexcept;
|
simdjson_inline simdjson_result<dom::element> operator[](const char *key) const noexcept;
|
||||||
|
|||||||
@@ -36,10 +36,11 @@ inline bool parser::dump_raw_tape(std::ostream &os) const noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline simdjson_result<size_t> parser::read_file(std::string_view path) noexcept {
|
inline simdjson_result<size_t> parser::read_file(std::string_view path) noexcept {
|
||||||
|
const std::string path_copy(path);
|
||||||
// Open the file
|
// Open the file
|
||||||
SIMDJSON_PUSH_DISABLE_WARNINGS
|
SIMDJSON_PUSH_DISABLE_WARNINGS
|
||||||
SIMDJSON_DISABLE_DEPRECATED_WARNING // Disable CRT_SECURE warning on MSVC: manually verified this is safe
|
SIMDJSON_DISABLE_DEPRECATED_WARNING // Disable CRT_SECURE warning on MSVC: manually verified this is safe
|
||||||
std::FILE *fp = std::fopen(path.data(), "rb");
|
std::FILE *fp = std::fopen(path_copy.c_str(), "rb");
|
||||||
SIMDJSON_POP_DISABLE_WARNINGS
|
SIMDJSON_POP_DISABLE_WARNINGS
|
||||||
|
|
||||||
if (fp == nullptr) {
|
if (fp == nullptr) {
|
||||||
@@ -132,6 +133,7 @@ inline simdjson_result<element> parser::parse_into_document(document& provided_d
|
|||||||
buf += 3;
|
buf += 3;
|
||||||
len -= 3;
|
len -= 3;
|
||||||
}
|
}
|
||||||
|
implementation->_number_as_string = _number_as_string;
|
||||||
_error = implementation->parse(buf, len, provided_doc);
|
_error = implementation->parse(buf, len, provided_doc);
|
||||||
|
|
||||||
if (_error) { return _error; }
|
if (_error) { return _error; }
|
||||||
|
|||||||
@@ -610,6 +610,13 @@ public:
|
|||||||
inline bool dump_raw_tape(std::ostream &os) const noexcept;
|
inline bool dump_raw_tape(std::ostream &os) const noexcept;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When enabled, big integers (exceeding uint64 range) are stored as strings
|
||||||
|
* in the tape instead of returning BIGINT_ERROR. Default: false.
|
||||||
|
*/
|
||||||
|
inline void number_as_string(bool enabled) noexcept { _number_as_string = enabled; }
|
||||||
|
inline bool number_as_string() const noexcept { return _number_as_string; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* The maximum document length this parser will automatically support.
|
* The maximum document length this parser will automatically support.
|
||||||
@@ -618,6 +625,9 @@ private:
|
|||||||
*/
|
*/
|
||||||
size_t _max_capacity;
|
size_t _max_capacity;
|
||||||
|
|
||||||
|
/** Whether to store big integers as strings instead of returning BIGINT_ERROR */
|
||||||
|
bool _number_as_string{false};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The loaded buffer (reused each time load() is called)
|
* The loaded buffer (reused each time load() is called)
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -460,6 +460,12 @@ inline void string_builder<serializer>::append(simdjson::dom::element value) {
|
|||||||
case tape_type::STRING:
|
case tape_type::STRING:
|
||||||
format.string(iter.get_string_view());
|
format.string(iter.get_string_view());
|
||||||
break;
|
break;
|
||||||
|
case tape_type::BIGINT: {
|
||||||
|
// Big integer stored as string — output raw digits (no quotes)
|
||||||
|
auto sv = iter.get_string_view();
|
||||||
|
format.chars(sv.data(), sv.data() + sv.size());
|
||||||
|
break;
|
||||||
|
}
|
||||||
case tape_type::INT64:
|
case tape_type::INT64:
|
||||||
format.number(iter.next_tape_value<int64_t>());
|
format.number(iter.next_tape_value<int64_t>());
|
||||||
iter.json_index++; // numbers take up 2 spots, so we need to increment
|
iter.json_index++; // numbers take up 2 spots, so we need to increment
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ namespace SIMDJSON_IMPLEMENTATION {
|
|||||||
namespace builder {
|
namespace builder {
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
requires(concepts::container_but_not_string<T> && !require_custom_serialization<T>)
|
requires(concepts::container_but_not_string<T> && ! concepts::optional_type<T> && !require_custom_serialization<T>)
|
||||||
constexpr void atom(string_builder &b, const T &t) {
|
constexpr void atom(string_builder &b, const T &t) {
|
||||||
auto it = t.begin();
|
auto it = t.begin();
|
||||||
auto end = t.end();
|
auto end = t.end();
|
||||||
@@ -130,7 +130,7 @@ template <typename T>
|
|||||||
requires(std::is_enum_v<T> && !require_custom_serialization<T>)
|
requires(std::is_enum_v<T> && !require_custom_serialization<T>)
|
||||||
void atom(string_builder &b, const T &e) {
|
void atom(string_builder &b, const T &e) {
|
||||||
#if SIMDJSON_STATIC_REFLECTION
|
#if SIMDJSON_STATIC_REFLECTION
|
||||||
constexpr auto enumerators = std::define_static_array(std::meta::enumerators_of(^^T));
|
static constexpr auto enumerators = std::define_static_array(std::meta::enumerators_of(^^T));
|
||||||
template for (constexpr auto enum_val : enumerators) {
|
template for (constexpr auto enum_val : enumerators) {
|
||||||
constexpr auto enum_str = std::define_static_string(constevalutil::consteval_to_quoted_escaped(std::meta::identifier_of(enum_val)));
|
constexpr auto enum_str = std::define_static_string(constevalutil::consteval_to_quoted_escaped(std::meta::identifier_of(enum_val)));
|
||||||
if (e == [:enum_val:]) {
|
if (e == [:enum_val:]) {
|
||||||
@@ -294,30 +294,23 @@ string_builder& operator<<(string_builder& b, const Z& z) {
|
|||||||
template<constevalutil::fixed_string... FieldNames, typename T>
|
template<constevalutil::fixed_string... FieldNames, typename T>
|
||||||
requires(std::is_class_v<T> && (sizeof...(FieldNames) > 0))
|
requires(std::is_class_v<T> && (sizeof...(FieldNames) > 0))
|
||||||
void extract_from(string_builder &b, const T &obj) {
|
void extract_from(string_builder &b, const T &obj) {
|
||||||
// Helper to check if a field name matches any of the requested fields
|
|
||||||
auto should_extract = [](std::string_view field_name) constexpr -> bool {
|
|
||||||
return ((FieldNames.view() == field_name) || ...);
|
|
||||||
};
|
|
||||||
|
|
||||||
b.append('{');
|
b.append('{');
|
||||||
bool first = true;
|
bool first = true;
|
||||||
|
|
||||||
// Iterate through all members of T using reflection
|
// Iterate through all members of T using reflection
|
||||||
template for (constexpr auto mem : std::define_static_array(
|
static constexpr auto members = std::define_static_array(std::meta::nonstatic_data_members_of(^^T, std::meta::access_context::unchecked()));
|
||||||
std::meta::nonstatic_data_members_of(^^T, std::meta::access_context::unchecked()))) {
|
template for (constexpr auto mem : members) {
|
||||||
|
|
||||||
if constexpr (std::meta::is_public(mem)) {
|
if constexpr (std::meta::is_public(mem)) {
|
||||||
constexpr std::string_view key = std::define_static_string(std::meta::identifier_of(mem));
|
static constexpr std::string_view key = std::define_static_string(std::meta::identifier_of(mem));
|
||||||
|
|
||||||
// Only serialize this field if it's in our list of requested fields
|
// Only serialize this field if it's in our list of requested fields
|
||||||
if constexpr (should_extract(key)) {
|
if constexpr (((FieldNames.view() == key) || ...)) {
|
||||||
if (!first) {
|
if (!first) {
|
||||||
b.append(',');
|
b.append(',');
|
||||||
}
|
}
|
||||||
first = false;
|
first = false;
|
||||||
|
|
||||||
// Serialize the key
|
// Serialize the key
|
||||||
constexpr auto quoted_key = std::define_static_string(constevalutil::consteval_to_quoted_escaped(std::meta::identifier_of(mem)));
|
static constexpr auto quoted_key = std::define_static_string(constevalutil::consteval_to_quoted_escaped(std::meta::identifier_of(mem)));
|
||||||
b.append_raw(quoted_key);
|
b.append_raw(quoted_key);
|
||||||
b.append(':');
|
b.append(':');
|
||||||
|
|
||||||
|
|||||||
@@ -505,7 +505,7 @@ simdjson_inline bool string_builder::capacity_check(size_t upcoming_bytes) {
|
|||||||
return is_valid;
|
return is_valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
simdjson_inline void string_builder::grow_buffer(size_t desired_capacity) {
|
inline void string_builder::grow_buffer(size_t desired_capacity) {
|
||||||
if (!is_valid) {
|
if (!is_valid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -842,7 +842,7 @@ simdjson_inline void string_builder::append(const T &value) {
|
|||||||
#if SIMDJSON_SUPPORTS_RANGES && SIMDJSON_SUPPORTS_CONCEPTS
|
#if SIMDJSON_SUPPORTS_RANGES && SIMDJSON_SUPPORTS_CONCEPTS
|
||||||
// Support for range-based appending (std::ranges::view, etc.)
|
// Support for range-based appending (std::ranges::view, etc.)
|
||||||
template <std::ranges::range R>
|
template <std::ranges::range R>
|
||||||
requires(!std::is_convertible<R, std::string_view>::value && !require_custom_serialization<R>)
|
requires(!std::is_convertible<R, std::string_view>::value && !concepts::optional_type<R> && !require_custom_serialization<R>)
|
||||||
simdjson_inline void string_builder::append(const R &range) noexcept {
|
simdjson_inline void string_builder::append(const R &range) noexcept {
|
||||||
auto it = std::ranges::begin(range);
|
auto it = std::ranges::begin(range);
|
||||||
auto end = std::ranges::end(range);
|
auto end = std::ranges::end(range);
|
||||||
|
|||||||
@@ -171,7 +171,7 @@ public:
|
|||||||
#if SIMDJSON_SUPPORTS_RANGES && SIMDJSON_SUPPORTS_CONCEPTS
|
#if SIMDJSON_SUPPORTS_RANGES && SIMDJSON_SUPPORTS_CONCEPTS
|
||||||
// Support for range-based appending (std::ranges::view, etc.)
|
// Support for range-based appending (std::ranges::view, etc.)
|
||||||
template <std::ranges::range R>
|
template <std::ranges::range R>
|
||||||
requires (!std::is_convertible<R, std::string_view>::value && !require_custom_serialization<R>)
|
requires (!std::is_convertible<R, std::string_view>::value && !concepts::optional_type<R> && !require_custom_serialization<R>)
|
||||||
simdjson_inline void append(const R &range) noexcept;
|
simdjson_inline void append(const R &range) noexcept;
|
||||||
#endif
|
#endif
|
||||||
/**
|
/**
|
||||||
@@ -249,7 +249,7 @@ private:
|
|||||||
* If the allocation fails, is_valid is set to false. We expect
|
* If the allocation fails, is_valid is set to false. We expect
|
||||||
* that this function would not be repeatedly called.
|
* that this function would not be repeatedly called.
|
||||||
*/
|
*/
|
||||||
simdjson_inline void grow_buffer(size_t desired_capacity);
|
inline void grow_buffer(size_t desired_capacity);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* We use this helper function to make sure that is_valid is kept consistent.
|
* We use this helper function to make sure that is_valid is kept consistent.
|
||||||
|
|||||||
@@ -16,6 +16,8 @@
|
|||||||
#include "simdjson/generic/ondemand/deserialize.h"
|
#include "simdjson/generic/ondemand/deserialize.h"
|
||||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
namespace simdjson {
|
namespace simdjson {
|
||||||
namespace SIMDJSON_IMPLEMENTATION {
|
namespace SIMDJSON_IMPLEMENTATION {
|
||||||
namespace ondemand {
|
namespace ondemand {
|
||||||
@@ -131,6 +133,18 @@ simdjson_inline simdjson_result<int64_t> document::get_int64() noexcept {
|
|||||||
simdjson_inline simdjson_result<int64_t> document::get_int64_in_string() noexcept {
|
simdjson_inline simdjson_result<int64_t> document::get_int64_in_string() noexcept {
|
||||||
return get_root_value_iterator().get_root_int64_in_string(true);
|
return get_root_value_iterator().get_root_int64_in_string(true);
|
||||||
}
|
}
|
||||||
|
simdjson_inline simdjson_result<uint32_t> document::get_uint32() noexcept {
|
||||||
|
uint64_t result;
|
||||||
|
SIMDJSON_TRY(get_uint64().get(result));
|
||||||
|
if (result > (std::numeric_limits<uint32_t>::max)()) { return NUMBER_OUT_OF_RANGE; }
|
||||||
|
return static_cast<uint32_t>(result);
|
||||||
|
}
|
||||||
|
simdjson_inline simdjson_result<int32_t> document::get_int32() noexcept {
|
||||||
|
int64_t result;
|
||||||
|
SIMDJSON_TRY(get_int64().get(result));
|
||||||
|
if (result > (std::numeric_limits<int32_t>::max)() || result < (std::numeric_limits<int32_t>::min)()) { return NUMBER_OUT_OF_RANGE; }
|
||||||
|
return static_cast<int32_t>(result);
|
||||||
|
}
|
||||||
simdjson_inline simdjson_result<double> document::get_double() noexcept {
|
simdjson_inline simdjson_result<double> document::get_double() noexcept {
|
||||||
return get_root_value_iterator().get_root_double(true);
|
return get_root_value_iterator().get_root_double(true);
|
||||||
}
|
}
|
||||||
@@ -164,6 +178,8 @@ template<> simdjson_inline simdjson_result<std::string_view> document::get() & n
|
|||||||
template<> simdjson_inline simdjson_result<double> document::get() & noexcept { return get_double(); }
|
template<> simdjson_inline simdjson_result<double> document::get() & noexcept { return get_double(); }
|
||||||
template<> simdjson_inline simdjson_result<uint64_t> document::get() & noexcept { return get_uint64(); }
|
template<> simdjson_inline simdjson_result<uint64_t> document::get() & noexcept { return get_uint64(); }
|
||||||
template<> simdjson_inline simdjson_result<int64_t> document::get() & noexcept { return get_int64(); }
|
template<> simdjson_inline simdjson_result<int64_t> document::get() & noexcept { return get_int64(); }
|
||||||
|
template<> simdjson_inline simdjson_result<uint32_t> document::get() & noexcept { return get_uint32(); }
|
||||||
|
template<> simdjson_inline simdjson_result<int32_t> document::get() & noexcept { return get_int32(); }
|
||||||
template<> simdjson_inline simdjson_result<bool> document::get() & noexcept { return get_bool(); }
|
template<> simdjson_inline simdjson_result<bool> document::get() & noexcept { return get_bool(); }
|
||||||
template<> simdjson_inline simdjson_result<value> document::get() & noexcept { return get_value(); }
|
template<> simdjson_inline simdjson_result<value> document::get() & noexcept { return get_value(); }
|
||||||
|
|
||||||
@@ -174,6 +190,8 @@ template<> simdjson_warn_unused simdjson_inline error_code document::get(std::st
|
|||||||
template<> simdjson_warn_unused simdjson_inline error_code document::get(double& out) & noexcept { return get_double().get(out); }
|
template<> simdjson_warn_unused simdjson_inline error_code document::get(double& out) & noexcept { return get_double().get(out); }
|
||||||
template<> simdjson_warn_unused simdjson_inline error_code document::get(uint64_t& out) & noexcept { return get_uint64().get(out); }
|
template<> simdjson_warn_unused simdjson_inline error_code document::get(uint64_t& out) & noexcept { return get_uint64().get(out); }
|
||||||
template<> simdjson_warn_unused simdjson_inline error_code document::get(int64_t& out) & noexcept { return get_int64().get(out); }
|
template<> simdjson_warn_unused simdjson_inline error_code document::get(int64_t& out) & noexcept { return get_int64().get(out); }
|
||||||
|
template<> simdjson_warn_unused simdjson_inline error_code document::get(uint32_t& out) & noexcept { return get_uint32().get(out); }
|
||||||
|
template<> simdjson_warn_unused simdjson_inline error_code document::get(int32_t& out) & noexcept { return get_int32().get(out); }
|
||||||
template<> simdjson_warn_unused simdjson_inline error_code document::get(bool& out) & noexcept { return get_bool().get(out); }
|
template<> simdjson_warn_unused simdjson_inline error_code document::get(bool& out) & noexcept { return get_bool().get(out); }
|
||||||
template<> simdjson_warn_unused simdjson_inline error_code document::get(value& out) & noexcept { return get_value().get(out); }
|
template<> simdjson_warn_unused simdjson_inline error_code document::get(value& out) & noexcept { return get_value().get(out); }
|
||||||
|
|
||||||
@@ -504,6 +522,14 @@ simdjson_inline simdjson_result<int64_t> simdjson_result<SIMDJSON_IMPLEMENTATION
|
|||||||
if (error()) { return error(); }
|
if (error()) { return error(); }
|
||||||
return first.get_int64_in_string();
|
return first.get_int64_in_string();
|
||||||
}
|
}
|
||||||
|
simdjson_inline simdjson_result<uint32_t> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::get_uint32() noexcept {
|
||||||
|
if (error()) { return error(); }
|
||||||
|
return first.get_uint32();
|
||||||
|
}
|
||||||
|
simdjson_inline simdjson_result<int32_t> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::get_int32() noexcept {
|
||||||
|
if (error()) { return error(); }
|
||||||
|
return first.get_int32();
|
||||||
|
}
|
||||||
simdjson_inline simdjson_result<double> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::get_double() noexcept {
|
simdjson_inline simdjson_result<double> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::get_double() noexcept {
|
||||||
if (error()) { return error(); }
|
if (error()) { return error(); }
|
||||||
return first.get_double();
|
return first.get_double();
|
||||||
@@ -627,27 +653,27 @@ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::op
|
|||||||
}
|
}
|
||||||
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::operator uint64_t() noexcept(false) {
|
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::operator uint64_t() noexcept(false) {
|
||||||
if (error()) { throw simdjson_error(error()); }
|
if (error()) { throw simdjson_error(error()); }
|
||||||
return first;
|
return first.get_uint64();
|
||||||
}
|
}
|
||||||
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::operator int64_t() noexcept(false) {
|
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::operator int64_t() noexcept(false) {
|
||||||
if (error()) { throw simdjson_error(error()); }
|
if (error()) { throw simdjson_error(error()); }
|
||||||
return first;
|
return first.get_int64();
|
||||||
}
|
}
|
||||||
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::operator double() noexcept(false) {
|
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::operator double() noexcept(false) {
|
||||||
if (error()) { throw simdjson_error(error()); }
|
if (error()) { throw simdjson_error(error()); }
|
||||||
return first;
|
return first.get_double();
|
||||||
}
|
}
|
||||||
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::operator std::string_view() noexcept(false) {
|
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::operator std::string_view() noexcept(false) {
|
||||||
if (error()) { throw simdjson_error(error()); }
|
if (error()) { throw simdjson_error(error()); }
|
||||||
return first;
|
return first.get_string();
|
||||||
}
|
}
|
||||||
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::operator SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string() noexcept(false) {
|
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::operator SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string() noexcept(false) {
|
||||||
if (error()) { throw simdjson_error(error()); }
|
if (error()) { throw simdjson_error(error()); }
|
||||||
return first;
|
return first.get_raw_json_string();
|
||||||
}
|
}
|
||||||
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::operator bool() noexcept(false) {
|
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::operator bool() noexcept(false) {
|
||||||
if (error()) { throw simdjson_error(error()); }
|
if (error()) { throw simdjson_error(error()); }
|
||||||
return first;
|
return first.get_bool();
|
||||||
}
|
}
|
||||||
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::operator SIMDJSON_IMPLEMENTATION::ondemand::value() noexcept(false) {
|
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::operator SIMDJSON_IMPLEMENTATION::ondemand::value() noexcept(false) {
|
||||||
if (error()) { throw simdjson_error(error()); }
|
if (error()) { throw simdjson_error(error()); }
|
||||||
@@ -731,6 +757,18 @@ simdjson_inline simdjson_result<uint64_t> document_reference::get_uint64() noexc
|
|||||||
simdjson_inline simdjson_result<uint64_t> document_reference::get_uint64_in_string() noexcept { return doc->get_root_value_iterator().get_root_uint64_in_string(false); }
|
simdjson_inline simdjson_result<uint64_t> document_reference::get_uint64_in_string() noexcept { return doc->get_root_value_iterator().get_root_uint64_in_string(false); }
|
||||||
simdjson_inline simdjson_result<int64_t> document_reference::get_int64() noexcept { return doc->get_root_value_iterator().get_root_int64(false); }
|
simdjson_inline simdjson_result<int64_t> document_reference::get_int64() noexcept { return doc->get_root_value_iterator().get_root_int64(false); }
|
||||||
simdjson_inline simdjson_result<int64_t> document_reference::get_int64_in_string() noexcept { return doc->get_root_value_iterator().get_root_int64_in_string(false); }
|
simdjson_inline simdjson_result<int64_t> document_reference::get_int64_in_string() noexcept { return doc->get_root_value_iterator().get_root_int64_in_string(false); }
|
||||||
|
simdjson_inline simdjson_result<uint32_t> document_reference::get_uint32() noexcept {
|
||||||
|
uint64_t result;
|
||||||
|
SIMDJSON_TRY(doc->get_root_value_iterator().get_root_uint64(false).get(result));
|
||||||
|
if (result > (std::numeric_limits<uint32_t>::max)()) { return NUMBER_OUT_OF_RANGE; }
|
||||||
|
return static_cast<uint32_t>(result);
|
||||||
|
}
|
||||||
|
simdjson_inline simdjson_result<int32_t> document_reference::get_int32() noexcept {
|
||||||
|
int64_t result;
|
||||||
|
SIMDJSON_TRY(doc->get_root_value_iterator().get_root_int64(false).get(result));
|
||||||
|
if (result > (std::numeric_limits<int32_t>::max)() || result < (std::numeric_limits<int32_t>::min)()) { return NUMBER_OUT_OF_RANGE; }
|
||||||
|
return static_cast<int32_t>(result);
|
||||||
|
}
|
||||||
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); }
|
||||||
@@ -748,6 +786,8 @@ template<> simdjson_inline simdjson_result<std::string_view> document_reference:
|
|||||||
template<> simdjson_inline simdjson_result<double> document_reference::get() & noexcept { return get_double(); }
|
template<> simdjson_inline simdjson_result<double> document_reference::get() & noexcept { return get_double(); }
|
||||||
template<> simdjson_inline simdjson_result<uint64_t> document_reference::get() & noexcept { return get_uint64(); }
|
template<> simdjson_inline simdjson_result<uint64_t> document_reference::get() & noexcept { return get_uint64(); }
|
||||||
template<> simdjson_inline simdjson_result<int64_t> document_reference::get() & noexcept { return get_int64(); }
|
template<> simdjson_inline simdjson_result<int64_t> document_reference::get() & noexcept { return get_int64(); }
|
||||||
|
template<> simdjson_inline simdjson_result<uint32_t> document_reference::get() & noexcept { return get_uint32(); }
|
||||||
|
template<> simdjson_inline simdjson_result<int32_t> document_reference::get() & noexcept { return get_int32(); }
|
||||||
template<> simdjson_inline simdjson_result<bool> document_reference::get() & noexcept { return get_bool(); }
|
template<> simdjson_inline simdjson_result<bool> document_reference::get() & noexcept { return get_bool(); }
|
||||||
template<> simdjson_inline simdjson_result<value> document_reference::get() & noexcept { return get_value(); }
|
template<> simdjson_inline simdjson_result<value> document_reference::get() & noexcept { return get_value(); }
|
||||||
#if SIMDJSON_EXCEPTIONS
|
#if SIMDJSON_EXCEPTIONS
|
||||||
@@ -879,6 +919,14 @@ simdjson_inline simdjson_result<int64_t> simdjson_result<SIMDJSON_IMPLEMENTATION
|
|||||||
if (error()) { return error(); }
|
if (error()) { return error(); }
|
||||||
return first.get_int64_in_string();
|
return first.get_int64_in_string();
|
||||||
}
|
}
|
||||||
|
simdjson_inline simdjson_result<uint32_t> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::get_uint32() noexcept {
|
||||||
|
if (error()) { return error(); }
|
||||||
|
return first.get_uint32();
|
||||||
|
}
|
||||||
|
simdjson_inline simdjson_result<int32_t> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::get_int32() noexcept {
|
||||||
|
if (error()) { return error(); }
|
||||||
|
return first.get_int32();
|
||||||
|
}
|
||||||
simdjson_inline simdjson_result<double> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::get_double() noexcept {
|
simdjson_inline simdjson_result<double> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::get_double() noexcept {
|
||||||
if (error()) { return error(); }
|
if (error()) { return error(); }
|
||||||
return first.get_double();
|
return first.get_double();
|
||||||
@@ -994,27 +1042,27 @@ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_refe
|
|||||||
}
|
}
|
||||||
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::operator uint64_t() noexcept(false) {
|
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::operator uint64_t() noexcept(false) {
|
||||||
if (error()) { throw simdjson_error(error()); }
|
if (error()) { throw simdjson_error(error()); }
|
||||||
return first;
|
return first.get_uint64();
|
||||||
}
|
}
|
||||||
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::operator int64_t() noexcept(false) {
|
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::operator int64_t() noexcept(false) {
|
||||||
if (error()) { throw simdjson_error(error()); }
|
if (error()) { throw simdjson_error(error()); }
|
||||||
return first;
|
return first.get_int64();
|
||||||
}
|
}
|
||||||
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::operator double() noexcept(false) {
|
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::operator double() noexcept(false) {
|
||||||
if (error()) { throw simdjson_error(error()); }
|
if (error()) { throw simdjson_error(error()); }
|
||||||
return first;
|
return first.get_double();
|
||||||
}
|
}
|
||||||
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::operator std::string_view() noexcept(false) {
|
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::operator std::string_view() noexcept(false) {
|
||||||
if (error()) { throw simdjson_error(error()); }
|
if (error()) { throw simdjson_error(error()); }
|
||||||
return first;
|
return first.get_string();
|
||||||
}
|
}
|
||||||
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::operator SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string() noexcept(false) {
|
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::operator SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string() noexcept(false) {
|
||||||
if (error()) { throw simdjson_error(error()); }
|
if (error()) { throw simdjson_error(error()); }
|
||||||
return first;
|
return first.get_raw_json_string();
|
||||||
}
|
}
|
||||||
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::operator bool() noexcept(false) {
|
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::operator bool() noexcept(false) {
|
||||||
if (error()) { throw simdjson_error(error()); }
|
if (error()) { throw simdjson_error(error()); }
|
||||||
return first;
|
return first.get_bool();
|
||||||
}
|
}
|
||||||
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::operator SIMDJSON_IMPLEMENTATION::ondemand::value() noexcept(false) {
|
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::operator SIMDJSON_IMPLEMENTATION::ondemand::value() noexcept(false) {
|
||||||
if (error()) { throw simdjson_error(error()); }
|
if (error()) { throw simdjson_error(error()); }
|
||||||
|
|||||||
@@ -76,6 +76,26 @@ public:
|
|||||||
* @returns INCORRECT_TYPE If the JSON value is not a 64-bit integer.
|
* @returns INCORRECT_TYPE If the JSON value is not a 64-bit integer.
|
||||||
*/
|
*/
|
||||||
simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
|
simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
|
||||||
|
/**
|
||||||
|
* Cast this JSON value to a 32-bit unsigned integer.
|
||||||
|
*
|
||||||
|
* Calls get_uint64() and checks that the result fits in a uint32_t.
|
||||||
|
*
|
||||||
|
* @returns A 32-bit unsigned integer.
|
||||||
|
* @returns INCORRECT_TYPE If the JSON value is not an unsigned integer.
|
||||||
|
* @returns NUMBER_OUT_OF_RANGE If the value does not fit in a uint32_t.
|
||||||
|
*/
|
||||||
|
simdjson_inline simdjson_result<uint32_t> get_uint32() noexcept;
|
||||||
|
/**
|
||||||
|
* Cast this JSON value to a 32-bit signed integer.
|
||||||
|
*
|
||||||
|
* Calls get_int64() and checks that the result fits in an int32_t.
|
||||||
|
*
|
||||||
|
* @returns A 32-bit signed integer.
|
||||||
|
* @returns INCORRECT_TYPE If the JSON value is not an integer.
|
||||||
|
* @returns NUMBER_OUT_OF_RANGE If the value does not fit in an int32_t.
|
||||||
|
*/
|
||||||
|
simdjson_inline simdjson_result<int32_t> get_int32() noexcept;
|
||||||
/**
|
/**
|
||||||
* Cast this JSON value to a double.
|
* Cast this JSON value to a double.
|
||||||
*
|
*
|
||||||
@@ -299,21 +319,21 @@ public:
|
|||||||
* @returns A signed 64-bit integer.
|
* @returns A signed 64-bit integer.
|
||||||
* @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not a 64-bit unsigned integer.
|
* @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not a 64-bit unsigned integer.
|
||||||
*/
|
*/
|
||||||
simdjson_inline operator uint64_t() noexcept(false);
|
explicit simdjson_inline operator uint64_t() noexcept(false);
|
||||||
/**
|
/**
|
||||||
* Cast this JSON value to a signed integer.
|
* Cast this JSON value to a signed integer.
|
||||||
*
|
*
|
||||||
* @returns A signed 64-bit integer.
|
* @returns A signed 64-bit integer.
|
||||||
* @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not a 64-bit integer.
|
* @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not a 64-bit integer.
|
||||||
*/
|
*/
|
||||||
simdjson_inline operator int64_t() noexcept(false);
|
explicit simdjson_inline operator int64_t() noexcept(false);
|
||||||
/**
|
/**
|
||||||
* Cast this JSON value to a double.
|
* Cast this JSON value to a double.
|
||||||
*
|
*
|
||||||
* @returns A double.
|
* @returns A double.
|
||||||
* @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not a valid floating-point number.
|
* @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not a valid floating-point number.
|
||||||
*/
|
*/
|
||||||
simdjson_inline operator double() noexcept(false);
|
explicit simdjson_inline operator double() noexcept(false);
|
||||||
/**
|
/**
|
||||||
* Cast this JSON value to a string.
|
* Cast this JSON value to a string.
|
||||||
*
|
*
|
||||||
@@ -323,7 +343,7 @@ public:
|
|||||||
* time it parses a document or when it is destroyed.
|
* time it parses a document or when it is destroyed.
|
||||||
* @exception simdjson_error(INCORRECT_TYPE) if the JSON value is not a string.
|
* @exception simdjson_error(INCORRECT_TYPE) if the JSON value is not a string.
|
||||||
*/
|
*/
|
||||||
simdjson_inline operator std::string_view() noexcept(false) simdjson_lifetime_bound;
|
explicit simdjson_inline operator std::string_view() noexcept(false) simdjson_lifetime_bound;
|
||||||
/**
|
/**
|
||||||
* Cast this JSON value to a raw_json_string.
|
* Cast this JSON value to a raw_json_string.
|
||||||
*
|
*
|
||||||
@@ -332,14 +352,14 @@ public:
|
|||||||
* @returns A pointer to the raw JSON for the given string.
|
* @returns A pointer to the raw JSON for the given string.
|
||||||
* @exception simdjson_error(INCORRECT_TYPE) if the JSON value is not a string.
|
* @exception simdjson_error(INCORRECT_TYPE) if the JSON value is not a string.
|
||||||
*/
|
*/
|
||||||
simdjson_inline operator raw_json_string() noexcept(false) simdjson_lifetime_bound;
|
explicit simdjson_inline operator raw_json_string() noexcept(false) simdjson_lifetime_bound;
|
||||||
/**
|
/**
|
||||||
* Cast this JSON value to a bool.
|
* Cast this JSON value to a bool.
|
||||||
*
|
*
|
||||||
* @returns A bool value.
|
* @returns A bool value.
|
||||||
* @exception simdjson_error(INCORRECT_TYPE) if the JSON value is not true or false.
|
* @exception simdjson_error(INCORRECT_TYPE) if the JSON value is not true or false.
|
||||||
*/
|
*/
|
||||||
simdjson_inline operator bool() noexcept(false);
|
explicit simdjson_inline operator bool() noexcept(false);
|
||||||
/**
|
/**
|
||||||
* Cast this JSON value to a value when the document is an object or an array.
|
* Cast this JSON value to a value when the document is an object or an array.
|
||||||
*
|
*
|
||||||
@@ -829,6 +849,8 @@ public:
|
|||||||
simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
|
simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
|
||||||
simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
|
simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
|
||||||
simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
|
simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
|
||||||
|
simdjson_inline simdjson_result<uint32_t> get_uint32() noexcept;
|
||||||
|
simdjson_inline simdjson_result<int32_t> get_int32() noexcept;
|
||||||
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;
|
||||||
@@ -923,12 +945,12 @@ public:
|
|||||||
explicit simdjson_inline operator T() noexcept(false);
|
explicit simdjson_inline operator T() noexcept(false);
|
||||||
simdjson_inline operator array() & noexcept(false);
|
simdjson_inline operator array() & noexcept(false);
|
||||||
simdjson_inline operator object() & noexcept(false);
|
simdjson_inline operator object() & noexcept(false);
|
||||||
simdjson_inline operator uint64_t() noexcept(false);
|
explicit simdjson_inline operator uint64_t() noexcept(false);
|
||||||
simdjson_inline operator int64_t() noexcept(false);
|
explicit simdjson_inline operator int64_t() noexcept(false);
|
||||||
simdjson_inline operator double() noexcept(false);
|
explicit simdjson_inline operator double() noexcept(false);
|
||||||
simdjson_inline operator std::string_view() noexcept(false);
|
explicit simdjson_inline operator std::string_view() noexcept(false);
|
||||||
simdjson_inline operator raw_json_string() noexcept(false);
|
explicit simdjson_inline operator raw_json_string() noexcept(false);
|
||||||
simdjson_inline operator bool() noexcept(false);
|
explicit simdjson_inline operator bool() noexcept(false);
|
||||||
simdjson_inline operator value() noexcept(false);
|
simdjson_inline operator value() noexcept(false);
|
||||||
#endif
|
#endif
|
||||||
simdjson_inline simdjson_result<size_t> count_elements() & noexcept;
|
simdjson_inline simdjson_result<size_t> count_elements() & noexcept;
|
||||||
@@ -982,6 +1004,8 @@ public:
|
|||||||
simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
|
simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
|
||||||
simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
|
simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
|
||||||
simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
|
simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
|
||||||
|
simdjson_inline simdjson_result<uint32_t> get_uint32() noexcept;
|
||||||
|
simdjson_inline simdjson_result<int32_t> get_int32() noexcept;
|
||||||
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;
|
||||||
@@ -1006,12 +1030,12 @@ public:
|
|||||||
explicit simdjson_inline operator T() noexcept(false);
|
explicit simdjson_inline operator T() noexcept(false);
|
||||||
simdjson_inline operator SIMDJSON_IMPLEMENTATION::ondemand::array() & noexcept(false);
|
simdjson_inline operator SIMDJSON_IMPLEMENTATION::ondemand::array() & noexcept(false);
|
||||||
simdjson_inline operator SIMDJSON_IMPLEMENTATION::ondemand::object() & noexcept(false);
|
simdjson_inline operator SIMDJSON_IMPLEMENTATION::ondemand::object() & noexcept(false);
|
||||||
simdjson_inline operator uint64_t() noexcept(false);
|
explicit simdjson_inline operator uint64_t() noexcept(false);
|
||||||
simdjson_inline operator int64_t() noexcept(false);
|
explicit simdjson_inline operator int64_t() noexcept(false);
|
||||||
simdjson_inline operator double() noexcept(false);
|
explicit simdjson_inline operator double() noexcept(false);
|
||||||
simdjson_inline operator std::string_view() noexcept(false);
|
explicit simdjson_inline operator std::string_view() noexcept(false);
|
||||||
simdjson_inline operator SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string() noexcept(false);
|
explicit simdjson_inline operator SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string() noexcept(false);
|
||||||
simdjson_inline operator bool() noexcept(false);
|
explicit simdjson_inline operator bool() noexcept(false);
|
||||||
simdjson_inline operator SIMDJSON_IMPLEMENTATION::ondemand::value() noexcept(false);
|
simdjson_inline operator SIMDJSON_IMPLEMENTATION::ondemand::value() noexcept(false);
|
||||||
#endif
|
#endif
|
||||||
simdjson_inline simdjson_result<size_t> count_elements() & noexcept;
|
simdjson_inline simdjson_result<size_t> count_elements() & noexcept;
|
||||||
@@ -1069,6 +1093,8 @@ public:
|
|||||||
simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
|
simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
|
||||||
simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
|
simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
|
||||||
simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
|
simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
|
||||||
|
simdjson_inline simdjson_result<uint32_t> get_uint32() noexcept;
|
||||||
|
simdjson_inline simdjson_result<int32_t> get_int32() noexcept;
|
||||||
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;
|
||||||
@@ -1090,12 +1116,12 @@ public:
|
|||||||
explicit simdjson_inline operator T() noexcept(false);
|
explicit simdjson_inline operator T() noexcept(false);
|
||||||
simdjson_inline operator SIMDJSON_IMPLEMENTATION::ondemand::array() & noexcept(false);
|
simdjson_inline operator SIMDJSON_IMPLEMENTATION::ondemand::array() & noexcept(false);
|
||||||
simdjson_inline operator SIMDJSON_IMPLEMENTATION::ondemand::object() & noexcept(false);
|
simdjson_inline operator SIMDJSON_IMPLEMENTATION::ondemand::object() & noexcept(false);
|
||||||
simdjson_inline operator uint64_t() noexcept(false);
|
explicit simdjson_inline operator uint64_t() noexcept(false);
|
||||||
simdjson_inline operator int64_t() noexcept(false);
|
explicit simdjson_inline operator int64_t() noexcept(false);
|
||||||
simdjson_inline operator double() noexcept(false);
|
explicit simdjson_inline operator double() noexcept(false);
|
||||||
simdjson_inline operator std::string_view() noexcept(false);
|
explicit simdjson_inline operator std::string_view() noexcept(false);
|
||||||
simdjson_inline operator SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string() noexcept(false);
|
explicit simdjson_inline operator SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string() noexcept(false);
|
||||||
simdjson_inline operator bool() noexcept(false);
|
explicit simdjson_inline operator bool() noexcept(false);
|
||||||
simdjson_inline operator SIMDJSON_IMPLEMENTATION::ondemand::value() noexcept(false);
|
simdjson_inline operator SIMDJSON_IMPLEMENTATION::ondemand::value() noexcept(false);
|
||||||
#endif
|
#endif
|
||||||
simdjson_inline simdjson_result<size_t> count_elements() & noexcept;
|
simdjson_inline simdjson_result<size_t> count_elements() & noexcept;
|
||||||
|
|||||||
@@ -172,7 +172,7 @@ simdjson_pure simdjson_inline size_t parser::max_depth() const noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
simdjson_inline void parser::set_max_capacity(size_t max_capacity) noexcept {
|
simdjson_inline void parser::set_max_capacity(size_t max_capacity) noexcept {
|
||||||
if(max_capacity < dom::MINIMAL_DOCUMENT_CAPACITY) {
|
if(max_capacity > dom::MINIMAL_DOCUMENT_CAPACITY) {
|
||||||
_max_capacity = max_capacity;
|
_max_capacity = max_capacity;
|
||||||
} else {
|
} else {
|
||||||
_max_capacity = dom::MINIMAL_DOCUMENT_CAPACITY;
|
_max_capacity = dom::MINIMAL_DOCUMENT_CAPACITY;
|
||||||
|
|||||||
@@ -305,7 +305,7 @@ error_code tag_invoke(deserialize_tag, ValT &val, T &out) noexcept {
|
|||||||
#if SIMDJSON_STATIC_REFLECTION
|
#if SIMDJSON_STATIC_REFLECTION
|
||||||
std::string_view str;
|
std::string_view str;
|
||||||
SIMDJSON_TRY(val.get_string().get(str));
|
SIMDJSON_TRY(val.get_string().get(str));
|
||||||
constexpr auto enumerators = std::define_static_array(std::meta::enumerators_of(^^T));
|
static constexpr auto enumerators = std::define_static_array(std::meta::enumerators_of(^^T));
|
||||||
template for (constexpr auto enum_val : enumerators) {
|
template for (constexpr auto enum_val : enumerators) {
|
||||||
if (str == std::meta::identifier_of(enum_val)) {
|
if (str == std::meta::identifier_of(enum_val)) {
|
||||||
out = [:enum_val:];
|
out = [:enum_val:];
|
||||||
|
|||||||
@@ -12,6 +12,8 @@
|
|||||||
#include "simdjson/generic/ondemand/value.h"
|
#include "simdjson/generic/ondemand/value.h"
|
||||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
namespace simdjson {
|
namespace simdjson {
|
||||||
namespace SIMDJSON_IMPLEMENTATION {
|
namespace SIMDJSON_IMPLEMENTATION {
|
||||||
namespace ondemand {
|
namespace ondemand {
|
||||||
@@ -72,6 +74,18 @@ simdjson_inline simdjson_result<int64_t> value::get_int64() noexcept {
|
|||||||
simdjson_inline simdjson_result<int64_t> value::get_int64_in_string() noexcept {
|
simdjson_inline simdjson_result<int64_t> value::get_int64_in_string() noexcept {
|
||||||
return iter.get_int64_in_string();
|
return iter.get_int64_in_string();
|
||||||
}
|
}
|
||||||
|
simdjson_inline simdjson_result<uint32_t> value::get_uint32() noexcept {
|
||||||
|
uint64_t result;
|
||||||
|
SIMDJSON_TRY(get_uint64().get(result));
|
||||||
|
if (result > (std::numeric_limits<uint32_t>::max)()) { return NUMBER_OUT_OF_RANGE; }
|
||||||
|
return static_cast<uint32_t>(result);
|
||||||
|
}
|
||||||
|
simdjson_inline simdjson_result<int32_t> value::get_int32() noexcept {
|
||||||
|
int64_t result;
|
||||||
|
SIMDJSON_TRY(get_int64().get(result));
|
||||||
|
if (result > (std::numeric_limits<int32_t>::max)() || result < (std::numeric_limits<int32_t>::min)()) { return NUMBER_OUT_OF_RANGE; }
|
||||||
|
return static_cast<int32_t>(result);
|
||||||
|
}
|
||||||
simdjson_inline simdjson_result<bool> value::get_bool() noexcept {
|
simdjson_inline simdjson_result<bool> value::get_bool() noexcept {
|
||||||
return iter.get_bool();
|
return iter.get_bool();
|
||||||
}
|
}
|
||||||
@@ -87,6 +101,8 @@ template<> simdjson_inline simdjson_result<number> value::get() noexcept { retur
|
|||||||
template<> simdjson_inline simdjson_result<double> value::get() noexcept { return get_double(); }
|
template<> simdjson_inline simdjson_result<double> value::get() noexcept { return get_double(); }
|
||||||
template<> simdjson_inline simdjson_result<uint64_t> value::get() noexcept { return get_uint64(); }
|
template<> simdjson_inline simdjson_result<uint64_t> value::get() noexcept { return get_uint64(); }
|
||||||
template<> simdjson_inline simdjson_result<int64_t> value::get() noexcept { return get_int64(); }
|
template<> simdjson_inline simdjson_result<int64_t> value::get() noexcept { return get_int64(); }
|
||||||
|
template<> simdjson_inline simdjson_result<uint32_t> value::get() noexcept { return get_uint32(); }
|
||||||
|
template<> simdjson_inline simdjson_result<int32_t> value::get() noexcept { return get_int32(); }
|
||||||
template<> simdjson_inline simdjson_result<bool> value::get() noexcept { return get_bool(); }
|
template<> simdjson_inline simdjson_result<bool> value::get() noexcept { return get_bool(); }
|
||||||
|
|
||||||
|
|
||||||
@@ -98,6 +114,8 @@ template<> simdjson_warn_unused simdjson_inline error_code value::get(number& ou
|
|||||||
template<> simdjson_warn_unused simdjson_inline error_code value::get(double& out) noexcept { return get_double().get(out); }
|
template<> simdjson_warn_unused simdjson_inline error_code value::get(double& out) noexcept { return get_double().get(out); }
|
||||||
template<> simdjson_warn_unused simdjson_inline error_code value::get(uint64_t& out) noexcept { return get_uint64().get(out); }
|
template<> simdjson_warn_unused simdjson_inline error_code value::get(uint64_t& out) noexcept { return get_uint64().get(out); }
|
||||||
template<> simdjson_warn_unused simdjson_inline error_code value::get(int64_t& out) noexcept { return get_int64().get(out); }
|
template<> simdjson_warn_unused simdjson_inline error_code value::get(int64_t& out) noexcept { return get_int64().get(out); }
|
||||||
|
template<> simdjson_warn_unused simdjson_inline error_code value::get(uint32_t& out) noexcept { return get_uint32().get(out); }
|
||||||
|
template<> simdjson_warn_unused simdjson_inline error_code value::get(int32_t& out) noexcept { return get_int32().get(out); }
|
||||||
template<> simdjson_warn_unused simdjson_inline error_code value::get(bool& out) noexcept { return get_bool().get(out); }
|
template<> simdjson_warn_unused simdjson_inline error_code value::get(bool& out) noexcept { return get_bool().get(out); }
|
||||||
|
|
||||||
#if SIMDJSON_EXCEPTIONS
|
#if SIMDJSON_EXCEPTIONS
|
||||||
@@ -401,6 +419,14 @@ simdjson_inline simdjson_result<int64_t> simdjson_result<SIMDJSON_IMPLEMENTATION
|
|||||||
if (error()) { return error(); }
|
if (error()) { return error(); }
|
||||||
return first.get_int64_in_string();
|
return first.get_int64_in_string();
|
||||||
}
|
}
|
||||||
|
simdjson_inline simdjson_result<uint32_t> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::get_uint32() noexcept {
|
||||||
|
if (error()) { return error(); }
|
||||||
|
return first.get_uint32();
|
||||||
|
}
|
||||||
|
simdjson_inline simdjson_result<int32_t> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::get_int32() noexcept {
|
||||||
|
if (error()) { return error(); }
|
||||||
|
return first.get_int32();
|
||||||
|
}
|
||||||
simdjson_inline simdjson_result<double> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::get_double() noexcept {
|
simdjson_inline simdjson_result<double> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::get_double() noexcept {
|
||||||
if (error()) { return error(); }
|
if (error()) { return error(); }
|
||||||
return first.get_double();
|
return first.get_double();
|
||||||
|
|||||||
@@ -161,6 +161,28 @@ public:
|
|||||||
*/
|
*/
|
||||||
simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
|
simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cast this JSON value to a 32-bit unsigned integer.
|
||||||
|
*
|
||||||
|
* Calls get_uint64() and checks that the result fits in a uint32_t.
|
||||||
|
*
|
||||||
|
* @returns A 32-bit unsigned integer.
|
||||||
|
* @returns INCORRECT_TYPE If the JSON value is not an unsigned integer.
|
||||||
|
* @returns NUMBER_OUT_OF_RANGE If the value does not fit in a uint32_t.
|
||||||
|
*/
|
||||||
|
simdjson_inline simdjson_result<uint32_t> get_uint32() noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cast this JSON value to a 32-bit signed integer.
|
||||||
|
*
|
||||||
|
* Calls get_int64() and checks that the result fits in an int32_t.
|
||||||
|
*
|
||||||
|
* @returns A 32-bit signed integer.
|
||||||
|
* @returns INCORRECT_TYPE If the JSON value is not an integer.
|
||||||
|
* @returns NUMBER_OUT_OF_RANGE If the value does not fit in an int32_t.
|
||||||
|
*/
|
||||||
|
simdjson_inline simdjson_result<int32_t> get_int32() noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cast this JSON value to a double.
|
* Cast this JSON value to a double.
|
||||||
*
|
*
|
||||||
@@ -746,6 +768,8 @@ public:
|
|||||||
simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
|
simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
|
||||||
simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
|
simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
|
||||||
simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
|
simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
|
||||||
|
simdjson_inline simdjson_result<uint32_t> get_uint32() noexcept;
|
||||||
|
simdjson_inline simdjson_result<int32_t> get_int32() noexcept;
|
||||||
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;
|
||||||
|
|||||||
@@ -212,6 +212,12 @@ protected:
|
|||||||
*/
|
*/
|
||||||
size_t _max_depth{0};
|
size_t _max_depth{0};
|
||||||
|
|
||||||
|
public:
|
||||||
|
/** Whether to store big integers as strings instead of returning BIGINT_ERROR */
|
||||||
|
bool _number_as_string{false};
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
// Declaring these so that subclasses can use them to implement their constructors.
|
// Declaring these so that subclasses can use them to implement their constructors.
|
||||||
simdjson_inline dom_parser_implementation() noexcept;
|
simdjson_inline dom_parser_implementation() noexcept;
|
||||||
simdjson_inline dom_parser_implementation(dom_parser_implementation &&other) noexcept;
|
simdjson_inline dom_parser_implementation(dom_parser_implementation &&other) noexcept;
|
||||||
|
|||||||
@@ -19,7 +19,8 @@ enum class tape_type {
|
|||||||
DOUBLE = 'd',
|
DOUBLE = 'd',
|
||||||
TRUE_VALUE = 't',
|
TRUE_VALUE = 't',
|
||||||
FALSE_VALUE = 'f',
|
FALSE_VALUE = 'f',
|
||||||
NULL_VALUE = 'n'
|
NULL_VALUE = 'n',
|
||||||
|
BIGINT = 'Z' // Big integer stored as string in string buffer
|
||||||
}; // enum class tape_type
|
}; // enum class tape_type
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
|||||||
@@ -168,10 +168,13 @@ inline padded_string::operator padded_string_view() const noexcept simdjson_life
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline simdjson_result<padded_string> padded_string::load(std::string_view filename) noexcept {
|
inline simdjson_result<padded_string> padded_string::load(std::string_view filename) noexcept {
|
||||||
|
// std::string_view is not guaranteed to be null-terminated, but std::fopen requires
|
||||||
|
// a null-terminated C string. Construct a temporary std::string to ensure null-termination.
|
||||||
|
const std::string null_terminated_filename(filename);
|
||||||
// Open the file
|
// Open the file
|
||||||
SIMDJSON_PUSH_DISABLE_WARNINGS
|
SIMDJSON_PUSH_DISABLE_WARNINGS
|
||||||
SIMDJSON_DISABLE_DEPRECATED_WARNING // Disable CRT_SECURE warning on MSVC: manually verified this is safe
|
SIMDJSON_DISABLE_DEPRECATED_WARNING // Disable CRT_SECURE warning on MSVC: manually verified this is safe
|
||||||
std::FILE *fp = std::fopen(filename.data(), "rb");
|
std::FILE *fp = std::fopen(null_terminated_filename.c_str(), "rb");
|
||||||
SIMDJSON_POP_DISABLE_WARNINGS
|
SIMDJSON_POP_DISABLE_WARNINGS
|
||||||
|
|
||||||
if (fp == nullptr) {
|
if (fp == nullptr) {
|
||||||
@@ -223,10 +226,13 @@ inline simdjson_result<padded_string> padded_string::load(std::string_view filen
|
|||||||
|
|
||||||
#if defined(_WIN32) && SIMDJSON_CPLUSPLUS17
|
#if defined(_WIN32) && SIMDJSON_CPLUSPLUS17
|
||||||
inline simdjson_result<padded_string> padded_string::load(std::wstring_view filename) noexcept {
|
inline simdjson_result<padded_string> padded_string::load(std::wstring_view filename) noexcept {
|
||||||
|
// std::wstring_view is not guaranteed to be null-terminated, but _wfopen requires
|
||||||
|
// a null-terminated wide C string. Construct a temporary std::wstring to ensure null-termination.
|
||||||
|
const std::wstring null_terminated_filename(filename);
|
||||||
// Open the file using the wide characters
|
// Open the file using the wide characters
|
||||||
SIMDJSON_PUSH_DISABLE_WARNINGS
|
SIMDJSON_PUSH_DISABLE_WARNINGS
|
||||||
SIMDJSON_DISABLE_DEPRECATED_WARNING // Disable CRT_SECURE warning on MSVC: manually verified this is safe
|
SIMDJSON_DISABLE_DEPRECATED_WARNING // Disable CRT_SECURE warning on MSVC: manually verified this is safe
|
||||||
std::FILE *fp = _wfopen(filename.data(), L"rb");
|
std::FILE *fp = _wfopen(null_terminated_filename.c_str(), L"rb");
|
||||||
SIMDJSON_POP_DISABLE_WARNINGS
|
SIMDJSON_POP_DISABLE_WARNINGS
|
||||||
|
|
||||||
if (fp == nullptr) {
|
if (fp == nullptr) {
|
||||||
@@ -349,6 +355,9 @@ inline padded_string padded_string_builder::convert() noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline bool padded_string_builder::reserve(size_t additional) noexcept {
|
inline bool padded_string_builder::reserve(size_t additional) noexcept {
|
||||||
|
if (simdjson_unlikely(additional + size < size)) {
|
||||||
|
return false; // overflow: cannot satisfy request
|
||||||
|
}
|
||||||
size_t needed = size + additional;
|
size_t needed = size + additional;
|
||||||
if (needed <= capacity) {
|
if (needed <= capacity) {
|
||||||
return true;
|
return true;
|
||||||
@@ -358,8 +367,9 @@ inline bool padded_string_builder::reserve(size_t additional) noexcept {
|
|||||||
// repeated allocations.
|
// repeated allocations.
|
||||||
if (new_capacity < 4096) {
|
if (new_capacity < 4096) {
|
||||||
new_capacity *= 2;
|
new_capacity *= 2;
|
||||||
} else {
|
// overflow guard: ensure new_capacity + new_capacity/2 does not overflow
|
||||||
new_capacity += new_capacity/2; // grow by 1.5x
|
} else if (new_capacity + new_capacity / 2 > new_capacity) {
|
||||||
|
new_capacity += new_capacity / 2; // grow by 1.5x
|
||||||
}
|
}
|
||||||
char *new_data = internal::allocate_padded_buffer(new_capacity);
|
char *new_data = internal::allocate_padded_buffer(new_capacity);
|
||||||
if (new_data == nullptr) {
|
if (new_data == nullptr) {
|
||||||
|
|||||||
@@ -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 "4.4.2"
|
#define SIMDJSON_VERSION "4.6.1"
|
||||||
|
|
||||||
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 = 4,
|
SIMDJSON_VERSION_MINOR = 6,
|
||||||
/**
|
/**
|
||||||
* 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 = 1
|
||||||
};
|
};
|
||||||
} // namespace simdjson
|
} // namespace simdjson
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"app_name": "MyApp",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"port": 8080,
|
||||||
|
"debug": true,
|
||||||
|
"features": ["logging", "caching"],
|
||||||
|
"database": {
|
||||||
|
"host": "localhost",
|
||||||
|
"port": 5432
|
||||||
|
}
|
||||||
|
}
|
||||||
+302
-11
@@ -1,4 +1,4 @@
|
|||||||
/* auto-generated on 2026-03-20 11:11:38 -0400. version 4.4.2 Do not edit! */
|
/* auto-generated on 2026-04-02 19:14:16 -0400. version 4.6.1 Do not edit! */
|
||||||
/* including simdjson.cpp: */
|
/* including simdjson.cpp: */
|
||||||
/* begin file simdjson.cpp */
|
/* begin file simdjson.cpp */
|
||||||
#define SIMDJSON_SRC_SIMDJSON_CPP
|
#define SIMDJSON_SRC_SIMDJSON_CPP
|
||||||
@@ -3168,6 +3168,11 @@ struct fixed_string {
|
|||||||
data[i] = str[i];
|
data[i] = str[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
constexpr fixed_string(const unsigned char (&str)[N]) {
|
||||||
|
for (std::size_t i = 0; i < N; ++i) {
|
||||||
|
data[i] = static_cast<char>(str[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
char data[N];
|
char data[N];
|
||||||
constexpr std::string_view view() const { return {data, N - 1}; }
|
constexpr std::string_view view() const { return {data, N - 1}; }
|
||||||
constexpr size_t size() const { return N ; }
|
constexpr size_t size() const { return N ; }
|
||||||
@@ -7308,6 +7313,12 @@ protected:
|
|||||||
*/
|
*/
|
||||||
size_t _max_depth{0};
|
size_t _max_depth{0};
|
||||||
|
|
||||||
|
public:
|
||||||
|
/** Whether to store big integers as strings instead of returning BIGINT_ERROR */
|
||||||
|
bool _number_as_string{false};
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
// Declaring these so that subclasses can use them to implement their constructors.
|
// Declaring these so that subclasses can use them to implement their constructors.
|
||||||
simdjson_inline dom_parser_implementation() noexcept;
|
simdjson_inline dom_parser_implementation() noexcept;
|
||||||
simdjson_inline dom_parser_implementation(dom_parser_implementation &&other) noexcept;
|
simdjson_inline dom_parser_implementation(dom_parser_implementation &&other) noexcept;
|
||||||
@@ -7883,7 +7894,8 @@ enum class tape_type {
|
|||||||
DOUBLE = 'd',
|
DOUBLE = 'd',
|
||||||
TRUE_VALUE = 't',
|
TRUE_VALUE = 't',
|
||||||
FALSE_VALUE = 'f',
|
FALSE_VALUE = 'f',
|
||||||
NULL_VALUE = 'n'
|
NULL_VALUE = 'n',
|
||||||
|
BIGINT = 'Z' // Big integer stored as string in string buffer
|
||||||
}; // enum class tape_type
|
}; // enum class tape_type
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
@@ -14178,6 +14190,9 @@ struct tape_writer {
|
|||||||
/** Write a double value to tape. */
|
/** Write a double value to tape. */
|
||||||
simdjson_inline void append_double(double value) noexcept;
|
simdjson_inline void append_double(double value) noexcept;
|
||||||
|
|
||||||
|
/** Write a big integer (as string) to tape. src points to first digit, len is byte count. */
|
||||||
|
simdjson_inline void append_bigint(const uint8_t *src, size_t len, uint8_t *&string_buf) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Append a tape entry (an 8-bit type,and 56 bits worth of value).
|
* Append a tape entry (an 8-bit type,and 56 bits worth of value).
|
||||||
*/
|
*/
|
||||||
@@ -14261,6 +14276,18 @@ simdjson_inline void tape_writer::write(uint64_t &tape_loc, uint64_t val, intern
|
|||||||
tape_loc = val | ((uint64_t(char(t))) << 56);
|
tape_loc = val | ((uint64_t(char(t))) << 56);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
simdjson_inline void tape_writer::append_bigint(const uint8_t *src, size_t len, uint8_t *&string_buf) noexcept {
|
||||||
|
// Write to string buffer: [4-byte LE length][digits][null]
|
||||||
|
uint32_t str_len = uint32_t(len);
|
||||||
|
memcpy(string_buf, &str_len, sizeof(uint32_t));
|
||||||
|
memcpy(string_buf + sizeof(uint32_t), src, len);
|
||||||
|
string_buf[sizeof(uint32_t) + len] = 0;
|
||||||
|
// Tape entry: offset into string buffer
|
||||||
|
// The caller must set the offset relative to doc.string_buf base
|
||||||
|
append(0, internal::tape_type::BIGINT); // placeholder offset, caller patches
|
||||||
|
string_buf += sizeof(uint32_t) + len + 1;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace stage2
|
} // namespace stage2
|
||||||
} // unnamed namespace
|
} // unnamed namespace
|
||||||
} // namespace arm64
|
} // namespace arm64
|
||||||
@@ -15198,7 +15225,23 @@ simdjson_warn_unused simdjson_inline error_code tape_builder::visit_root_string(
|
|||||||
|
|
||||||
simdjson_warn_unused simdjson_inline error_code tape_builder::visit_number(json_iterator &iter, const uint8_t *value) noexcept {
|
simdjson_warn_unused simdjson_inline error_code tape_builder::visit_number(json_iterator &iter, const uint8_t *value) noexcept {
|
||||||
iter.log_value("number");
|
iter.log_value("number");
|
||||||
return numberparsing::parse_number(value, tape);
|
error_code err = numberparsing::parse_number(value, tape);
|
||||||
|
if (simdjson_unlikely(err == BIGINT_ERROR &&
|
||||||
|
iter.dom_parser._number_as_string)) {
|
||||||
|
// Write big integer to string buffer using the same format as strings.
|
||||||
|
// Scan digits the same way parse_number does (skip optional '-', then digits).
|
||||||
|
const uint8_t *p = value;
|
||||||
|
if (*p == '-') p++;
|
||||||
|
while (numberparsing::is_digit(*p)) p++;
|
||||||
|
size_t len = size_t(p - value);
|
||||||
|
tape.append(current_string_buf_loc - iter.dom_parser.doc->string_buf.get(), internal::tape_type::BIGINT);
|
||||||
|
uint8_t *dst = current_string_buf_loc + sizeof(uint32_t);
|
||||||
|
memcpy(dst, value, len);
|
||||||
|
dst += len;
|
||||||
|
on_end_string(dst);
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
simdjson_warn_unused simdjson_inline error_code tape_builder::visit_root_number(json_iterator &iter, const uint8_t *value) noexcept {
|
simdjson_warn_unused simdjson_inline error_code tape_builder::visit_root_number(json_iterator &iter, const uint8_t *value) noexcept {
|
||||||
@@ -20539,6 +20582,9 @@ struct tape_writer {
|
|||||||
/** Write a double value to tape. */
|
/** Write a double value to tape. */
|
||||||
simdjson_inline void append_double(double value) noexcept;
|
simdjson_inline void append_double(double value) noexcept;
|
||||||
|
|
||||||
|
/** Write a big integer (as string) to tape. src points to first digit, len is byte count. */
|
||||||
|
simdjson_inline void append_bigint(const uint8_t *src, size_t len, uint8_t *&string_buf) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Append a tape entry (an 8-bit type,and 56 bits worth of value).
|
* Append a tape entry (an 8-bit type,and 56 bits worth of value).
|
||||||
*/
|
*/
|
||||||
@@ -20622,6 +20668,18 @@ simdjson_inline void tape_writer::write(uint64_t &tape_loc, uint64_t val, intern
|
|||||||
tape_loc = val | ((uint64_t(char(t))) << 56);
|
tape_loc = val | ((uint64_t(char(t))) << 56);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
simdjson_inline void tape_writer::append_bigint(const uint8_t *src, size_t len, uint8_t *&string_buf) noexcept {
|
||||||
|
// Write to string buffer: [4-byte LE length][digits][null]
|
||||||
|
uint32_t str_len = uint32_t(len);
|
||||||
|
memcpy(string_buf, &str_len, sizeof(uint32_t));
|
||||||
|
memcpy(string_buf + sizeof(uint32_t), src, len);
|
||||||
|
string_buf[sizeof(uint32_t) + len] = 0;
|
||||||
|
// Tape entry: offset into string buffer
|
||||||
|
// The caller must set the offset relative to doc.string_buf base
|
||||||
|
append(0, internal::tape_type::BIGINT); // placeholder offset, caller patches
|
||||||
|
string_buf += sizeof(uint32_t) + len + 1;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace stage2
|
} // namespace stage2
|
||||||
} // unnamed namespace
|
} // unnamed namespace
|
||||||
} // namespace haswell
|
} // namespace haswell
|
||||||
@@ -21559,7 +21617,23 @@ simdjson_warn_unused simdjson_inline error_code tape_builder::visit_root_string(
|
|||||||
|
|
||||||
simdjson_warn_unused simdjson_inline error_code tape_builder::visit_number(json_iterator &iter, const uint8_t *value) noexcept {
|
simdjson_warn_unused simdjson_inline error_code tape_builder::visit_number(json_iterator &iter, const uint8_t *value) noexcept {
|
||||||
iter.log_value("number");
|
iter.log_value("number");
|
||||||
return numberparsing::parse_number(value, tape);
|
error_code err = numberparsing::parse_number(value, tape);
|
||||||
|
if (simdjson_unlikely(err == BIGINT_ERROR &&
|
||||||
|
iter.dom_parser._number_as_string)) {
|
||||||
|
// Write big integer to string buffer using the same format as strings.
|
||||||
|
// Scan digits the same way parse_number does (skip optional '-', then digits).
|
||||||
|
const uint8_t *p = value;
|
||||||
|
if (*p == '-') p++;
|
||||||
|
while (numberparsing::is_digit(*p)) p++;
|
||||||
|
size_t len = size_t(p - value);
|
||||||
|
tape.append(current_string_buf_loc - iter.dom_parser.doc->string_buf.get(), internal::tape_type::BIGINT);
|
||||||
|
uint8_t *dst = current_string_buf_loc + sizeof(uint32_t);
|
||||||
|
memcpy(dst, value, len);
|
||||||
|
dst += len;
|
||||||
|
on_end_string(dst);
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
simdjson_warn_unused simdjson_inline error_code tape_builder::visit_root_number(json_iterator &iter, const uint8_t *value) noexcept {
|
simdjson_warn_unused simdjson_inline error_code tape_builder::visit_root_number(json_iterator &iter, const uint8_t *value) noexcept {
|
||||||
@@ -26895,6 +26969,9 @@ struct tape_writer {
|
|||||||
/** Write a double value to tape. */
|
/** Write a double value to tape. */
|
||||||
simdjson_inline void append_double(double value) noexcept;
|
simdjson_inline void append_double(double value) noexcept;
|
||||||
|
|
||||||
|
/** Write a big integer (as string) to tape. src points to first digit, len is byte count. */
|
||||||
|
simdjson_inline void append_bigint(const uint8_t *src, size_t len, uint8_t *&string_buf) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Append a tape entry (an 8-bit type,and 56 bits worth of value).
|
* Append a tape entry (an 8-bit type,and 56 bits worth of value).
|
||||||
*/
|
*/
|
||||||
@@ -26978,6 +27055,18 @@ simdjson_inline void tape_writer::write(uint64_t &tape_loc, uint64_t val, intern
|
|||||||
tape_loc = val | ((uint64_t(char(t))) << 56);
|
tape_loc = val | ((uint64_t(char(t))) << 56);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
simdjson_inline void tape_writer::append_bigint(const uint8_t *src, size_t len, uint8_t *&string_buf) noexcept {
|
||||||
|
// Write to string buffer: [4-byte LE length][digits][null]
|
||||||
|
uint32_t str_len = uint32_t(len);
|
||||||
|
memcpy(string_buf, &str_len, sizeof(uint32_t));
|
||||||
|
memcpy(string_buf + sizeof(uint32_t), src, len);
|
||||||
|
string_buf[sizeof(uint32_t) + len] = 0;
|
||||||
|
// Tape entry: offset into string buffer
|
||||||
|
// The caller must set the offset relative to doc.string_buf base
|
||||||
|
append(0, internal::tape_type::BIGINT); // placeholder offset, caller patches
|
||||||
|
string_buf += sizeof(uint32_t) + len + 1;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace stage2
|
} // namespace stage2
|
||||||
} // unnamed namespace
|
} // unnamed namespace
|
||||||
} // namespace icelake
|
} // namespace icelake
|
||||||
@@ -27915,7 +28004,23 @@ simdjson_warn_unused simdjson_inline error_code tape_builder::visit_root_string(
|
|||||||
|
|
||||||
simdjson_warn_unused simdjson_inline error_code tape_builder::visit_number(json_iterator &iter, const uint8_t *value) noexcept {
|
simdjson_warn_unused simdjson_inline error_code tape_builder::visit_number(json_iterator &iter, const uint8_t *value) noexcept {
|
||||||
iter.log_value("number");
|
iter.log_value("number");
|
||||||
return numberparsing::parse_number(value, tape);
|
error_code err = numberparsing::parse_number(value, tape);
|
||||||
|
if (simdjson_unlikely(err == BIGINT_ERROR &&
|
||||||
|
iter.dom_parser._number_as_string)) {
|
||||||
|
// Write big integer to string buffer using the same format as strings.
|
||||||
|
// Scan digits the same way parse_number does (skip optional '-', then digits).
|
||||||
|
const uint8_t *p = value;
|
||||||
|
if (*p == '-') p++;
|
||||||
|
while (numberparsing::is_digit(*p)) p++;
|
||||||
|
size_t len = size_t(p - value);
|
||||||
|
tape.append(current_string_buf_loc - iter.dom_parser.doc->string_buf.get(), internal::tape_type::BIGINT);
|
||||||
|
uint8_t *dst = current_string_buf_loc + sizeof(uint32_t);
|
||||||
|
memcpy(dst, value, len);
|
||||||
|
dst += len;
|
||||||
|
on_end_string(dst);
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
simdjson_warn_unused simdjson_inline error_code tape_builder::visit_root_number(json_iterator &iter, const uint8_t *value) noexcept {
|
simdjson_warn_unused simdjson_inline error_code tape_builder::visit_root_number(json_iterator &iter, const uint8_t *value) noexcept {
|
||||||
@@ -33522,6 +33627,9 @@ struct tape_writer {
|
|||||||
/** Write a double value to tape. */
|
/** Write a double value to tape. */
|
||||||
simdjson_inline void append_double(double value) noexcept;
|
simdjson_inline void append_double(double value) noexcept;
|
||||||
|
|
||||||
|
/** Write a big integer (as string) to tape. src points to first digit, len is byte count. */
|
||||||
|
simdjson_inline void append_bigint(const uint8_t *src, size_t len, uint8_t *&string_buf) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Append a tape entry (an 8-bit type,and 56 bits worth of value).
|
* Append a tape entry (an 8-bit type,and 56 bits worth of value).
|
||||||
*/
|
*/
|
||||||
@@ -33605,6 +33713,18 @@ simdjson_inline void tape_writer::write(uint64_t &tape_loc, uint64_t val, intern
|
|||||||
tape_loc = val | ((uint64_t(char(t))) << 56);
|
tape_loc = val | ((uint64_t(char(t))) << 56);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
simdjson_inline void tape_writer::append_bigint(const uint8_t *src, size_t len, uint8_t *&string_buf) noexcept {
|
||||||
|
// Write to string buffer: [4-byte LE length][digits][null]
|
||||||
|
uint32_t str_len = uint32_t(len);
|
||||||
|
memcpy(string_buf, &str_len, sizeof(uint32_t));
|
||||||
|
memcpy(string_buf + sizeof(uint32_t), src, len);
|
||||||
|
string_buf[sizeof(uint32_t) + len] = 0;
|
||||||
|
// Tape entry: offset into string buffer
|
||||||
|
// The caller must set the offset relative to doc.string_buf base
|
||||||
|
append(0, internal::tape_type::BIGINT); // placeholder offset, caller patches
|
||||||
|
string_buf += sizeof(uint32_t) + len + 1;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace stage2
|
} // namespace stage2
|
||||||
} // unnamed namespace
|
} // unnamed namespace
|
||||||
} // namespace ppc64
|
} // namespace ppc64
|
||||||
@@ -34542,7 +34662,23 @@ simdjson_warn_unused simdjson_inline error_code tape_builder::visit_root_string(
|
|||||||
|
|
||||||
simdjson_warn_unused simdjson_inline error_code tape_builder::visit_number(json_iterator &iter, const uint8_t *value) noexcept {
|
simdjson_warn_unused simdjson_inline error_code tape_builder::visit_number(json_iterator &iter, const uint8_t *value) noexcept {
|
||||||
iter.log_value("number");
|
iter.log_value("number");
|
||||||
return numberparsing::parse_number(value, tape);
|
error_code err = numberparsing::parse_number(value, tape);
|
||||||
|
if (simdjson_unlikely(err == BIGINT_ERROR &&
|
||||||
|
iter.dom_parser._number_as_string)) {
|
||||||
|
// Write big integer to string buffer using the same format as strings.
|
||||||
|
// Scan digits the same way parse_number does (skip optional '-', then digits).
|
||||||
|
const uint8_t *p = value;
|
||||||
|
if (*p == '-') p++;
|
||||||
|
while (numberparsing::is_digit(*p)) p++;
|
||||||
|
size_t len = size_t(p - value);
|
||||||
|
tape.append(current_string_buf_loc - iter.dom_parser.doc->string_buf.get(), internal::tape_type::BIGINT);
|
||||||
|
uint8_t *dst = current_string_buf_loc + sizeof(uint32_t);
|
||||||
|
memcpy(dst, value, len);
|
||||||
|
dst += len;
|
||||||
|
on_end_string(dst);
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
simdjson_warn_unused simdjson_inline error_code tape_builder::visit_root_number(json_iterator &iter, const uint8_t *value) noexcept {
|
simdjson_warn_unused simdjson_inline error_code tape_builder::visit_root_number(json_iterator &iter, const uint8_t *value) noexcept {
|
||||||
@@ -40711,6 +40847,9 @@ struct tape_writer {
|
|||||||
/** Write a double value to tape. */
|
/** Write a double value to tape. */
|
||||||
simdjson_inline void append_double(double value) noexcept;
|
simdjson_inline void append_double(double value) noexcept;
|
||||||
|
|
||||||
|
/** Write a big integer (as string) to tape. src points to first digit, len is byte count. */
|
||||||
|
simdjson_inline void append_bigint(const uint8_t *src, size_t len, uint8_t *&string_buf) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Append a tape entry (an 8-bit type,and 56 bits worth of value).
|
* Append a tape entry (an 8-bit type,and 56 bits worth of value).
|
||||||
*/
|
*/
|
||||||
@@ -40794,6 +40933,18 @@ simdjson_inline void tape_writer::write(uint64_t &tape_loc, uint64_t val, intern
|
|||||||
tape_loc = val | ((uint64_t(char(t))) << 56);
|
tape_loc = val | ((uint64_t(char(t))) << 56);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
simdjson_inline void tape_writer::append_bigint(const uint8_t *src, size_t len, uint8_t *&string_buf) noexcept {
|
||||||
|
// Write to string buffer: [4-byte LE length][digits][null]
|
||||||
|
uint32_t str_len = uint32_t(len);
|
||||||
|
memcpy(string_buf, &str_len, sizeof(uint32_t));
|
||||||
|
memcpy(string_buf + sizeof(uint32_t), src, len);
|
||||||
|
string_buf[sizeof(uint32_t) + len] = 0;
|
||||||
|
// Tape entry: offset into string buffer
|
||||||
|
// The caller must set the offset relative to doc.string_buf base
|
||||||
|
append(0, internal::tape_type::BIGINT); // placeholder offset, caller patches
|
||||||
|
string_buf += sizeof(uint32_t) + len + 1;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace stage2
|
} // namespace stage2
|
||||||
} // unnamed namespace
|
} // unnamed namespace
|
||||||
} // namespace westmere
|
} // namespace westmere
|
||||||
@@ -41731,7 +41882,23 @@ simdjson_warn_unused simdjson_inline error_code tape_builder::visit_root_string(
|
|||||||
|
|
||||||
simdjson_warn_unused simdjson_inline error_code tape_builder::visit_number(json_iterator &iter, const uint8_t *value) noexcept {
|
simdjson_warn_unused simdjson_inline error_code tape_builder::visit_number(json_iterator &iter, const uint8_t *value) noexcept {
|
||||||
iter.log_value("number");
|
iter.log_value("number");
|
||||||
return numberparsing::parse_number(value, tape);
|
error_code err = numberparsing::parse_number(value, tape);
|
||||||
|
if (simdjson_unlikely(err == BIGINT_ERROR &&
|
||||||
|
iter.dom_parser._number_as_string)) {
|
||||||
|
// Write big integer to string buffer using the same format as strings.
|
||||||
|
// Scan digits the same way parse_number does (skip optional '-', then digits).
|
||||||
|
const uint8_t *p = value;
|
||||||
|
if (*p == '-') p++;
|
||||||
|
while (numberparsing::is_digit(*p)) p++;
|
||||||
|
size_t len = size_t(p - value);
|
||||||
|
tape.append(current_string_buf_loc - iter.dom_parser.doc->string_buf.get(), internal::tape_type::BIGINT);
|
||||||
|
uint8_t *dst = current_string_buf_loc + sizeof(uint32_t);
|
||||||
|
memcpy(dst, value, len);
|
||||||
|
dst += len;
|
||||||
|
on_end_string(dst);
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
simdjson_warn_unused simdjson_inline error_code tape_builder::visit_root_number(json_iterator &iter, const uint8_t *value) noexcept {
|
simdjson_warn_unused simdjson_inline error_code tape_builder::visit_root_number(json_iterator &iter, const uint8_t *value) noexcept {
|
||||||
@@ -46931,6 +47098,9 @@ struct tape_writer {
|
|||||||
/** Write a double value to tape. */
|
/** Write a double value to tape. */
|
||||||
simdjson_inline void append_double(double value) noexcept;
|
simdjson_inline void append_double(double value) noexcept;
|
||||||
|
|
||||||
|
/** Write a big integer (as string) to tape. src points to first digit, len is byte count. */
|
||||||
|
simdjson_inline void append_bigint(const uint8_t *src, size_t len, uint8_t *&string_buf) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Append a tape entry (an 8-bit type,and 56 bits worth of value).
|
* Append a tape entry (an 8-bit type,and 56 bits worth of value).
|
||||||
*/
|
*/
|
||||||
@@ -47014,6 +47184,18 @@ simdjson_inline void tape_writer::write(uint64_t &tape_loc, uint64_t val, intern
|
|||||||
tape_loc = val | ((uint64_t(char(t))) << 56);
|
tape_loc = val | ((uint64_t(char(t))) << 56);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
simdjson_inline void tape_writer::append_bigint(const uint8_t *src, size_t len, uint8_t *&string_buf) noexcept {
|
||||||
|
// Write to string buffer: [4-byte LE length][digits][null]
|
||||||
|
uint32_t str_len = uint32_t(len);
|
||||||
|
memcpy(string_buf, &str_len, sizeof(uint32_t));
|
||||||
|
memcpy(string_buf + sizeof(uint32_t), src, len);
|
||||||
|
string_buf[sizeof(uint32_t) + len] = 0;
|
||||||
|
// Tape entry: offset into string buffer
|
||||||
|
// The caller must set the offset relative to doc.string_buf base
|
||||||
|
append(0, internal::tape_type::BIGINT); // placeholder offset, caller patches
|
||||||
|
string_buf += sizeof(uint32_t) + len + 1;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace stage2
|
} // namespace stage2
|
||||||
} // unnamed namespace
|
} // unnamed namespace
|
||||||
} // namespace lasx
|
} // namespace lasx
|
||||||
@@ -47951,7 +48133,23 @@ simdjson_warn_unused simdjson_inline error_code tape_builder::visit_root_string(
|
|||||||
|
|
||||||
simdjson_warn_unused simdjson_inline error_code tape_builder::visit_number(json_iterator &iter, const uint8_t *value) noexcept {
|
simdjson_warn_unused simdjson_inline error_code tape_builder::visit_number(json_iterator &iter, const uint8_t *value) noexcept {
|
||||||
iter.log_value("number");
|
iter.log_value("number");
|
||||||
return numberparsing::parse_number(value, tape);
|
error_code err = numberparsing::parse_number(value, tape);
|
||||||
|
if (simdjson_unlikely(err == BIGINT_ERROR &&
|
||||||
|
iter.dom_parser._number_as_string)) {
|
||||||
|
// Write big integer to string buffer using the same format as strings.
|
||||||
|
// Scan digits the same way parse_number does (skip optional '-', then digits).
|
||||||
|
const uint8_t *p = value;
|
||||||
|
if (*p == '-') p++;
|
||||||
|
while (numberparsing::is_digit(*p)) p++;
|
||||||
|
size_t len = size_t(p - value);
|
||||||
|
tape.append(current_string_buf_loc - iter.dom_parser.doc->string_buf.get(), internal::tape_type::BIGINT);
|
||||||
|
uint8_t *dst = current_string_buf_loc + sizeof(uint32_t);
|
||||||
|
memcpy(dst, value, len);
|
||||||
|
dst += len;
|
||||||
|
on_end_string(dst);
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
simdjson_warn_unused simdjson_inline error_code tape_builder::visit_root_number(json_iterator &iter, const uint8_t *value) noexcept {
|
simdjson_warn_unused simdjson_inline error_code tape_builder::visit_root_number(json_iterator &iter, const uint8_t *value) noexcept {
|
||||||
@@ -53055,6 +53253,9 @@ struct tape_writer {
|
|||||||
/** Write a double value to tape. */
|
/** Write a double value to tape. */
|
||||||
simdjson_inline void append_double(double value) noexcept;
|
simdjson_inline void append_double(double value) noexcept;
|
||||||
|
|
||||||
|
/** Write a big integer (as string) to tape. src points to first digit, len is byte count. */
|
||||||
|
simdjson_inline void append_bigint(const uint8_t *src, size_t len, uint8_t *&string_buf) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Append a tape entry (an 8-bit type,and 56 bits worth of value).
|
* Append a tape entry (an 8-bit type,and 56 bits worth of value).
|
||||||
*/
|
*/
|
||||||
@@ -53138,6 +53339,18 @@ simdjson_inline void tape_writer::write(uint64_t &tape_loc, uint64_t val, intern
|
|||||||
tape_loc = val | ((uint64_t(char(t))) << 56);
|
tape_loc = val | ((uint64_t(char(t))) << 56);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
simdjson_inline void tape_writer::append_bigint(const uint8_t *src, size_t len, uint8_t *&string_buf) noexcept {
|
||||||
|
// Write to string buffer: [4-byte LE length][digits][null]
|
||||||
|
uint32_t str_len = uint32_t(len);
|
||||||
|
memcpy(string_buf, &str_len, sizeof(uint32_t));
|
||||||
|
memcpy(string_buf + sizeof(uint32_t), src, len);
|
||||||
|
string_buf[sizeof(uint32_t) + len] = 0;
|
||||||
|
// Tape entry: offset into string buffer
|
||||||
|
// The caller must set the offset relative to doc.string_buf base
|
||||||
|
append(0, internal::tape_type::BIGINT); // placeholder offset, caller patches
|
||||||
|
string_buf += sizeof(uint32_t) + len + 1;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace stage2
|
} // namespace stage2
|
||||||
} // unnamed namespace
|
} // unnamed namespace
|
||||||
} // namespace lsx
|
} // namespace lsx
|
||||||
@@ -54075,7 +54288,23 @@ simdjson_warn_unused simdjson_inline error_code tape_builder::visit_root_string(
|
|||||||
|
|
||||||
simdjson_warn_unused simdjson_inline error_code tape_builder::visit_number(json_iterator &iter, const uint8_t *value) noexcept {
|
simdjson_warn_unused simdjson_inline error_code tape_builder::visit_number(json_iterator &iter, const uint8_t *value) noexcept {
|
||||||
iter.log_value("number");
|
iter.log_value("number");
|
||||||
return numberparsing::parse_number(value, tape);
|
error_code err = numberparsing::parse_number(value, tape);
|
||||||
|
if (simdjson_unlikely(err == BIGINT_ERROR &&
|
||||||
|
iter.dom_parser._number_as_string)) {
|
||||||
|
// Write big integer to string buffer using the same format as strings.
|
||||||
|
// Scan digits the same way parse_number does (skip optional '-', then digits).
|
||||||
|
const uint8_t *p = value;
|
||||||
|
if (*p == '-') p++;
|
||||||
|
while (numberparsing::is_digit(*p)) p++;
|
||||||
|
size_t len = size_t(p - value);
|
||||||
|
tape.append(current_string_buf_loc - iter.dom_parser.doc->string_buf.get(), internal::tape_type::BIGINT);
|
||||||
|
uint8_t *dst = current_string_buf_loc + sizeof(uint32_t);
|
||||||
|
memcpy(dst, value, len);
|
||||||
|
dst += len;
|
||||||
|
on_end_string(dst);
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
simdjson_warn_unused simdjson_inline error_code tape_builder::visit_root_number(json_iterator &iter, const uint8_t *value) noexcept {
|
simdjson_warn_unused simdjson_inline error_code tape_builder::visit_root_number(json_iterator &iter, const uint8_t *value) noexcept {
|
||||||
@@ -59598,6 +59827,9 @@ struct tape_writer {
|
|||||||
/** Write a double value to tape. */
|
/** Write a double value to tape. */
|
||||||
simdjson_inline void append_double(double value) noexcept;
|
simdjson_inline void append_double(double value) noexcept;
|
||||||
|
|
||||||
|
/** Write a big integer (as string) to tape. src points to first digit, len is byte count. */
|
||||||
|
simdjson_inline void append_bigint(const uint8_t *src, size_t len, uint8_t *&string_buf) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Append a tape entry (an 8-bit type,and 56 bits worth of value).
|
* Append a tape entry (an 8-bit type,and 56 bits worth of value).
|
||||||
*/
|
*/
|
||||||
@@ -59681,6 +59913,18 @@ simdjson_inline void tape_writer::write(uint64_t &tape_loc, uint64_t val, intern
|
|||||||
tape_loc = val | ((uint64_t(char(t))) << 56);
|
tape_loc = val | ((uint64_t(char(t))) << 56);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
simdjson_inline void tape_writer::append_bigint(const uint8_t *src, size_t len, uint8_t *&string_buf) noexcept {
|
||||||
|
// Write to string buffer: [4-byte LE length][digits][null]
|
||||||
|
uint32_t str_len = uint32_t(len);
|
||||||
|
memcpy(string_buf, &str_len, sizeof(uint32_t));
|
||||||
|
memcpy(string_buf + sizeof(uint32_t), src, len);
|
||||||
|
string_buf[sizeof(uint32_t) + len] = 0;
|
||||||
|
// Tape entry: offset into string buffer
|
||||||
|
// The caller must set the offset relative to doc.string_buf base
|
||||||
|
append(0, internal::tape_type::BIGINT); // placeholder offset, caller patches
|
||||||
|
string_buf += sizeof(uint32_t) + len + 1;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace stage2
|
} // namespace stage2
|
||||||
} // unnamed namespace
|
} // unnamed namespace
|
||||||
} // namespace rvv_vls
|
} // namespace rvv_vls
|
||||||
@@ -60618,7 +60862,23 @@ simdjson_warn_unused simdjson_inline error_code tape_builder::visit_root_string(
|
|||||||
|
|
||||||
simdjson_warn_unused simdjson_inline error_code tape_builder::visit_number(json_iterator &iter, const uint8_t *value) noexcept {
|
simdjson_warn_unused simdjson_inline error_code tape_builder::visit_number(json_iterator &iter, const uint8_t *value) noexcept {
|
||||||
iter.log_value("number");
|
iter.log_value("number");
|
||||||
return numberparsing::parse_number(value, tape);
|
error_code err = numberparsing::parse_number(value, tape);
|
||||||
|
if (simdjson_unlikely(err == BIGINT_ERROR &&
|
||||||
|
iter.dom_parser._number_as_string)) {
|
||||||
|
// Write big integer to string buffer using the same format as strings.
|
||||||
|
// Scan digits the same way parse_number does (skip optional '-', then digits).
|
||||||
|
const uint8_t *p = value;
|
||||||
|
if (*p == '-') p++;
|
||||||
|
while (numberparsing::is_digit(*p)) p++;
|
||||||
|
size_t len = size_t(p - value);
|
||||||
|
tape.append(current_string_buf_loc - iter.dom_parser.doc->string_buf.get(), internal::tape_type::BIGINT);
|
||||||
|
uint8_t *dst = current_string_buf_loc + sizeof(uint32_t);
|
||||||
|
memcpy(dst, value, len);
|
||||||
|
dst += len;
|
||||||
|
on_end_string(dst);
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
simdjson_warn_unused simdjson_inline error_code tape_builder::visit_root_number(json_iterator &iter, const uint8_t *value) noexcept {
|
simdjson_warn_unused simdjson_inline error_code tape_builder::visit_root_number(json_iterator &iter, const uint8_t *value) noexcept {
|
||||||
@@ -64189,6 +64449,9 @@ struct tape_writer {
|
|||||||
/** Write a double value to tape. */
|
/** Write a double value to tape. */
|
||||||
simdjson_inline void append_double(double value) noexcept;
|
simdjson_inline void append_double(double value) noexcept;
|
||||||
|
|
||||||
|
/** Write a big integer (as string) to tape. src points to first digit, len is byte count. */
|
||||||
|
simdjson_inline void append_bigint(const uint8_t *src, size_t len, uint8_t *&string_buf) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Append a tape entry (an 8-bit type,and 56 bits worth of value).
|
* Append a tape entry (an 8-bit type,and 56 bits worth of value).
|
||||||
*/
|
*/
|
||||||
@@ -64272,6 +64535,18 @@ simdjson_inline void tape_writer::write(uint64_t &tape_loc, uint64_t val, intern
|
|||||||
tape_loc = val | ((uint64_t(char(t))) << 56);
|
tape_loc = val | ((uint64_t(char(t))) << 56);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
simdjson_inline void tape_writer::append_bigint(const uint8_t *src, size_t len, uint8_t *&string_buf) noexcept {
|
||||||
|
// Write to string buffer: [4-byte LE length][digits][null]
|
||||||
|
uint32_t str_len = uint32_t(len);
|
||||||
|
memcpy(string_buf, &str_len, sizeof(uint32_t));
|
||||||
|
memcpy(string_buf + sizeof(uint32_t), src, len);
|
||||||
|
string_buf[sizeof(uint32_t) + len] = 0;
|
||||||
|
// Tape entry: offset into string buffer
|
||||||
|
// The caller must set the offset relative to doc.string_buf base
|
||||||
|
append(0, internal::tape_type::BIGINT); // placeholder offset, caller patches
|
||||||
|
string_buf += sizeof(uint32_t) + len + 1;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace stage2
|
} // namespace stage2
|
||||||
} // unnamed namespace
|
} // unnamed namespace
|
||||||
} // namespace fallback
|
} // namespace fallback
|
||||||
@@ -64455,7 +64730,23 @@ simdjson_warn_unused simdjson_inline error_code tape_builder::visit_root_string(
|
|||||||
|
|
||||||
simdjson_warn_unused simdjson_inline error_code tape_builder::visit_number(json_iterator &iter, const uint8_t *value) noexcept {
|
simdjson_warn_unused simdjson_inline error_code tape_builder::visit_number(json_iterator &iter, const uint8_t *value) noexcept {
|
||||||
iter.log_value("number");
|
iter.log_value("number");
|
||||||
return numberparsing::parse_number(value, tape);
|
error_code err = numberparsing::parse_number(value, tape);
|
||||||
|
if (simdjson_unlikely(err == BIGINT_ERROR &&
|
||||||
|
iter.dom_parser._number_as_string)) {
|
||||||
|
// Write big integer to string buffer using the same format as strings.
|
||||||
|
// Scan digits the same way parse_number does (skip optional '-', then digits).
|
||||||
|
const uint8_t *p = value;
|
||||||
|
if (*p == '-') p++;
|
||||||
|
while (numberparsing::is_digit(*p)) p++;
|
||||||
|
size_t len = size_t(p - value);
|
||||||
|
tape.append(current_string_buf_loc - iter.dom_parser.doc->string_buf.get(), internal::tape_type::BIGINT);
|
||||||
|
uint8_t *dst = current_string_buf_loc + sizeof(uint32_t);
|
||||||
|
memcpy(dst, value, len);
|
||||||
|
dst += len;
|
||||||
|
on_end_string(dst);
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
simdjson_warn_unused simdjson_inline error_code tape_builder::visit_root_number(json_iterator &iter, const uint8_t *value) noexcept {
|
simdjson_warn_unused simdjson_inline error_code tape_builder::visit_root_number(json_iterator &iter, const uint8_t *value) noexcept {
|
||||||
|
|||||||
+1690
-549
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@@ -172,7 +172,23 @@ simdjson_warn_unused simdjson_inline error_code tape_builder::visit_root_string(
|
|||||||
|
|
||||||
simdjson_warn_unused simdjson_inline error_code tape_builder::visit_number(json_iterator &iter, const uint8_t *value) noexcept {
|
simdjson_warn_unused simdjson_inline error_code tape_builder::visit_number(json_iterator &iter, const uint8_t *value) noexcept {
|
||||||
iter.log_value("number");
|
iter.log_value("number");
|
||||||
return numberparsing::parse_number(value, tape);
|
error_code err = numberparsing::parse_number(value, tape);
|
||||||
|
if (simdjson_unlikely(err == BIGINT_ERROR &&
|
||||||
|
iter.dom_parser._number_as_string)) {
|
||||||
|
// Write big integer to string buffer using the same format as strings.
|
||||||
|
// Scan digits the same way parse_number does (skip optional '-', then digits).
|
||||||
|
const uint8_t *p = value;
|
||||||
|
if (*p == '-') p++;
|
||||||
|
while (numberparsing::is_digit(*p)) p++;
|
||||||
|
size_t len = size_t(p - value);
|
||||||
|
tape.append(current_string_buf_loc - iter.dom_parser.doc->string_buf.get(), internal::tape_type::BIGINT);
|
||||||
|
uint8_t *dst = current_string_buf_loc + sizeof(uint32_t);
|
||||||
|
memcpy(dst, value, len);
|
||||||
|
dst += len;
|
||||||
|
on_end_string(dst);
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
simdjson_warn_unused simdjson_inline error_code tape_builder::visit_root_number(json_iterator &iter, const uint8_t *value) noexcept {
|
simdjson_warn_unused simdjson_inline error_code tape_builder::visit_root_number(json_iterator &iter, const uint8_t *value) noexcept {
|
||||||
|
|||||||
@@ -26,6 +26,9 @@ struct tape_writer {
|
|||||||
/** Write a double value to tape. */
|
/** Write a double value to tape. */
|
||||||
simdjson_inline void append_double(double value) noexcept;
|
simdjson_inline void append_double(double value) noexcept;
|
||||||
|
|
||||||
|
/** Write a big integer (as string) to tape. src points to first digit, len is byte count. */
|
||||||
|
simdjson_inline void append_bigint(const uint8_t *src, size_t len, uint8_t *&string_buf) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Append a tape entry (an 8-bit type,and 56 bits worth of value).
|
* Append a tape entry (an 8-bit type,and 56 bits worth of value).
|
||||||
*/
|
*/
|
||||||
@@ -109,6 +112,18 @@ simdjson_inline void tape_writer::write(uint64_t &tape_loc, uint64_t val, intern
|
|||||||
tape_loc = val | ((uint64_t(char(t))) << 56);
|
tape_loc = val | ((uint64_t(char(t))) << 56);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
simdjson_inline void tape_writer::append_bigint(const uint8_t *src, size_t len, uint8_t *&string_buf) noexcept {
|
||||||
|
// Write to string buffer: [4-byte LE length][digits][null]
|
||||||
|
uint32_t str_len = uint32_t(len);
|
||||||
|
memcpy(string_buf, &str_len, sizeof(uint32_t));
|
||||||
|
memcpy(string_buf + sizeof(uint32_t), src, len);
|
||||||
|
string_buf[sizeof(uint32_t) + len] = 0;
|
||||||
|
// Tape entry: offset into string buffer
|
||||||
|
// The caller must set the offset relative to doc.string_buf base
|
||||||
|
append(0, internal::tape_type::BIGINT); // placeholder offset, caller patches
|
||||||
|
string_buf += sizeof(uint32_t) + len + 1;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace stage2
|
} // namespace stage2
|
||||||
} // unnamed namespace
|
} // unnamed namespace
|
||||||
} // namespace SIMDJSON_IMPLEMENTATION
|
} // namespace SIMDJSON_IMPLEMENTATION
|
||||||
|
|||||||
@@ -6,40 +6,40 @@
|
|||||||
|
|
||||||
using namespace simdjson;
|
using namespace simdjson;
|
||||||
struct Car {
|
struct Car {
|
||||||
std::string make;
|
std::string make{};
|
||||||
std::string model;
|
std::string model{};
|
||||||
int64_t year;
|
int64_t year{};
|
||||||
std::vector<double> tire_pressure;
|
std::vector<double> tire_pressure{};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct kid {
|
struct kid {
|
||||||
int age;
|
int age{};
|
||||||
std::string name;
|
std::string name{};
|
||||||
std::vector<std::string> toys;
|
std::vector<std::string> toys{};
|
||||||
bool operator<=> (const kid&) const = default;
|
bool operator<=> (const kid&) const = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Z {
|
struct Z {
|
||||||
int x;
|
int x{};
|
||||||
bool operator<=> (const Z&) const = default;
|
bool operator<=> (const Z&) const = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Y {
|
struct Y {
|
||||||
int g;
|
int g{};
|
||||||
std::string h;
|
std::string h{};
|
||||||
std::vector<int> i;
|
std::vector<int> i{};
|
||||||
Z z;
|
Z z{};
|
||||||
bool operator<=> (const Y&) const = default;
|
bool operator<=> (const Y&) const = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct X {
|
struct X {
|
||||||
char a;
|
char a{};
|
||||||
int b;
|
int b{};
|
||||||
int c;
|
int c{};
|
||||||
std::string d;
|
std::string d{};
|
||||||
std::vector<int> e;
|
std::vector<int> e{};
|
||||||
std::vector<std::string> f;
|
std::vector<std::string> f{};
|
||||||
Y y;
|
Y y{};
|
||||||
bool operator<=> (const X&) const = default;
|
bool operator<=> (const X&) const = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ namespace builder_tests {
|
|||||||
#if SIMDJSON_STATIC_REFLECTION
|
#if SIMDJSON_STATIC_REFLECTION
|
||||||
// Custom type for testing tag_invoke with extract_into
|
// Custom type for testing tag_invoke with extract_into
|
||||||
struct Price {
|
struct Price {
|
||||||
double amount;
|
double amount{};
|
||||||
std::string currency;
|
std::string currency{};
|
||||||
|
|
||||||
// Custom deserializer that applies currency conversion
|
// Custom deserializer that applies currency conversion
|
||||||
friend error_code tag_invoke(deserialize_tag,
|
friend error_code tag_invoke(deserialize_tag,
|
||||||
@@ -46,17 +46,37 @@ namespace builder_tests {
|
|||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
struct Car {
|
||||||
|
std::string make{};
|
||||||
|
std::string model{};
|
||||||
|
int year{};
|
||||||
|
double price{};
|
||||||
|
bool electric{};
|
||||||
|
};
|
||||||
|
struct CarOpt {
|
||||||
|
std::string make;
|
||||||
|
std::string model;
|
||||||
|
int year;
|
||||||
|
double price;
|
||||||
|
std::optional<std::string> color;
|
||||||
|
};
|
||||||
|
struct CarColor {
|
||||||
|
std::string make;
|
||||||
|
std::string model;
|
||||||
|
int year;
|
||||||
|
double price;
|
||||||
|
std::string color;
|
||||||
|
};
|
||||||
struct Product {
|
struct Product {
|
||||||
std::string name;
|
std::string name{};
|
||||||
Price price; // Custom deserializable type
|
Price price{}; // Custom deserializable type
|
||||||
int stock;
|
int stock{};
|
||||||
};
|
};
|
||||||
|
|
||||||
// Another custom type for testing
|
// Another custom type for testing
|
||||||
struct Dimensions {
|
struct Dimensions {
|
||||||
double value;
|
double value{};
|
||||||
std::string unit;
|
std::string unit{};
|
||||||
|
|
||||||
// Custom deserializer that converts to metric
|
// Custom deserializer that converts to metric
|
||||||
friend error_code tag_invoke(deserialize_tag,
|
friend error_code tag_invoke(deserialize_tag,
|
||||||
@@ -89,6 +109,13 @@ namespace builder_tests {
|
|||||||
Dimensions weight;
|
Dimensions weight;
|
||||||
Dimensions length;
|
Dimensions length;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Person {
|
||||||
|
std::string name;
|
||||||
|
int age;
|
||||||
|
std::optional<std::string> email;
|
||||||
|
std::optional<std::string> phone;
|
||||||
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool test_primitive_types() {
|
bool test_primitive_types() {
|
||||||
@@ -132,8 +159,8 @@ namespace builder_tests {
|
|||||||
TEST_START();
|
TEST_START();
|
||||||
#if SIMDJSON_STATIC_REFLECTION
|
#if SIMDJSON_STATIC_REFLECTION
|
||||||
struct StringTypes {
|
struct StringTypes {
|
||||||
std::string string_val;
|
std::string string_val{};
|
||||||
std::string_view string_view_val;
|
std::string_view string_view_val{};
|
||||||
};
|
};
|
||||||
|
|
||||||
StringTypes test{"hello world", "test_view"};
|
StringTypes test{"hello world", "test_view"};
|
||||||
@@ -159,10 +186,10 @@ namespace builder_tests {
|
|||||||
TEST_START();
|
TEST_START();
|
||||||
#if SIMDJSON_STATIC_REFLECTION
|
#if SIMDJSON_STATIC_REFLECTION
|
||||||
struct OptionalTypes {
|
struct OptionalTypes {
|
||||||
std::optional<int> opt_int_with_value;
|
std::optional<int> opt_int_with_value{};
|
||||||
std::optional<std::string> opt_string_with_value;
|
std::optional<std::string> opt_string_with_value{};
|
||||||
std::optional<int> opt_int_null;
|
std::optional<int> opt_int_null{};
|
||||||
std::optional<std::string> opt_string_null;
|
std::optional<std::string> opt_string_null{};
|
||||||
};
|
};
|
||||||
|
|
||||||
OptionalTypes test;
|
OptionalTypes test;
|
||||||
@@ -200,11 +227,11 @@ namespace builder_tests {
|
|||||||
TEST_START();
|
TEST_START();
|
||||||
#if SIMDJSON_STATIC_REFLECTION
|
#if SIMDJSON_STATIC_REFLECTION
|
||||||
struct SmartPointerTypes {
|
struct SmartPointerTypes {
|
||||||
std::unique_ptr<int> unique_int_with_value;
|
std::unique_ptr<int> unique_int_with_value{};
|
||||||
std::shared_ptr<std::string> shared_string_with_value;
|
std::shared_ptr<std::string> shared_string_with_value{};
|
||||||
std::unique_ptr<bool> unique_bool_with_value;
|
std::unique_ptr<bool> unique_bool_with_value{};
|
||||||
std::unique_ptr<int> unique_int_null;
|
std::unique_ptr<int> unique_int_null{};
|
||||||
std::shared_ptr<std::string> shared_string_null;
|
std::shared_ptr<std::string> shared_string_null{};
|
||||||
};
|
};
|
||||||
|
|
||||||
SmartPointerTypes test;
|
SmartPointerTypes test;
|
||||||
@@ -245,9 +272,9 @@ namespace builder_tests {
|
|||||||
#if SIMDJSON_STATIC_REFLECTION
|
#if SIMDJSON_STATIC_REFLECTION
|
||||||
// Test basic container types
|
// Test basic container types
|
||||||
struct ContainerTypes {
|
struct ContainerTypes {
|
||||||
std::vector<int> int_vector;
|
std::vector<int> int_vector{};
|
||||||
std::set<std::string> string_set;
|
std::set<std::string> string_set{};
|
||||||
std::map<std::string, int> string_map;
|
std::map<std::string, int> string_map{};
|
||||||
};
|
};
|
||||||
|
|
||||||
ContainerTypes test;
|
ContainerTypes test;
|
||||||
@@ -278,8 +305,8 @@ namespace builder_tests {
|
|||||||
|
|
||||||
// Test std::list with iterator-based serialization
|
// Test std::list with iterator-based serialization
|
||||||
struct ListContainer {
|
struct ListContainer {
|
||||||
std::list<int> int_list;
|
std::list<int> int_list{};
|
||||||
std::list<std::string> string_list;
|
std::list<std::string> string_list{};
|
||||||
};
|
};
|
||||||
|
|
||||||
ListContainer list_test;
|
ListContainer list_test;
|
||||||
@@ -319,13 +346,7 @@ namespace builder_tests {
|
|||||||
bool test_extract_into() {
|
bool test_extract_into() {
|
||||||
TEST_START();
|
TEST_START();
|
||||||
#if SIMDJSON_STATIC_REFLECTION
|
#if SIMDJSON_STATIC_REFLECTION
|
||||||
struct Car {
|
|
||||||
std::string make;
|
|
||||||
std::string model;
|
|
||||||
int year;
|
|
||||||
double price;
|
|
||||||
std::optional<std::string> color;
|
|
||||||
};
|
|
||||||
|
|
||||||
ondemand::parser parser;
|
ondemand::parser parser;
|
||||||
|
|
||||||
@@ -341,7 +362,7 @@ namespace builder_tests {
|
|||||||
"transmission": "Automatic"
|
"transmission": "Automatic"
|
||||||
})"_padded;
|
})"_padded;
|
||||||
|
|
||||||
Car car{};
|
CarOpt car{};
|
||||||
ondemand::document doc;
|
ondemand::document doc;
|
||||||
ASSERT_SUCCESS( parser.iterate(padded).get(doc) );
|
ASSERT_SUCCESS( parser.iterate(padded).get(doc) );
|
||||||
|
|
||||||
@@ -377,7 +398,7 @@ namespace builder_tests {
|
|||||||
"color": "Red"
|
"color": "Red"
|
||||||
})"_padded;
|
})"_padded;
|
||||||
|
|
||||||
Car car{};
|
CarOpt car{};
|
||||||
ondemand::document doc;
|
ondemand::document doc;
|
||||||
ASSERT_SUCCESS(parser.iterate(padded).get(doc));
|
ASSERT_SUCCESS(parser.iterate(padded).get(doc));
|
||||||
|
|
||||||
@@ -402,7 +423,7 @@ namespace builder_tests {
|
|||||||
"price": 35999.99
|
"price": 35999.99
|
||||||
})"_padded;
|
})"_padded;
|
||||||
|
|
||||||
Car car{};
|
CarOpt car{};
|
||||||
ondemand::document doc;
|
ondemand::document doc;
|
||||||
ASSERT_SUCCESS(parser.iterate(padded).get(doc));
|
ASSERT_SUCCESS(parser.iterate(padded).get(doc));
|
||||||
|
|
||||||
@@ -495,13 +516,6 @@ namespace builder_tests {
|
|||||||
#if SIMDJSON_STATIC_REFLECTION
|
#if SIMDJSON_STATIC_REFLECTION
|
||||||
// Test 1: Extract specific fields from Car struct
|
// Test 1: Extract specific fields from Car struct
|
||||||
{
|
{
|
||||||
struct Car {
|
|
||||||
std::string make;
|
|
||||||
std::string model;
|
|
||||||
int year;
|
|
||||||
double price;
|
|
||||||
bool electric;
|
|
||||||
};
|
|
||||||
|
|
||||||
Car car{"Tesla", "Model 3", 2023, 42000.0, true};
|
Car car{"Tesla", "Model 3", 2023, 42000.0, true};
|
||||||
|
|
||||||
@@ -533,13 +547,7 @@ namespace builder_tests {
|
|||||||
|
|
||||||
// Test 2: Extract different field combination
|
// Test 2: Extract different field combination
|
||||||
{
|
{
|
||||||
struct Car {
|
|
||||||
std::string make;
|
|
||||||
std::string model;
|
|
||||||
int year;
|
|
||||||
double price;
|
|
||||||
bool electric;
|
|
||||||
};
|
|
||||||
|
|
||||||
Car car{"Ford", "F-150", 2024, 55000.0, false};
|
Car car{"Ford", "F-150", 2024, 55000.0, false};
|
||||||
|
|
||||||
@@ -566,13 +574,6 @@ namespace builder_tests {
|
|||||||
|
|
||||||
// Test 3: Extract from struct with optional fields
|
// Test 3: Extract from struct with optional fields
|
||||||
{
|
{
|
||||||
struct Person {
|
|
||||||
std::string name;
|
|
||||||
int age;
|
|
||||||
std::optional<std::string> email;
|
|
||||||
std::optional<std::string> phone;
|
|
||||||
};
|
|
||||||
|
|
||||||
Person person{"John Doe", 30, "john@example.com", std::nullopt};
|
Person person{"John Doe", 30, "john@example.com", std::nullopt};
|
||||||
|
|
||||||
// Extract name and email
|
// Extract name and email
|
||||||
@@ -594,13 +595,6 @@ namespace builder_tests {
|
|||||||
|
|
||||||
// Test 4: Extract with optional that has value
|
// Test 4: Extract with optional that has value
|
||||||
{
|
{
|
||||||
struct Person {
|
|
||||||
std::string name;
|
|
||||||
int age;
|
|
||||||
std::optional<std::string> email;
|
|
||||||
std::optional<std::string> phone;
|
|
||||||
};
|
|
||||||
|
|
||||||
Person person{"Jane Smith", 25, "jane@example.com", "555-1234"};
|
Person person{"Jane Smith", 25, "jane@example.com", "555-1234"};
|
||||||
|
|
||||||
// Extract name, age, and phone
|
// Extract name, age, and phone
|
||||||
@@ -629,21 +623,21 @@ namespace builder_tests {
|
|||||||
|
|
||||||
// Test 5: Round-trip test - serialize with extract_from, deserialize with extract_into
|
// Test 5: Round-trip test - serialize with extract_from, deserialize with extract_into
|
||||||
{
|
{
|
||||||
struct Product {
|
struct MyProduct {
|
||||||
std::string id;
|
std::string id{};
|
||||||
std::string name;
|
std::string name{};
|
||||||
double price;
|
double price{};
|
||||||
int stock;
|
int stock{};
|
||||||
};
|
};
|
||||||
|
|
||||||
Product original{"P123", "Widget", 19.99, 100};
|
MyProduct original{"P123", "Widget", 19.99, 100};
|
||||||
|
|
||||||
// Extract specific fields to JSON
|
// Extract specific fields to JSON
|
||||||
std::string json;
|
std::string json;
|
||||||
ASSERT_SUCCESS((extract_from<"id", "name", "price">(original).get(json)));
|
ASSERT_SUCCESS((extract_from<"id", "name", "price">(original).get(json)));
|
||||||
|
|
||||||
// Parse and extract back
|
// Parse and extract back
|
||||||
Product restored{"", "", 0.0, 0};
|
MyProduct restored{"", "", 0.0, 0};
|
||||||
auto padded = pad(json);
|
auto padded = pad(json);
|
||||||
ondemand::parser parser;
|
ondemand::parser parser;
|
||||||
auto doc = parser.iterate(padded);
|
auto doc = parser.iterate(padded);
|
||||||
|
|||||||
@@ -11,10 +11,10 @@ using namespace simdjson;
|
|||||||
// Suppose that we want to serialize/deserialize Car using
|
// Suppose that we want to serialize/deserialize Car using
|
||||||
// strings for the year
|
// strings for the year
|
||||||
struct Car {
|
struct Car {
|
||||||
std::string make;
|
std::string make{};
|
||||||
std::string model;
|
std::string model{};
|
||||||
int64_t year;
|
int64_t year{};
|
||||||
std::vector<float> tire_pressure;
|
std::vector<float> tire_pressure{};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -14,11 +14,11 @@ namespace builder_tests {
|
|||||||
TEST_START();
|
TEST_START();
|
||||||
#if SIMDJSON_STATIC_REFLECTION
|
#if SIMDJSON_STATIC_REFLECTION
|
||||||
struct EmptyValues {
|
struct EmptyValues {
|
||||||
std::string empty_string;
|
std::string empty_string{};
|
||||||
std::vector<int> empty_vector;
|
std::vector<int> empty_vector{};
|
||||||
std::optional<int> null_optional;
|
std::optional<int> null_optional{};
|
||||||
std::unique_ptr<int> null_unique_ptr;
|
std::unique_ptr<int> null_unique_ptr{};
|
||||||
std::shared_ptr<std::string> null_shared_ptr;
|
std::shared_ptr<std::string> null_shared_ptr{};
|
||||||
};
|
};
|
||||||
|
|
||||||
EmptyValues test;
|
EmptyValues test;
|
||||||
@@ -56,18 +56,18 @@ namespace builder_tests {
|
|||||||
TEST_START();
|
TEST_START();
|
||||||
#if SIMDJSON_STATIC_REFLECTION
|
#if SIMDJSON_STATIC_REFLECTION
|
||||||
struct SpecialChars {
|
struct SpecialChars {
|
||||||
std::string quotes;
|
std::string quotes{};
|
||||||
std::string backslashes;
|
std::string backslashes{};
|
||||||
std::string newlines;
|
std::string newlines{};
|
||||||
std::string unicode;
|
std::string unicode{};
|
||||||
char null_char;
|
char null_char{};
|
||||||
};
|
};
|
||||||
|
|
||||||
SpecialChars test;
|
SpecialChars test;
|
||||||
test.quotes = "He said \"Hello\"";
|
test.quotes = "He said \"Hello\"";
|
||||||
test.backslashes = "Path\\to\\file";
|
test.backslashes = "Path\\to\\file";
|
||||||
test.newlines = "Line1\nLine2\tTabbed";
|
test.newlines = "Line1\nLine2\tTabbed";
|
||||||
test.unicode = "Café résumé";
|
test.unicode = "Caf\xc3\xa9 r\xc3\xa9sum\xc3\xa9";
|
||||||
test.null_char = '\0';
|
test.null_char = '\0';
|
||||||
|
|
||||||
std::string json;
|
std::string json;
|
||||||
@@ -82,10 +82,10 @@ namespace builder_tests {
|
|||||||
|
|
||||||
// Test round-trip (excluding null char which has special handling)
|
// Test round-trip (excluding null char which has special handling)
|
||||||
struct SpecialCharsNoNull {
|
struct SpecialCharsNoNull {
|
||||||
std::string quotes;
|
std::string quotes{};
|
||||||
std::string backslashes;
|
std::string backslashes{};
|
||||||
std::string newlines;
|
std::string newlines{};
|
||||||
std::string unicode;
|
std::string unicode{};
|
||||||
};
|
};
|
||||||
|
|
||||||
SpecialCharsNoNull test_no_null;
|
SpecialCharsNoNull test_no_null;
|
||||||
@@ -157,15 +157,15 @@ namespace builder_tests {
|
|||||||
TEST_START();
|
TEST_START();
|
||||||
#if SIMDJSON_STATIC_REFLECTION
|
#if SIMDJSON_STATIC_REFLECTION
|
||||||
struct Inner {
|
struct Inner {
|
||||||
int value;
|
int value{};
|
||||||
std::string name;
|
std::string name{};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Outer {
|
struct Outer {
|
||||||
Inner inner_obj;
|
Inner inner_obj{};
|
||||||
std::vector<Inner> inner_vector;
|
std::vector<Inner> inner_vector{};
|
||||||
std::optional<Inner> optional_inner;
|
std::optional<Inner> optional_inner{};
|
||||||
std::unique_ptr<Inner> unique_inner;
|
std::unique_ptr<Inner> unique_inner{};
|
||||||
};
|
};
|
||||||
|
|
||||||
Outer test;
|
Outer test;
|
||||||
@@ -213,4 +213,4 @@ namespace builder_tests {
|
|||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
return test_main(argc, argv, builder_tests::run);
|
return test_main(argc, argv, builder_tests::run);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,8 +51,8 @@ namespace builder_tests {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct StatusStruct {
|
struct StatusStruct {
|
||||||
Status status;
|
Status status{};
|
||||||
std::string name;
|
std::string name{};
|
||||||
};
|
};
|
||||||
|
|
||||||
// Test deserialization of different enum values with string representation
|
// Test deserialization of different enum values with string representation
|
||||||
@@ -104,9 +104,9 @@ namespace builder_tests {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct Task {
|
struct Task {
|
||||||
Priority priority;
|
Priority priority{};
|
||||||
std::string description;
|
std::string description{};
|
||||||
int id;
|
int id{};
|
||||||
};
|
};
|
||||||
|
|
||||||
Task original{Priority::High, "Important task", 123};
|
Task original{Priority::High, "Important task", 123};
|
||||||
@@ -144,8 +144,8 @@ namespace builder_tests {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct Response {
|
struct Response {
|
||||||
ErrorCode error;
|
ErrorCode error{};
|
||||||
std::string message;
|
std::string message{};
|
||||||
};
|
};
|
||||||
|
|
||||||
Response test{ErrorCode::NotFound, "Resource not found"};
|
Response test{ErrorCode::NotFound, "Resource not found"};
|
||||||
|
|||||||
@@ -8,26 +8,26 @@ using namespace simdjson;
|
|||||||
|
|
||||||
// Test structures for FracturedJson builder integration
|
// Test structures for FracturedJson builder integration
|
||||||
struct SimpleUser {
|
struct SimpleUser {
|
||||||
int id;
|
int id{};
|
||||||
std::string name;
|
std::string name{};
|
||||||
bool active;
|
bool active{};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct UserWithEmail {
|
struct UserWithEmail {
|
||||||
int id;
|
int id{};
|
||||||
std::string name;
|
std::string name{};
|
||||||
std::string email;
|
std::string email{};
|
||||||
bool active;
|
bool active{};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NestedData {
|
struct NestedData {
|
||||||
std::string title;
|
std::string title{};
|
||||||
std::vector<SimpleUser> users;
|
std::vector<SimpleUser> users{};
|
||||||
int count;
|
int count{};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TableTestData {
|
struct TableTestData {
|
||||||
std::vector<SimpleUser> records;
|
std::vector<SimpleUser> records{};
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace fractured_json_builder_tests {
|
namespace fractured_json_builder_tests {
|
||||||
|
|||||||
@@ -666,27 +666,27 @@ bool test_array_of_objects_with_concept() {
|
|||||||
/**
|
/**
|
||||||
* Test: #embed support for external JSON files (C++26)
|
* Test: #embed support for external JSON files (C++26)
|
||||||
*/
|
*/
|
||||||
bool test_embed_twitter_json() {
|
bool test_embed_example_config_json() {
|
||||||
TEST_START();
|
TEST_START();
|
||||||
|
|
||||||
// C++26 #embed allows embedding files directly into the binary at compile time
|
// C++26 #embed allows embedding files directly into the binary at compile time
|
||||||
// This creates a const char array with the file contents plus null terminator
|
// This creates a const char array with the file contents plus null terminator
|
||||||
constexpr const char twitter_json[] = {
|
constexpr const unsigned char example_config_json[] = {
|
||||||
#embed TWITTER_JSON
|
#embed "../../jsonexamples/example_config.json"
|
||||||
, 0
|
, 0
|
||||||
};
|
};
|
||||||
|
|
||||||
// Parse the embedded JSON at compile time
|
// Parse the embedded JSON at compile time
|
||||||
constexpr auto parsed_twitter = simdjson::compile_time::parse_json<twitter_json>();
|
constexpr auto parsed_example_config = simdjson::compile_time::parse_json<example_config_json>();
|
||||||
|
|
||||||
// Verify the structure - twitter.json should have a "statuses" array
|
// Verify the structure - example_config.json should have an "app_name" field
|
||||||
static_assert(parsed_twitter.statuses.size() > 0);
|
static_assert(std::string_view(parsed_example_config.app_name) == "MyApp");
|
||||||
|
|
||||||
// Runtime verification
|
// Runtime verification
|
||||||
ASSERT_TRUE(parsed_twitter.statuses.size() > 0);
|
ASSERT_TRUE(std::string_view(parsed_example_config.app_name) == "MyApp");
|
||||||
|
|
||||||
std::cout << "Successfully parsed embedded twitter.json with "
|
std::cout << "Successfully parsed embedded example_config.json with "
|
||||||
<< parsed_twitter.statuses.size() << " statuses" << std::endl;
|
<< parsed_example_config.app_name << " as app_name" << std::endl;
|
||||||
|
|
||||||
TEST_SUCCEED();
|
TEST_SUCCEED();
|
||||||
}
|
}
|
||||||
@@ -718,11 +718,10 @@ bool run() {
|
|||||||
test_top_level_array_example() &&
|
test_top_level_array_example() &&
|
||||||
test_array_of_objects_with_concept()
|
test_array_of_objects_with_concept()
|
||||||
#ifdef TEST_EMBED_SUPPORTED
|
#ifdef TEST_EMBED_SUPPORTED
|
||||||
&& test_embed_twitter_json()
|
&& test_embed_example_config_json()
|
||||||
#endif
|
#endif
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace compile_time_json_tests
|
} // namespace compile_time_json_tests
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ add_cpp_test(document_tests LABELS dom acceptance per_implementation
|
|||||||
add_cpp_test(errortests LABELS dom acceptance per_implementation)
|
add_cpp_test(errortests LABELS dom acceptance per_implementation)
|
||||||
add_cpp_test(extracting_values_example LABELS dom acceptance per_implementation)
|
add_cpp_test(extracting_values_example LABELS dom acceptance per_implementation)
|
||||||
add_cpp_test(integer_tests LABELS dom acceptance per_implementation)
|
add_cpp_test(integer_tests LABELS dom acceptance per_implementation)
|
||||||
|
add_cpp_test(big_integer_tests LABELS dom acceptance per_implementation)
|
||||||
add_cpp_test(jsoncheck LABELS dom acceptance per_implementation)
|
add_cpp_test(jsoncheck LABELS dom acceptance per_implementation)
|
||||||
add_cpp_test(json_path_tests LABELS dom acceptance per_implementation)
|
add_cpp_test(json_path_tests LABELS dom acceptance per_implementation)
|
||||||
add_cpp_test(minefieldcheck LABELS dom acceptance per_implementation)
|
add_cpp_test(minefieldcheck LABELS dom acceptance per_implementation)
|
||||||
|
|||||||
@@ -0,0 +1,151 @@
|
|||||||
|
#include "simdjson.h"
|
||||||
|
#include "test_macros.h"
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
using namespace simdjson;
|
||||||
|
|
||||||
|
namespace big_integer_tests {
|
||||||
|
|
||||||
|
bool option_off_by_default() {
|
||||||
|
TEST_START();
|
||||||
|
dom::parser parser;
|
||||||
|
ASSERT_EQUAL(parser.number_as_string(), false);
|
||||||
|
TEST_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool default_returns_bigint_error() {
|
||||||
|
TEST_START();
|
||||||
|
dom::parser parser;
|
||||||
|
auto result = parser.parse(R"({"val":123456789012345678901})"_padded);
|
||||||
|
ASSERT_EQUAL(result.error(), BIGINT_ERROR);
|
||||||
|
TEST_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool opt_in_parses_big_integer() {
|
||||||
|
TEST_START();
|
||||||
|
dom::parser parser;
|
||||||
|
parser.number_as_string(true);
|
||||||
|
dom::element doc;
|
||||||
|
ASSERT_SUCCESS(parser.parse(R"({"val":123456789012345678901})"_padded).get(doc));
|
||||||
|
dom::element val;
|
||||||
|
ASSERT_SUCCESS(doc["val"].get(val));
|
||||||
|
ASSERT_EQUAL(val.type(), dom::element_type::BIGINT);
|
||||||
|
ASSERT_TRUE(val.is_bigint());
|
||||||
|
std::string_view digits;
|
||||||
|
ASSERT_SUCCESS(val.get_bigint().get(digits));
|
||||||
|
ASSERT_EQUAL(digits, "123456789012345678901");
|
||||||
|
// Verify streaming works (same pattern as readme_examples)
|
||||||
|
std::ostringstream os;
|
||||||
|
os << val.get_bigint().value_unsafe();
|
||||||
|
ASSERT_EQUAL(os.str(), "123456789012345678901");
|
||||||
|
TEST_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool negative_big_integer() {
|
||||||
|
TEST_START();
|
||||||
|
dom::parser parser;
|
||||||
|
parser.number_as_string(true);
|
||||||
|
dom::element doc;
|
||||||
|
ASSERT_SUCCESS(parser.parse(R"({"val":-12345678901234567890})"_padded).get(doc));
|
||||||
|
dom::element val;
|
||||||
|
ASSERT_SUCCESS(doc["val"].get(val));
|
||||||
|
ASSERT_EQUAL(val.type(), dom::element_type::BIGINT);
|
||||||
|
std::string_view digits;
|
||||||
|
ASSERT_SUCCESS(val.get_bigint().get(digits));
|
||||||
|
ASSERT_EQUAL(digits, "-12345678901234567890");
|
||||||
|
TEST_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool big_integer_in_array() {
|
||||||
|
TEST_START();
|
||||||
|
dom::parser parser;
|
||||||
|
parser.number_as_string(true);
|
||||||
|
dom::element doc;
|
||||||
|
ASSERT_SUCCESS(parser.parse(R"([1, 123456789012345678901, 3])"_padded).get(doc));
|
||||||
|
dom::array arr;
|
||||||
|
ASSERT_SUCCESS(doc.get_array().get(arr));
|
||||||
|
size_t count = 0;
|
||||||
|
for (auto elem : arr) { (void)elem; count++; }
|
||||||
|
ASSERT_EQUAL(count, 3);
|
||||||
|
TEST_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool serialization_preserves_digits() {
|
||||||
|
TEST_START();
|
||||||
|
dom::parser parser;
|
||||||
|
parser.number_as_string(true);
|
||||||
|
dom::element doc;
|
||||||
|
ASSERT_SUCCESS(parser.parse(R"({"val":123456789012345678901})"_padded).get(doc));
|
||||||
|
std::string output = simdjson::to_string(doc);
|
||||||
|
// Raw digits should appear
|
||||||
|
ASSERT_TRUE(output.find("123456789012345678901") != std::string::npos);
|
||||||
|
// Must not be quoted - it's a number, not a string
|
||||||
|
ASSERT_EQUAL(output.find("\"123456789012345678901\""), std::string::npos);
|
||||||
|
TEST_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool normal_numbers_unaffected() {
|
||||||
|
TEST_START();
|
||||||
|
dom::parser parser;
|
||||||
|
parser.number_as_string(true);
|
||||||
|
dom::element doc;
|
||||||
|
ASSERT_SUCCESS(parser.parse(R"({"a":42,"b":-1,"c":3.14,"d":18446744073709551615})"_padded).get(doc));
|
||||||
|
int64_t a;
|
||||||
|
ASSERT_SUCCESS(doc["a"].get_int64().get(a));
|
||||||
|
ASSERT_EQUAL(a, 42);
|
||||||
|
uint64_t d;
|
||||||
|
ASSERT_SUCCESS(doc["d"].get_uint64().get(d));
|
||||||
|
ASSERT_EQUAL(d, 18446744073709551615ULL);
|
||||||
|
TEST_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool type_checks() {
|
||||||
|
TEST_START();
|
||||||
|
dom::parser parser;
|
||||||
|
parser.number_as_string(true);
|
||||||
|
dom::element doc;
|
||||||
|
ASSERT_SUCCESS(parser.parse(R"({"val":123456789012345678901})"_padded).get(doc));
|
||||||
|
dom::element val;
|
||||||
|
ASSERT_SUCCESS(doc["val"].get(val));
|
||||||
|
// is_bigint should be true
|
||||||
|
ASSERT_TRUE(val.is_bigint());
|
||||||
|
// other type checks should be false
|
||||||
|
ASSERT_FALSE(val.is_int64());
|
||||||
|
ASSERT_FALSE(val.is_uint64());
|
||||||
|
ASSERT_FALSE(val.is_double());
|
||||||
|
ASSERT_FALSE(val.is_string());
|
||||||
|
ASSERT_FALSE(val.is_bool());
|
||||||
|
ASSERT_FALSE(val.is_null());
|
||||||
|
// get_int64/uint64/double should return INCORRECT_TYPE
|
||||||
|
ASSERT_ERROR(val.get_int64(), INCORRECT_TYPE);
|
||||||
|
ASSERT_ERROR(val.get_uint64(), INCORRECT_TYPE);
|
||||||
|
ASSERT_ERROR(val.get_double(), INCORRECT_TYPE);
|
||||||
|
ASSERT_ERROR(val.get_string(), INCORRECT_TYPE);
|
||||||
|
TEST_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool element_type_output() {
|
||||||
|
TEST_START();
|
||||||
|
std::ostringstream os;
|
||||||
|
os << dom::element_type::BIGINT;
|
||||||
|
ASSERT_EQUAL(os.str(), "bigint");
|
||||||
|
TEST_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool run() {
|
||||||
|
return option_off_by_default() &&
|
||||||
|
default_returns_bigint_error() &&
|
||||||
|
opt_in_parses_big_integer() &&
|
||||||
|
negative_big_integer() &&
|
||||||
|
big_integer_in_array() &&
|
||||||
|
serialization_preserves_digits() &&
|
||||||
|
normal_numbers_unaffected() &&
|
||||||
|
type_checks() &&
|
||||||
|
element_type_output();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace big_integer_tests
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
return big_integer_tests::run() ? 0 : 1;
|
||||||
|
}
|
||||||
@@ -114,6 +114,20 @@ namespace parser_load {
|
|||||||
TEST_SUCCEED();
|
TEST_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool parser_load_string_view_subpath() {
|
||||||
|
TEST_START();
|
||||||
|
const std::string valid_path(TWITTER_JSON);
|
||||||
|
const std::string backing = valid_path + ".extra";
|
||||||
|
const std::string_view view(backing.data(), valid_path.size());
|
||||||
|
uint64_t count_from_string = 0;
|
||||||
|
uint64_t count_from_view = 0;
|
||||||
|
dom::parser parser;
|
||||||
|
ASSERT_SUCCESS(parser.load(valid_path)["search_metadata"]["count"].get(count_from_string));
|
||||||
|
ASSERT_SUCCESS(parser.load(view)["search_metadata"]["count"].get(count_from_view));
|
||||||
|
ASSERT_EQUAL(count_from_view, count_from_string);
|
||||||
|
TEST_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
bool parser_load_chain() {
|
bool parser_load_chain() {
|
||||||
TEST_START();
|
TEST_START();
|
||||||
dom::parser parser;
|
dom::parser parser;
|
||||||
@@ -136,6 +150,7 @@ namespace parser_load {
|
|||||||
&& parser_load_nonexistent()
|
&& parser_load_nonexistent()
|
||||||
&& parser_load_many_nonexistent()
|
&& parser_load_many_nonexistent()
|
||||||
&& padded_string_load_nonexistent()
|
&& padded_string_load_nonexistent()
|
||||||
|
&& parser_load_string_view_subpath()
|
||||||
&& parser_load_chain()
|
&& parser_load_chain()
|
||||||
&& parser_load_many_chain()
|
&& parser_load_many_chain()
|
||||||
&& parser_parse_many_documents_error_in_the_middle()
|
&& parser_parse_many_documents_error_in_the_middle()
|
||||||
|
|||||||
@@ -273,6 +273,9 @@ namespace treewalk_1 {
|
|||||||
case dom::element_type::NULL_VALUE:
|
case dom::element_type::NULL_VALUE:
|
||||||
cout << "null" << endl;
|
cout << "null" << endl;
|
||||||
break;
|
break;
|
||||||
|
case dom::element_type::BIGINT:
|
||||||
|
cout << element.get_bigint().value_unsafe() << endl;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -475,11 +475,11 @@ bool unicode_test() {
|
|||||||
std::cout << "Running " << __func__ << std::endl;
|
std::cout << "Running " << __func__ << std::endl;
|
||||||
|
|
||||||
const char* json = R"({
|
const char* json = R"({
|
||||||
"greeting": "Hello, 世界!",
|
"greeting": "Hello, \u4e16\u754c!",
|
||||||
"emoji": "🎉🚀✨",
|
"emoji": "\ud83c\udf89\ud83d\ude80\u2728",
|
||||||
"arabic": "مرحبا",
|
"arabic": "\u0645\u0631\u062d\u0628\u0627",
|
||||||
"russian": "Привет",
|
"russian": "\u041f\u0440\u0438\u0432\u0435\u0442",
|
||||||
"mixed": "café résumé naïve"
|
"mixed": "caf\u00e9 r\u00e9sum\u00e9 na\u00efve"
|
||||||
})";
|
})";
|
||||||
|
|
||||||
simdjson::dom::parser parser;
|
simdjson::dom::parser parser;
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ public:
|
|||||||
return date_str;
|
return date_str;
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
std::string date_str;
|
std::string date_str{};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -52,8 +52,8 @@ auto tag_invoke(deserialize_tag, simdjson_value &val, MyDate& date) {
|
|||||||
} // namespace simdjson
|
} // namespace simdjson
|
||||||
|
|
||||||
struct complicated_weather_data {
|
struct complicated_weather_data {
|
||||||
std::vector<MyDate> time;
|
std::vector<MyDate> time{};
|
||||||
std::vector<float> temperature;
|
std::vector<float> temperature{};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -152,19 +152,19 @@ simdjson::padded_string json_cars =
|
|||||||
TEST_SUCCEED();
|
TEST_SUCCEED();
|
||||||
}
|
}
|
||||||
struct Player {
|
struct Player {
|
||||||
std::string username;
|
std::string username{};
|
||||||
int level;
|
int level{};
|
||||||
double health;
|
double health{};
|
||||||
};
|
};
|
||||||
struct BadPlayer {
|
struct BadPlayer {
|
||||||
int username; // Oops, should be string!
|
int username{}; // Oops, should be string!
|
||||||
int level;
|
int level{};
|
||||||
double health;
|
double health{};
|
||||||
};
|
};
|
||||||
struct OptionalPlayer {
|
struct OptionalPlayer {
|
||||||
std::string username;
|
std::string username{};
|
||||||
std::optional<int> level;
|
std::optional<int> level{};
|
||||||
double health;
|
double health{};
|
||||||
};
|
};
|
||||||
#if SIMDJSON_STATIC_REFLECTION
|
#if SIMDJSON_STATIC_REFLECTION
|
||||||
bool missing_key_player() {
|
bool missing_key_player() {
|
||||||
|
|||||||
@@ -884,6 +884,30 @@ namespace document_stream_tests {
|
|||||||
TEST_SUCCEED();
|
TEST_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool uint32_with_trailing() {
|
||||||
|
TEST_START();
|
||||||
|
auto json = R"( 133 badstuff )"_padded;
|
||||||
|
ondemand::parser parser;
|
||||||
|
ondemand::document_stream doc;
|
||||||
|
ASSERT_SUCCESS(parser.iterate_many(json).get(doc));
|
||||||
|
uint32_t x;
|
||||||
|
ASSERT_SUCCESS((*doc.begin()).get_uint32().get(x));
|
||||||
|
ASSERT_EQUAL(x,133);
|
||||||
|
TEST_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool int32_with_trailing() {
|
||||||
|
TEST_START();
|
||||||
|
auto json = R"( 133 badstuff )"_padded;
|
||||||
|
ondemand::parser parser;
|
||||||
|
ondemand::document_stream doc;
|
||||||
|
ASSERT_SUCCESS(parser.iterate_many(json).get(doc));
|
||||||
|
int32_t x;
|
||||||
|
ASSERT_SUCCESS((*doc.begin()).get_int32().get(x));
|
||||||
|
ASSERT_EQUAL(x,133);
|
||||||
|
TEST_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
bool double_with_trailing() {
|
bool double_with_trailing() {
|
||||||
TEST_START();
|
TEST_START();
|
||||||
auto json = R"( 133 badstuff )"_padded;
|
auto json = R"( 133 badstuff )"_padded;
|
||||||
@@ -931,6 +955,8 @@ namespace document_stream_tests {
|
|||||||
string_with_trailing() &&
|
string_with_trailing() &&
|
||||||
uint64_with_trailing() &&
|
uint64_with_trailing() &&
|
||||||
int64_with_trailing() &&
|
int64_with_trailing() &&
|
||||||
|
uint32_with_trailing() &&
|
||||||
|
int32_with_trailing() &&
|
||||||
bool_with_trailing() &&
|
bool_with_trailing() &&
|
||||||
null_with_trailing() &&
|
null_with_trailing() &&
|
||||||
truncated_utf8() &&
|
truncated_utf8() &&
|
||||||
|
|||||||
@@ -171,6 +171,17 @@ namespace error_tests {
|
|||||||
TEST_SUCCEED();
|
TEST_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool parser_set_max_capacity() {
|
||||||
|
TEST_START();
|
||||||
|
ondemand::parser parser;
|
||||||
|
parser.set_max_capacity(1024 * 1024);
|
||||||
|
ASSERT_EQUAL(parser.max_capacity(), size_t(1024 * 1024));
|
||||||
|
auto json = R"({"k":"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"})"_padded;
|
||||||
|
ondemand::document doc;
|
||||||
|
ASSERT_SUCCESS(parser.iterate(json).get(doc));
|
||||||
|
TEST_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
bool simple_error_example() {
|
bool simple_error_example() {
|
||||||
TEST_START();
|
TEST_START();
|
||||||
ondemand::parser parser;
|
ondemand::parser parser;
|
||||||
@@ -212,7 +223,11 @@ namespace error_tests {
|
|||||||
ASSERT_ERROR( val.get_double(), INCORRECT_TYPE );
|
ASSERT_ERROR( val.get_double(), INCORRECT_TYPE );
|
||||||
ASSERT_ERROR( val.get_uint64(), INCORRECT_TYPE );
|
ASSERT_ERROR( val.get_uint64(), INCORRECT_TYPE );
|
||||||
ASSERT_ERROR( val.get_int64(), INCORRECT_TYPE );
|
ASSERT_ERROR( val.get_int64(), INCORRECT_TYPE );
|
||||||
|
ASSERT_ERROR( val.get_uint32(), INCORRECT_TYPE );
|
||||||
|
ASSERT_ERROR( val.get_int32(), INCORRECT_TYPE );
|
||||||
ASSERT_ERROR( val.get_object(), INCORRECT_TYPE );
|
ASSERT_ERROR( val.get_object(), INCORRECT_TYPE );
|
||||||
|
ASSERT_ERROR( val.get_int32(), INCORRECT_TYPE );
|
||||||
|
ASSERT_ERROR( val.get_uint32(), INCORRECT_TYPE );
|
||||||
ASSERT_ERROR( val.get_int64(), INCORRECT_TYPE );
|
ASSERT_ERROR( val.get_int64(), INCORRECT_TYPE );
|
||||||
ASSERT_ERROR( val.get_uint64(), INCORRECT_TYPE );
|
ASSERT_ERROR( val.get_uint64(), INCORRECT_TYPE );
|
||||||
ASSERT_ERROR( val.get_double(), INCORRECT_TYPE );
|
ASSERT_ERROR( val.get_double(), INCORRECT_TYPE );
|
||||||
@@ -235,7 +250,11 @@ namespace error_tests {
|
|||||||
ASSERT_ERROR( val.get_double(), INCORRECT_TYPE );
|
ASSERT_ERROR( val.get_double(), INCORRECT_TYPE );
|
||||||
ASSERT_ERROR( val.get_uint64(), INCORRECT_TYPE );
|
ASSERT_ERROR( val.get_uint64(), INCORRECT_TYPE );
|
||||||
ASSERT_ERROR( val.get_int64(), INCORRECT_TYPE );
|
ASSERT_ERROR( val.get_int64(), INCORRECT_TYPE );
|
||||||
|
ASSERT_ERROR( val.get_uint32(), INCORRECT_TYPE );
|
||||||
|
ASSERT_ERROR( val.get_int32(), INCORRECT_TYPE );
|
||||||
ASSERT_ERROR( val.get_object(), INCORRECT_TYPE );
|
ASSERT_ERROR( val.get_object(), INCORRECT_TYPE );
|
||||||
|
ASSERT_ERROR( val.get_int32(), INCORRECT_TYPE );
|
||||||
|
ASSERT_ERROR( val.get_uint32(), INCORRECT_TYPE );
|
||||||
ASSERT_ERROR( val.get_int64(), INCORRECT_TYPE );
|
ASSERT_ERROR( val.get_int64(), INCORRECT_TYPE );
|
||||||
ASSERT_ERROR( val.get_uint64(), INCORRECT_TYPE );
|
ASSERT_ERROR( val.get_uint64(), INCORRECT_TYPE );
|
||||||
ASSERT_ERROR( val.get_double(), INCORRECT_TYPE );
|
ASSERT_ERROR( val.get_double(), INCORRECT_TYPE );
|
||||||
@@ -257,7 +276,11 @@ namespace error_tests {
|
|||||||
ASSERT_ERROR( val.get_double(), INCORRECT_TYPE );
|
ASSERT_ERROR( val.get_double(), INCORRECT_TYPE );
|
||||||
ASSERT_ERROR( val.get_uint64(), INCORRECT_TYPE );
|
ASSERT_ERROR( val.get_uint64(), INCORRECT_TYPE );
|
||||||
ASSERT_ERROR( val.get_int64(), INCORRECT_TYPE );
|
ASSERT_ERROR( val.get_int64(), INCORRECT_TYPE );
|
||||||
|
ASSERT_ERROR( val.get_uint32(), INCORRECT_TYPE );
|
||||||
|
ASSERT_ERROR( val.get_int32(), INCORRECT_TYPE );
|
||||||
ASSERT_ERROR( val.get_object(), INCORRECT_TYPE );
|
ASSERT_ERROR( val.get_object(), INCORRECT_TYPE );
|
||||||
|
ASSERT_ERROR( val.get_int32(), INCORRECT_TYPE );
|
||||||
|
ASSERT_ERROR( val.get_uint32(), INCORRECT_TYPE );
|
||||||
ASSERT_ERROR( val.get_int64(), INCORRECT_TYPE );
|
ASSERT_ERROR( val.get_int64(), INCORRECT_TYPE );
|
||||||
ASSERT_ERROR( val.get_uint64(), INCORRECT_TYPE );
|
ASSERT_ERROR( val.get_uint64(), INCORRECT_TYPE );
|
||||||
ASSERT_ERROR( val.get_double(), INCORRECT_TYPE );
|
ASSERT_ERROR( val.get_double(), INCORRECT_TYPE );
|
||||||
@@ -279,7 +302,11 @@ namespace error_tests {
|
|||||||
ASSERT_ERROR( val.get_double(), INCORRECT_TYPE );
|
ASSERT_ERROR( val.get_double(), INCORRECT_TYPE );
|
||||||
ASSERT_ERROR( val.get_uint64(), INCORRECT_TYPE );
|
ASSERT_ERROR( val.get_uint64(), INCORRECT_TYPE );
|
||||||
ASSERT_ERROR( val.get_int64(), INCORRECT_TYPE );
|
ASSERT_ERROR( val.get_int64(), INCORRECT_TYPE );
|
||||||
|
ASSERT_ERROR( val.get_uint32(), INCORRECT_TYPE );
|
||||||
|
ASSERT_ERROR( val.get_int32(), INCORRECT_TYPE );
|
||||||
ASSERT_ERROR( val.get_object(), INCORRECT_TYPE );
|
ASSERT_ERROR( val.get_object(), INCORRECT_TYPE );
|
||||||
|
ASSERT_ERROR( val.get_int32(), INCORRECT_TYPE );
|
||||||
|
ASSERT_ERROR( val.get_uint32(), INCORRECT_TYPE );
|
||||||
ASSERT_ERROR( val.get_int64(), INCORRECT_TYPE );
|
ASSERT_ERROR( val.get_int64(), INCORRECT_TYPE );
|
||||||
ASSERT_ERROR( val.get_uint64(), INCORRECT_TYPE );
|
ASSERT_ERROR( val.get_uint64(), INCORRECT_TYPE );
|
||||||
ASSERT_ERROR( val.get_double(), INCORRECT_TYPE );
|
ASSERT_ERROR( val.get_double(), INCORRECT_TYPE );
|
||||||
@@ -306,7 +333,11 @@ namespace error_tests {
|
|||||||
ASSERT_ERROR( val.get_double(), INCORRECT_TYPE );
|
ASSERT_ERROR( val.get_double(), INCORRECT_TYPE );
|
||||||
ASSERT_ERROR( val.get_uint64(), INCORRECT_TYPE );
|
ASSERT_ERROR( val.get_uint64(), INCORRECT_TYPE );
|
||||||
ASSERT_ERROR( val.get_int64(), INCORRECT_TYPE );
|
ASSERT_ERROR( val.get_int64(), INCORRECT_TYPE );
|
||||||
|
ASSERT_ERROR( val.get_uint32(), INCORRECT_TYPE );
|
||||||
|
ASSERT_ERROR( val.get_int32(), INCORRECT_TYPE );
|
||||||
ASSERT_ERROR( val.get_object(), INCORRECT_TYPE );
|
ASSERT_ERROR( val.get_object(), INCORRECT_TYPE );
|
||||||
|
ASSERT_ERROR( val.get_int32(), INCORRECT_TYPE );
|
||||||
|
ASSERT_ERROR( val.get_uint32(), INCORRECT_TYPE );
|
||||||
ASSERT_ERROR( val.get_int64(), INCORRECT_TYPE );
|
ASSERT_ERROR( val.get_int64(), INCORRECT_TYPE );
|
||||||
ASSERT_ERROR( val.get_uint64(), INCORRECT_TYPE );
|
ASSERT_ERROR( val.get_uint64(), INCORRECT_TYPE );
|
||||||
ASSERT_ERROR( val.get_double(), INCORRECT_TYPE );
|
ASSERT_ERROR( val.get_double(), INCORRECT_TYPE );
|
||||||
@@ -329,7 +360,11 @@ namespace error_tests {
|
|||||||
ASSERT_ERROR( val.get_double(), INCORRECT_TYPE );
|
ASSERT_ERROR( val.get_double(), INCORRECT_TYPE );
|
||||||
ASSERT_ERROR( val.get_uint64(), INCORRECT_TYPE );
|
ASSERT_ERROR( val.get_uint64(), INCORRECT_TYPE );
|
||||||
ASSERT_ERROR( val.get_int64(), INCORRECT_TYPE );
|
ASSERT_ERROR( val.get_int64(), INCORRECT_TYPE );
|
||||||
|
ASSERT_ERROR( val.get_uint32(), INCORRECT_TYPE );
|
||||||
|
ASSERT_ERROR( val.get_int32(), INCORRECT_TYPE );
|
||||||
ASSERT_ERROR( val.get_object(), INCORRECT_TYPE );
|
ASSERT_ERROR( val.get_object(), INCORRECT_TYPE );
|
||||||
|
ASSERT_ERROR( val.get_int32(), INCORRECT_TYPE );
|
||||||
|
ASSERT_ERROR( val.get_uint32(), INCORRECT_TYPE );
|
||||||
ASSERT_ERROR( val.get_int64(), INCORRECT_TYPE );
|
ASSERT_ERROR( val.get_int64(), INCORRECT_TYPE );
|
||||||
ASSERT_ERROR( val.get_uint64(), INCORRECT_TYPE );
|
ASSERT_ERROR( val.get_uint64(), INCORRECT_TYPE );
|
||||||
ASSERT_ERROR( val.get_double(), INCORRECT_TYPE );
|
ASSERT_ERROR( val.get_double(), INCORRECT_TYPE );
|
||||||
@@ -350,7 +385,11 @@ namespace error_tests {
|
|||||||
ASSERT_ERROR( val.get_double(), INCORRECT_TYPE );
|
ASSERT_ERROR( val.get_double(), INCORRECT_TYPE );
|
||||||
ASSERT_ERROR( val.get_uint64(), INCORRECT_TYPE );
|
ASSERT_ERROR( val.get_uint64(), INCORRECT_TYPE );
|
||||||
ASSERT_ERROR( val.get_int64(), INCORRECT_TYPE );
|
ASSERT_ERROR( val.get_int64(), INCORRECT_TYPE );
|
||||||
|
ASSERT_ERROR( val.get_uint32(), INCORRECT_TYPE );
|
||||||
|
ASSERT_ERROR( val.get_int32(), INCORRECT_TYPE );
|
||||||
ASSERT_ERROR( val.get_object(), INCORRECT_TYPE );
|
ASSERT_ERROR( val.get_object(), INCORRECT_TYPE );
|
||||||
|
ASSERT_ERROR( val.get_int32(), INCORRECT_TYPE );
|
||||||
|
ASSERT_ERROR( val.get_uint32(), INCORRECT_TYPE );
|
||||||
ASSERT_ERROR( val.get_int64(), INCORRECT_TYPE );
|
ASSERT_ERROR( val.get_int64(), INCORRECT_TYPE );
|
||||||
ASSERT_ERROR( val.get_uint64(), INCORRECT_TYPE );
|
ASSERT_ERROR( val.get_uint64(), INCORRECT_TYPE );
|
||||||
ASSERT_ERROR( val.get_double(), INCORRECT_TYPE );
|
ASSERT_ERROR( val.get_double(), INCORRECT_TYPE );
|
||||||
@@ -371,7 +410,11 @@ namespace error_tests {
|
|||||||
ASSERT_ERROR( val.get_double(), INCORRECT_TYPE );
|
ASSERT_ERROR( val.get_double(), INCORRECT_TYPE );
|
||||||
ASSERT_ERROR( val.get_uint64(), INCORRECT_TYPE );
|
ASSERT_ERROR( val.get_uint64(), INCORRECT_TYPE );
|
||||||
ASSERT_ERROR( val.get_int64(), INCORRECT_TYPE );
|
ASSERT_ERROR( val.get_int64(), INCORRECT_TYPE );
|
||||||
|
ASSERT_ERROR( val.get_uint32(), INCORRECT_TYPE );
|
||||||
|
ASSERT_ERROR( val.get_int32(), INCORRECT_TYPE );
|
||||||
ASSERT_ERROR( val.get_object(), INCORRECT_TYPE );
|
ASSERT_ERROR( val.get_object(), INCORRECT_TYPE );
|
||||||
|
ASSERT_ERROR( val.get_int32(), INCORRECT_TYPE );
|
||||||
|
ASSERT_ERROR( val.get_uint32(), INCORRECT_TYPE );
|
||||||
ASSERT_ERROR( val.get_int64(), INCORRECT_TYPE );
|
ASSERT_ERROR( val.get_int64(), INCORRECT_TYPE );
|
||||||
ASSERT_ERROR( val.get_uint64(), INCORRECT_TYPE );
|
ASSERT_ERROR( val.get_uint64(), INCORRECT_TYPE );
|
||||||
ASSERT_ERROR( val.get_double(), INCORRECT_TYPE );
|
ASSERT_ERROR( val.get_double(), INCORRECT_TYPE );
|
||||||
@@ -432,6 +475,7 @@ namespace error_tests {
|
|||||||
raw_json_string_error() &&
|
raw_json_string_error() &&
|
||||||
empty_document_error() &&
|
empty_document_error() &&
|
||||||
parser_max_capacity() &&
|
parser_max_capacity() &&
|
||||||
|
parser_set_max_capacity() &&
|
||||||
get_fail_then_succeed_bool() &&
|
get_fail_then_succeed_bool() &&
|
||||||
get_fail_then_succeed_null() &&
|
get_fail_then_succeed_null() &&
|
||||||
simple_error_example() &&
|
simple_error_example() &&
|
||||||
|
|||||||
@@ -545,8 +545,111 @@ namespace number_tests {
|
|||||||
TEST_SUCCEED();
|
TEST_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool get_int32_values() {
|
||||||
|
TEST_START();
|
||||||
|
ondemand::parser parser;
|
||||||
|
ondemand::document doc;
|
||||||
|
int32_t val;
|
||||||
|
padded_string docdata;
|
||||||
|
|
||||||
|
// Valid int32 values
|
||||||
|
docdata = "0"_padded;
|
||||||
|
ASSERT_SUCCESS(parser.iterate(docdata).get(doc));
|
||||||
|
ASSERT_SUCCESS(doc.get_int32().get(val));
|
||||||
|
ASSERT_EQUAL(val, 0);
|
||||||
|
|
||||||
|
docdata = "42"_padded;
|
||||||
|
ASSERT_SUCCESS(parser.iterate(docdata).get(doc));
|
||||||
|
ASSERT_SUCCESS(doc.get_int32().get(val));
|
||||||
|
ASSERT_EQUAL(val, 42);
|
||||||
|
|
||||||
|
docdata = "-1"_padded;
|
||||||
|
ASSERT_SUCCESS(parser.iterate(docdata).get(doc));
|
||||||
|
ASSERT_SUCCESS(doc.get_int32().get(val));
|
||||||
|
ASSERT_EQUAL(val, -1);
|
||||||
|
|
||||||
|
docdata = "2147483647"_padded; // INT32_MAX
|
||||||
|
ASSERT_SUCCESS(parser.iterate(docdata).get(doc));
|
||||||
|
ASSERT_SUCCESS(doc.get_int32().get(val));
|
||||||
|
ASSERT_EQUAL(val, 2147483647);
|
||||||
|
|
||||||
|
docdata = "-2147483648"_padded; // INT32_MIN
|
||||||
|
ASSERT_SUCCESS(parser.iterate(docdata).get(doc));
|
||||||
|
ASSERT_SUCCESS(doc.get_int32().get(val));
|
||||||
|
ASSERT_EQUAL(val, -2147483648);
|
||||||
|
|
||||||
|
// Out of range
|
||||||
|
docdata = "2147483648"_padded; // INT32_MAX + 1
|
||||||
|
ASSERT_SUCCESS(parser.iterate(docdata).get(doc));
|
||||||
|
ASSERT_ERROR(doc.get_int32(), NUMBER_OUT_OF_RANGE);
|
||||||
|
|
||||||
|
docdata = "-2147483649"_padded; // INT32_MIN - 1
|
||||||
|
ASSERT_SUCCESS(parser.iterate(docdata).get(doc));
|
||||||
|
ASSERT_ERROR(doc.get_int32(), NUMBER_OUT_OF_RANGE);
|
||||||
|
|
||||||
|
docdata = "9999999999"_padded;
|
||||||
|
ASSERT_SUCCESS(parser.iterate(docdata).get(doc));
|
||||||
|
ASSERT_ERROR(doc.get_int32(), NUMBER_OUT_OF_RANGE);
|
||||||
|
|
||||||
|
// Test via value path
|
||||||
|
auto json = R"({"x": 42})"_padded;
|
||||||
|
ASSERT_SUCCESS(parser.iterate(json).get(doc));
|
||||||
|
ASSERT_SUCCESS(doc["x"].get_int32().get(val));
|
||||||
|
ASSERT_EQUAL(val, 42);
|
||||||
|
|
||||||
|
TEST_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool get_uint32_values() {
|
||||||
|
TEST_START();
|
||||||
|
ondemand::parser parser;
|
||||||
|
ondemand::document doc;
|
||||||
|
uint32_t val;
|
||||||
|
padded_string docdata;
|
||||||
|
|
||||||
|
// Valid uint32 values
|
||||||
|
docdata = "0"_padded;
|
||||||
|
ASSERT_SUCCESS(parser.iterate(docdata).get(doc));
|
||||||
|
ASSERT_SUCCESS(doc.get_uint32().get(val));
|
||||||
|
ASSERT_EQUAL(val, 0u);
|
||||||
|
|
||||||
|
docdata = "42"_padded;
|
||||||
|
ASSERT_SUCCESS(parser.iterate(docdata).get(doc));
|
||||||
|
ASSERT_SUCCESS(doc.get_uint32().get(val));
|
||||||
|
ASSERT_EQUAL(val, 42u);
|
||||||
|
|
||||||
|
docdata = "4294967295"_padded; // UINT32_MAX
|
||||||
|
ASSERT_SUCCESS(parser.iterate(docdata).get(doc));
|
||||||
|
ASSERT_SUCCESS(doc.get_uint32().get(val));
|
||||||
|
ASSERT_EQUAL(val, 4294967295u);
|
||||||
|
|
||||||
|
// Out of range
|
||||||
|
docdata = "4294967296"_padded; // UINT32_MAX + 1
|
||||||
|
ASSERT_SUCCESS(parser.iterate(docdata).get(doc));
|
||||||
|
ASSERT_ERROR(doc.get_uint32(), NUMBER_OUT_OF_RANGE);
|
||||||
|
|
||||||
|
docdata = "9999999999"_padded;
|
||||||
|
ASSERT_SUCCESS(parser.iterate(docdata).get(doc));
|
||||||
|
ASSERT_ERROR(doc.get_uint32(), NUMBER_OUT_OF_RANGE);
|
||||||
|
|
||||||
|
// Negative values should fail (get_uint64 will fail with INCORRECT_TYPE)
|
||||||
|
docdata = "-1"_padded;
|
||||||
|
ASSERT_SUCCESS(parser.iterate(docdata).get(doc));
|
||||||
|
ASSERT_ERROR(doc.get_uint32(), INCORRECT_TYPE);
|
||||||
|
|
||||||
|
// Test via value path
|
||||||
|
auto json = R"({"x": 42})"_padded;
|
||||||
|
ASSERT_SUCCESS(parser.iterate(json).get(doc));
|
||||||
|
ASSERT_SUCCESS(doc["x"].get_uint32().get(val));
|
||||||
|
ASSERT_EQUAL(val, 42u);
|
||||||
|
|
||||||
|
TEST_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
bool run() {
|
bool run() {
|
||||||
return minus_zero() &&
|
return get_int32_values() &&
|
||||||
|
get_uint32_values() &&
|
||||||
|
minus_zero() &&
|
||||||
gigantic_big_int() &&
|
gigantic_big_int() &&
|
||||||
big_int_not_zero() &&
|
big_int_not_zero() &&
|
||||||
negative_big_int() &&
|
negative_big_int() &&
|
||||||
|
|||||||
@@ -15,9 +15,9 @@ namespace wrong_type_error_tests {
|
|||||||
return false; \
|
return false; \
|
||||||
} \
|
} \
|
||||||
{ \
|
{ \
|
||||||
padded_string a_json(std::string(R"({ "a": )") + JSON + " }"); \
|
std::string a_json(R"({ "a": )"); a_json += JSON; a_json += " }"; \
|
||||||
std::cout << R"(- Subtest: get_)" << (#TYPE) << "() - JSON: " << a_json << std::endl; \
|
std::cout << R"(- Subtest: get_)" << (#TYPE) << "() - JSON: " << a_json << std::endl; \
|
||||||
if (!test_ondemand_doc(a_json, [&](auto doc_result) { \
|
if (!test_ondemand_doc(simdjson::pad(a_json), [&](auto doc_result) { \
|
||||||
ASSERT_ERROR( doc_result["a"].get_##TYPE(), (ERROR) ); \
|
ASSERT_ERROR( doc_result["a"].get_##TYPE(), (ERROR) ); \
|
||||||
return true; \
|
return true; \
|
||||||
})) { \
|
})) { \
|
||||||
|
|||||||
Reference in New Issue
Block a user