mirror of
https://github.com/simdjson/simdjson
synced 2026-06-08 17:27:07 +00:00
Compare commits
41 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5be57348c4 | |||
| 8955c2c6d5 | |||
| 73e69a5e84 | |||
| fb83b114ef | |||
| 542cd7af71 | |||
| 769364abb2 | |||
| f25d5f9fc2 | |||
| 12fb30ae9c | |||
| c0a952687d | |||
| 307ddd4415 | |||
| 21657455ed | |||
| afb1c9f4b1 | |||
| 9973f7b3a3 | |||
| 18d612df15 | |||
| bddb23177e | |||
| 2c5de6c6ed | |||
| 844e5eac23 | |||
| 45caa861cd | |||
| 50bf372d3f | |||
| b4a0fd3ff4 | |||
| a1ff05a5e8 | |||
| 5395aacb8b | |||
| 781ea4b495 | |||
| 03e8d14eee | |||
| be94694290 | |||
| 6065b3b424 | |||
| 019bf1dfe0 | |||
| 2922822622 | |||
| 262ddad037 | |||
| ba007b0cb9 | |||
| ec675d9c61 | |||
| 7dcc196f66 | |||
| 7ec4572d33 | |||
| 5891d4b64b | |||
| 3cd9875f1f | |||
| 6cf1bdba43 | |||
| 817f10dd7d | |||
| e829566589 | |||
| dbe0c1543e | |||
| 06c774c655 | |||
| 95d8c81810 |
@@ -29,6 +29,9 @@ We accept the identification of an issue by a sanitizer or some checker tool (e.
|
|||||||
|
|
||||||
We recommend that you run your tests using different optimization levels. In particular, we recommend your run tests with the simdjson library and you code compiled in debug mode. The simdjson then sets the SIMDJSON_DEVELOPMENT_CHECKS macro to 1, and this triggers additional checks on your code and on the internals of the library. If possible, we recommend that you run tests with sanitizers (e.g., see [No more leaks with sanitize flags in gcc and clang](https://lemire.me/blog/2016/04/20/no-more-leaks-with-sanitize-flags-in-gcc-and-clang/)). You can compile the library with sanitizers for debugging purposes (e.g., set SIMDJSON_SANITIZE to ON using CMake), but you should also turn on sanitizers on your own code. You may also use tools like valgrind or the commercial equivalent.
|
We recommend that you run your tests using different optimization levels. In particular, we recommend your run tests with the simdjson library and you code compiled in debug mode. The simdjson then sets the SIMDJSON_DEVELOPMENT_CHECKS macro to 1, and this triggers additional checks on your code and on the internals of the library. If possible, we recommend that you run tests with sanitizers (e.g., see [No more leaks with sanitize flags in gcc and clang](https://lemire.me/blog/2016/04/20/no-more-leaks-with-sanitize-flags-in-gcc-and-clang/)). You can compile the library with sanitizers for debugging purposes (e.g., set SIMDJSON_SANITIZE to ON using CMake), but you should also turn on sanitizers on your own code. You may also use tools like valgrind or the commercial equivalent.
|
||||||
|
|
||||||
|
Mixing debug and release simdjson code is unsafe: you either build all your code using simdjson in
|
||||||
|
release mode or all of it in debug mode.
|
||||||
|
|
||||||
Before reporting a bug, please ensure that you have read our documentation.
|
Before reporting a bug, please ensure that you have read our documentation.
|
||||||
|
|
||||||
**To Reproduce**
|
**To Reproduce**
|
||||||
@@ -55,6 +58,7 @@ We support up-to-date 64-bit ARM and x64 FreeBSD, macOS, Windows and Linux syste
|
|||||||
* We do not support unreleased or experimental compilers. If you encounter an issue with a
|
* We do not support unreleased or experimental compilers. If you encounter an issue with a
|
||||||
pre-release version of a compiler, do not report it as a bug to simdjson. However, we always
|
pre-release version of a compiler, do not report it as a bug to simdjson. However, we always
|
||||||
invite contributions either in the form an analysis or of a code contribution.
|
invite contributions either in the form an analysis or of a code contribution.
|
||||||
|
* Vendors (e.g., Apple and Microsoft) stop supporting old systems. Once a compiler system is no longer supported by its vendor, we no longer support it. We will gladly accept code contributions, but we do not consider it a *bug* if you have issues with an obsolete compiler systems. This policy extends to obsolete standard libraries, linkers and other build tools. Please do not report it as an issue. If you cannot resolve the issue yourself, we encourage you to reach out to the vendor for legacy support.
|
||||||
|
|
||||||
Under Windows, we support Visual Studio (both with LLVM and without). We do not support MinGW and other alternate compiler systems. Windows users should be aware that there [is a long-running bug with GCC under Windows](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54412).
|
Under Windows, we support Visual Studio (both with LLVM and without). We do not support MinGW and other alternate compiler systems. Windows users should be aware that there [is a long-running bug with GCC under Windows](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54412).
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ How to verify / test
|
|||||||
Please read before contributing:
|
Please read before contributing:
|
||||||
- CONTRIBUTING: https://github.com/simdjson/simdjson/blob/master/CONTRIBUTING.md
|
- CONTRIBUTING: https://github.com/simdjson/simdjson/blob/master/CONTRIBUTING.md
|
||||||
- HACKING: https://github.com/simdjson/simdjson/blob/master/HACKING.md
|
- HACKING: https://github.com/simdjson/simdjson/blob/master/HACKING.md
|
||||||
|
- AI Usage Policy: https://github.com/simdjson/simdjson/blob/master/AI_USAGE_POLICY.md
|
||||||
|
|
||||||
|
|
||||||
If you can, we recommend running our tests with the sanitizers turned on.
|
If you can, we recommend running our tests with the sanitizers turned on.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
name: Performance check on Ubuntu 20.04 CI (GCC 9)
|
name: Performance check on Ubuntu 24.04 CI (GCC 13)
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
name: Ubuntu 20.04 CI (GCC 9) without exceptions
|
name: Ubuntu 24.04 CI (GCC 13) without exceptions
|
||||||
|
|
||||||
on: [push, pull_request]
|
on: [push, pull_request]
|
||||||
|
|
||||||
@@ -24,7 +24,7 @@ jobs:
|
|||||||
cd .. &&
|
cd .. &&
|
||||||
mkdir build &&
|
mkdir build &&
|
||||||
cd build &&
|
cd build &&
|
||||||
cmake -DSIMDJSON_DEVELOPER_MODE=ON -DSIMDJSON_GOOGLE_BENCHMARKS=ON -DSIMDJSON_GOOGLE_BENCHMARKS=ON -DSIMDJSON_EXCEPTIONS=OFF -DBUILD_SHARED_LIBS=OFF -DCMAKE_INSTALL_PREFIX:PATH=destination .. &&
|
cmake -DSIMDJSON_DEVELOPER_MODE=ON -DSIMDJSON_GOOGLE_BENCHMARKS=ON -DSIMDJSON_EXCEPTIONS=OFF -DBUILD_SHARED_LIBS=OFF -DCMAKE_INSTALL_PREFIX:PATH=destination .. &&
|
||||||
cmake --build . &&
|
cmake --build . &&
|
||||||
ctest --output-on-failure -LE explicitonly -j &&
|
ctest --output-on-failure -LE explicitonly -j &&
|
||||||
make install &&
|
make install &&
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
name: Ubuntu 20.04 CI (GCC 9) Without Threads
|
name: Ubuntu 24.04 CI (GCC 13) Without Threads
|
||||||
|
|
||||||
on: [push, pull_request]
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
name: Ubuntu 20.04 CI (GCC 9) With Memory Sanitizer
|
name: Ubuntu 24.04 CI (GCC 13) With Memory Sanitizer
|
||||||
|
|
||||||
on: [push, pull_request]
|
on: [push, pull_request]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
ubuntu-build-address-sanitizier:
|
ubuntu-build-address-sanitizer:
|
||||||
if: >-
|
if: >-
|
||||||
! contains(toJSON(github.event.commits.*.message), '[skip ci]') &&
|
! contains(toJSON(github.event.commits.*.message), '[skip ci]') &&
|
||||||
! contains(toJSON(github.event.commits.*.message), '[skip github]')
|
! contains(toJSON(github.event.commits.*.message), '[skip github]')
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
# AI Usage Policy
|
||||||
|
|
||||||
|
Contributors can use whatever tools they would like to
|
||||||
|
craft their contributions, but there must be a **human in the loop**.
|
||||||
|
**Contributors must read and review all LLM-generated code or text before they
|
||||||
|
ask other project members to review it.** The contributor is always the author
|
||||||
|
and is fully accountable for their contributions. Contributors should be
|
||||||
|
sufficiently confident that the contribution is high enough quality that asking
|
||||||
|
for a review is a good use of scarce maintainer time, and they should be **able
|
||||||
|
to answer questions about their work** during review.
|
||||||
|
|
||||||
|
We expect that new contributors will be less confident in their contributions,
|
||||||
|
and our guidance to them is to **start with small contributions** that they can
|
||||||
|
fully understand to build confidence. We aspire to be a welcoming community
|
||||||
|
that helps new contributors grow their expertise, but learning involves taking
|
||||||
|
small steps, getting feedback, and iterating. Passing maintainer feedback to an
|
||||||
|
LLM doesn't help anyone grow, and does not sustain our community.
|
||||||
|
|
||||||
|
This policy includes, but is not limited to, the following kinds of
|
||||||
|
contributions:
|
||||||
|
|
||||||
|
- Code, usually in the form of a pull request
|
||||||
|
- Issues or security vulnerabilities
|
||||||
|
- Comments and feedback on pull requests
|
||||||
|
|
||||||
|
## Extractive Contributions
|
||||||
|
|
||||||
|
The reason for our "human-in-the-loop" contribution policy is that processing
|
||||||
|
patches, PRs, RFCs, and comments is not free -- it takes a lot of
|
||||||
|
maintainer time and energy to review those contributions! Sending the
|
||||||
|
unreviewed output of an LLM to open source project maintainers *extracts* work
|
||||||
|
from them in the form of design and code review, so we call this kind of
|
||||||
|
contribution an "extractive contribution".
|
||||||
|
|
||||||
|
## Transparency
|
||||||
|
|
||||||
|
For contributions involving significant AI assistance, we encourage you to disclose
|
||||||
|
its use and explain your process. If a submission appears to rely heavily on AI
|
||||||
|
without disclosure, we may doubt that the **human-in-the-loop** requirement has
|
||||||
|
been met. Please show awareness of your use of AI.
|
||||||
|
|
||||||
|
## Copyright
|
||||||
|
|
||||||
|
Artificial intelligence systems raise many questions around copyright that have
|
||||||
|
yet to be answered. Our policy on AI tools is similar to our copyright policy:
|
||||||
|
Contributors are responsible for ensuring that they have the right to
|
||||||
|
contribute code under the terms of our license, typically meaning that either
|
||||||
|
they, their employer, or their collaborators hold the copyright. Using AI tools
|
||||||
|
to regenerate copyrighted material does not remove the copyright, and
|
||||||
|
contributors are responsible for ensuring that such material does not appear in
|
||||||
|
their contributions. Contributions found to violate this policy will be removed
|
||||||
|
just like any other offending contribution.
|
||||||
|
|
||||||
|
## Reference
|
||||||
|
|
||||||
|
- [LLVM AI Tool Use Policy](https://discourse.llvm.org/t/rfc-llvm-ai-tool-policy-human-in-the-loop/89159)
|
||||||
+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.2.4
|
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 "29.0.0" CACHE STRING "simdjson library version")
|
set(SIMDJSON_LIB_VERSION "33.0.0" CACHE STRING "simdjson library version")
|
||||||
set(SIMDJSON_LIB_SOVERSION "29" 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()
|
||||||
|
|
||||||
##
|
##
|
||||||
|
|||||||
@@ -101,3 +101,10 @@ Getting Started Hacking
|
|||||||
|
|
||||||
An overview of simdjson's directory structure, with pointers to architecture and design
|
An overview of simdjson's directory structure, with pointers to architecture and design
|
||||||
considerations and other helpful notes, can be found at [HACKING.md](HACKING.md).
|
considerations and other helpful notes, can be found at [HACKING.md](HACKING.md).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
AI Usage Policy
|
||||||
|
---------------
|
||||||
|
|
||||||
|
Please also review our [AI Usage Policy](AI_USAGE_POLICY.md).
|
||||||
|
|||||||
@@ -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.2.4"
|
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.
|
||||||
@@ -188,6 +189,7 @@ We distinguish between "bindings" (which just wrap the C++ code) and a port to a
|
|||||||
- [JSON::SIMD](https://metacpan.org/pod/JSON::SIMD): Perl bindings; fully-featured JSON module that uses simdjson for decoding.
|
- [JSON::SIMD](https://metacpan.org/pod/JSON::SIMD): Perl bindings; fully-featured JSON module that uses simdjson for decoding.
|
||||||
- [gemmaJSON](https://github.com/sainttttt/gemmaJSON): Nim JSON parser based on simdjson bindings.
|
- [gemmaJSON](https://github.com/sainttttt/gemmaJSON): Nim JSON parser based on simdjson bindings.
|
||||||
- [simdjson-java](https://github.com/simdjson/simdjson-java): Java port.
|
- [simdjson-java](https://github.com/simdjson/simdjson-java): Java port.
|
||||||
|
- [mruby-fast-json](https://github.com/Asmod4n/mruby-fast-json): mruby binding with high API coverage.
|
||||||
|
|
||||||
About simdjson
|
About simdjson
|
||||||
--------------
|
--------------
|
||||||
@@ -210,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"
|
||||||
|
|||||||
+24
-7
@@ -271,6 +271,21 @@ Further, they may use the AreFileApisANSI function to determine whether
|
|||||||
the filename is interpreted using the ANSI or the system default OEM
|
the filename is interpreted using the ANSI or the system default OEM
|
||||||
codepage, and they may call SetFileApisToOEM accordingly.
|
codepage, and they may call SetFileApisToOEM accordingly.
|
||||||
|
|
||||||
|
|
||||||
|
**Advanced feature:**
|
||||||
|
On non-Windows systems, you can use memory-file mapping to create a `simdjson::padded_string_view`
|
||||||
|
from a file on disk.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// If the macro _WIN32 is defined, this will not work since we do not support memory-file mapping
|
||||||
|
// under Windows at this time.
|
||||||
|
simdjson::padded_memory_map map(myfilename);
|
||||||
|
if (!map.is_valid()) { /* handle error */ }
|
||||||
|
simdjson::padded_string_view view = map.view(); // view is usable while padded_memory_map is in scope
|
||||||
|
ondemand::document doc = parser.iterate(view); // parse the JSON
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
Documents are iterators
|
Documents are iterators
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
@@ -364,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
|
||||||
@@ -374,6 +391,10 @@ builds to disable additional runtime testing and get the best performance. We
|
|||||||
disable these checks on a best-effort basis but the C++ standard does not provide
|
disable these checks on a best-effort basis but the C++ standard does not provide
|
||||||
a direct way to check for a release build.
|
a direct way to check for a release build.
|
||||||
|
|
||||||
|
|
||||||
|
Warnign: Mixing debug and release simdjson code is unsafe: you either build all your code
|
||||||
|
using simdjson in release mode or all of it in debug mode.
|
||||||
|
|
||||||
Using the parsed JSON
|
Using the parsed JSON
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
@@ -417,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,
|
||||||
@@ -427,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.
|
||||||
|
|
||||||
@@ -1281,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;
|
||||||
}
|
}
|
||||||
|
|||||||
+34
-1
@@ -125,6 +125,22 @@ Further, they may use the AreFileApisANSI function to determine whether
|
|||||||
the filename is interpreted using the ANSI or the system default OEM
|
the filename is interpreted using the ANSI or the system default OEM
|
||||||
codepage, and they may call SetFileApisToOEM accordingly.
|
codepage, and they may call SetFileApisToOEM accordingly.
|
||||||
|
|
||||||
|
|
||||||
|
**Advanced feature:**
|
||||||
|
On non-Windows systems, you can use memory-file mapping to create a `simdjson::padded_string_view`
|
||||||
|
from a file on disk.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// if the macro _WIN32 is defined, this will not work since we do not support Windows
|
||||||
|
simdjson::padded_memory_map map(TWITTER_JSON);
|
||||||
|
if (!map.is_valid()) { /* handle error */ }
|
||||||
|
simdjson::padded_string_view view = map.view(); // view is usable while padded_memory_map is in scope
|
||||||
|
ondemand::document doc = parser.iterate(view); // parse the JSON
|
||||||
|
```
|
||||||
|
|
||||||
|
Using memory-file mapping requires some care. The file should not be modified while you are
|
||||||
|
accessing it.
|
||||||
|
|
||||||
Using the Parsed JSON
|
Using the Parsed JSON
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
@@ -152,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) { ... }`
|
||||||
@@ -164,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
|
||||||
|
|||||||
@@ -33,6 +33,9 @@ compiles *all* the implementations into the executable. On Intel, it will includ
|
|||||||
(icelake, haswell, westmere and fallback), on 64-bit ARM it will include just one since running dispatching is unnecessary, and on PPC
|
(icelake, haswell, westmere and fallback), on 64-bit ARM it will include just one since running dispatching is unnecessary, and on PPC
|
||||||
it will include 2 (ppc64 and fallback).
|
it will include 2 (ppc64 and fallback).
|
||||||
|
|
||||||
|
On Loongson processors, LASX runtime dispatching is only enabled on GCC 15+, not on LLVM or older versions of GCC.
|
||||||
|
Thus unless you compile specifically for LASX or use GCC 15+, you will not benefit from LASX support.
|
||||||
|
|
||||||
If you know more about where you're going to run and want to save the space, you can disable any of
|
If you know more about where you're going to run and want to save the space, you can disable any of
|
||||||
these implementations at compile time with `-DSIMDJSON_IMPLEMENTATION_X=0` (where X is ICELAKE, HASWELL,
|
these implementations at compile time with `-DSIMDJSON_IMPLEMENTATION_X=0` (where X is ICELAKE, HASWELL,
|
||||||
WESTMERE, ARM64, PPC64, LSX, LASX and FALLBACK).
|
WESTMERE, ARM64, PPC64, LSX, LASX and FALLBACK).
|
||||||
|
|||||||
@@ -154,6 +154,20 @@ for (auto doc : docs) {
|
|||||||
|
|
||||||
See [basics.md](basics.md#newline-delimited-json-ndjson-and-json-lines) for an overview of the API.
|
See [basics.md](basics.md#newline-delimited-json-ndjson-and-json-lines) for an overview of the API.
|
||||||
|
|
||||||
|
|
||||||
|
**Advanced feature:**
|
||||||
|
On non-Windows systems, you can use memory-file mapping to create a `simdjson::padded_string_view`
|
||||||
|
from a file on disk.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// If the macro _WIN32 is defined, this will not work since we do not support memory-file mapping
|
||||||
|
// under Windows at this time.
|
||||||
|
simdjson::padded_memory_map map(myfilename);
|
||||||
|
if (!map.is_valid()) { /* handle error */ }
|
||||||
|
simdjson::padded_string_view view = map.view(); // view is usable while padded_memory_map is in scope
|
||||||
|
ondemand::document doc = parser.iterate(view); // parse the JSON
|
||||||
|
```
|
||||||
|
|
||||||
## Use cases
|
## Use cases
|
||||||
|
|
||||||
From [jsonlines.org](http://jsonlines.org/examples/):
|
From [jsonlines.org](http://jsonlines.org/examples/):
|
||||||
|
|||||||
@@ -217,6 +217,20 @@ got full document at 29
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Advanced feature:**
|
||||||
|
On non-Windows systems, you can use memory-file mapping to create a `simdjson::padded_string_view`
|
||||||
|
from a file on disk.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// If the macro _WIN32 is defined, this will not work since we do not support memory-file mapping
|
||||||
|
// under Windows at this time.
|
||||||
|
simdjson::padded_memory_map map(myfilename);
|
||||||
|
if (!map.is_valid()) { /* handle error */ }
|
||||||
|
simdjson::padded_string_view view = map.view(); // view is usable while padded_memory_map is in scope
|
||||||
|
ondemand::document doc = parser.iterate(view); // parse the JSON
|
||||||
|
```
|
||||||
|
|
||||||
Incomplete streams
|
Incomplete streams
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -119,5 +119,4 @@
|
|||||||
#define SIMDJSON_CONSTEVAL 0
|
#define SIMDJSON_CONSTEVAL 0
|
||||||
#endif // defined(__cpp_consteval) && __cpp_consteval >= 201811L && defined(__cpp_lib_constexpr_string) && __cpp_lib_constexpr_string >= 201907L
|
#endif // defined(__cpp_consteval) && __cpp_consteval >= 201811L && defined(__cpp_lib_constexpr_string) && __cpp_lib_constexpr_string >= 201907L
|
||||||
#endif // !defined(SIMDJSON_CONSTEVAL)
|
#endif // !defined(SIMDJSON_CONSTEVAL)
|
||||||
|
|
||||||
#endif // SIMDJSON_COMPILER_CHECK_H
|
#endif // SIMDJSON_COMPILER_CHECK_H
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -41,6 +41,19 @@ simdjson_inline int leading_zeroes(uint64_t input_num) {
|
|||||||
#endif// _MSC_VER
|
#endif// _MSC_VER
|
||||||
}
|
}
|
||||||
|
|
||||||
|
simdjson_inline int trailing_zeroes(uint64_t input_num) {
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
unsigned long trailing_zero = 0;
|
||||||
|
// Search the mask data from least significant bit (LSB)
|
||||||
|
// to most significant bit (MSB) for a set bit (1).
|
||||||
|
if (_BitScanForward64(&trailing_zero, input_num))
|
||||||
|
return (int)trailing_zero;
|
||||||
|
else return 64;
|
||||||
|
#else
|
||||||
|
return __builtin_ctzll(input_num);
|
||||||
|
#endif// _MSC_VER
|
||||||
|
}
|
||||||
|
|
||||||
} // unnamed namespace
|
} // unnamed namespace
|
||||||
} // namespace fallback
|
} // namespace fallback
|
||||||
} // namespace simdjson
|
} // namespace simdjson
|
||||||
|
|||||||
@@ -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(':');
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,22 @@
|
|||||||
#define SIMDJSON_EXPERIMENTAL_HAS_NEON 1
|
#define SIMDJSON_EXPERIMENTAL_HAS_NEON 1
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(__loongarch_sx)
|
||||||
|
#ifndef SIMDJSON_EXPERIMENTAL_HAS_LSX
|
||||||
|
#define SIMDJSON_EXPERIMENTAL_HAS_LSX 1
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#if defined(__riscv_v_intrinsic) && __riscv_v_intrinsic >= 11000 && \
|
||||||
|
defined(__riscv_vector)
|
||||||
|
#ifndef SIMDJSON_EXPERIMENTAL_HAS_RVV
|
||||||
|
#define SIMDJSON_EXPERIMENTAL_HAS_RVV 1
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#if (defined(__PPC64__) || defined(_M_PPC64)) && defined(__ALTIVEC__)
|
||||||
|
#ifndef SIMDJSON_EXPERIMENTAL_HAS_PPC64
|
||||||
|
#define SIMDJSON_EXPERIMENTAL_HAS_PPC64 1
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
#if SIMDJSON_EXPERIMENTAL_HAS_NEON
|
#if SIMDJSON_EXPERIMENTAL_HAS_NEON
|
||||||
#include <arm_neon.h>
|
#include <arm_neon.h>
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
@@ -39,6 +55,22 @@
|
|||||||
#include <intrin.h>
|
#include <intrin.h>
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
#if SIMDJSON_EXPERIMENTAL_HAS_LSX
|
||||||
|
#include <lsxintrin.h>
|
||||||
|
#endif
|
||||||
|
#if SIMDJSON_EXPERIMENTAL_HAS_RVV
|
||||||
|
#include <riscv_vector.h>
|
||||||
|
#endif
|
||||||
|
#if SIMDJSON_EXPERIMENTAL_HAS_PPC64
|
||||||
|
#include <altivec.h>
|
||||||
|
#ifdef bool
|
||||||
|
#undef bool
|
||||||
|
#endif
|
||||||
|
#ifdef vector
|
||||||
|
#undef vector
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
namespace simdjson {
|
namespace simdjson {
|
||||||
namespace SIMDJSON_IMPLEMENTATION {
|
namespace SIMDJSON_IMPLEMENTATION {
|
||||||
@@ -139,6 +171,35 @@ simdjson_inline bool fast_needs_escaping(std::string_view view) {
|
|||||||
}
|
}
|
||||||
return _mm_movemask_epi8(running) != 0;
|
return _mm_movemask_epi8(running) != 0;
|
||||||
}
|
}
|
||||||
|
#elif SIMDJSON_EXPERIMENTAL_HAS_PPC64
|
||||||
|
simdjson_inline bool fast_needs_escaping(std::string_view view) {
|
||||||
|
if (view.size() < 16) {
|
||||||
|
return simple_needs_escaping(view);
|
||||||
|
}
|
||||||
|
size_t i = 0;
|
||||||
|
__vector unsigned char running = vec_splats((unsigned char)0);
|
||||||
|
__vector unsigned char v34 = vec_splats((unsigned char)34);
|
||||||
|
__vector unsigned char v92 = vec_splats((unsigned char)92);
|
||||||
|
__vector unsigned char v32 = vec_splats((unsigned char)32);
|
||||||
|
|
||||||
|
for (; i + 15 < view.size(); i += 16) {
|
||||||
|
__vector unsigned char word =
|
||||||
|
vec_vsx_ld(0, reinterpret_cast<const unsigned char *>(view.data() + i));
|
||||||
|
running = vec_or(running, (__vector unsigned char)vec_cmpeq(word, v34));
|
||||||
|
running = vec_or(running, (__vector unsigned char)vec_cmpeq(word, v92));
|
||||||
|
running = vec_or(running,
|
||||||
|
(__vector unsigned char)vec_cmplt(word, v32));
|
||||||
|
}
|
||||||
|
if (i < view.size()) {
|
||||||
|
__vector unsigned char word = vec_vsx_ld(
|
||||||
|
0, reinterpret_cast<const unsigned char *>(view.data() + view.length() - 16));
|
||||||
|
running = vec_or(running, (__vector unsigned char)vec_cmpeq(word, v34));
|
||||||
|
running = vec_or(running, (__vector unsigned char)vec_cmpeq(word, v92));
|
||||||
|
running = vec_or(running,
|
||||||
|
(__vector unsigned char)vec_cmplt(word, v32));
|
||||||
|
}
|
||||||
|
return !vec_all_eq(running, vec_splats((unsigned char)0));
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
simdjson_inline bool fast_needs_escaping(std::string_view view) {
|
simdjson_inline bool fast_needs_escaping(std::string_view view) {
|
||||||
return simple_needs_escaping(view);
|
return simple_needs_escaping(view);
|
||||||
@@ -146,7 +207,7 @@ simdjson_inline bool fast_needs_escaping(std::string_view view) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Scalar fallback for finding next quotable character
|
// Scalar fallback for finding next quotable character
|
||||||
SIMDJSON_CONSTEXPR_LAMBDA inline size_t
|
SIMDJSON_CONSTEXPR_LAMBDA simdjson_inline size_t
|
||||||
find_next_json_quotable_character_scalar(const std::string_view view,
|
find_next_json_quotable_character_scalar(const std::string_view view,
|
||||||
size_t location) noexcept {
|
size_t location) noexcept {
|
||||||
for (auto pos = view.begin() + location; pos != view.end(); ++pos) {
|
for (auto pos = view.begin() + location; pos != view.end(); ++pos) {
|
||||||
@@ -182,28 +243,12 @@ find_next_json_quotable_character(const std::string_view view,
|
|||||||
needs_escape = vorrq_u8(needs_escape, vceqq_u8(word, v92));
|
needs_escape = vorrq_u8(needs_escape, vceqq_u8(word, v92));
|
||||||
needs_escape = vorrq_u8(needs_escape, vcltq_u8(word, v32));
|
needs_escape = vorrq_u8(needs_escape, vcltq_u8(word, v32));
|
||||||
|
|
||||||
if (vmaxvq_u32(vreinterpretq_u32_u8(needs_escape)) != 0) {
|
const uint8x8_t res = vshrn_n_u16(vreinterpretq_u16_u8(needs_escape), 4);
|
||||||
// Found quotable character - extract exact byte position using ctz
|
const uint64_t mask = vget_lane_u64(vreinterpret_u64_u8(res), 0);
|
||||||
uint64x2_t as64 = vreinterpretq_u64_u8(needs_escape);
|
if(mask != 0) {
|
||||||
uint64_t lo = vgetq_lane_u64(as64, 0);
|
|
||||||
uint64_t hi = vgetq_lane_u64(as64, 1);
|
|
||||||
size_t offset = ptr - reinterpret_cast<const uint8_t *>(view.data());
|
size_t offset = ptr - reinterpret_cast<const uint8_t *>(view.data());
|
||||||
#ifdef _MSC_VER
|
auto trailing_zero = trailing_zeroes(mask);
|
||||||
unsigned long trailing_zero = 0;
|
return offset + (trailing_zero >> 2);
|
||||||
if (lo != 0) {
|
|
||||||
_BitScanForward64(&trailing_zero, lo);
|
|
||||||
return offset + trailing_zero / 8;
|
|
||||||
} else {
|
|
||||||
_BitScanForward64(&trailing_zero, hi);
|
|
||||||
return offset + 8 + trailing_zero / 8;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
if (lo != 0) {
|
|
||||||
return offset + __builtin_ctzll(lo) / 8;
|
|
||||||
} else {
|
|
||||||
return offset + 8 + __builtin_ctzll(hi) / 8;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
ptr += 16;
|
ptr += 16;
|
||||||
remaining -= 16;
|
remaining -= 16;
|
||||||
@@ -241,13 +286,128 @@ find_next_json_quotable_character(const std::string_view view,
|
|||||||
if (mask != 0) {
|
if (mask != 0) {
|
||||||
// Found quotable character - use trailing zero count to find position
|
// Found quotable character - use trailing zero count to find position
|
||||||
size_t offset = ptr - reinterpret_cast<const uint8_t *>(view.data());
|
size_t offset = ptr - reinterpret_cast<const uint8_t *>(view.data());
|
||||||
#ifdef _MSC_VER
|
return offset + trailing_zeroes(mask);
|
||||||
unsigned long trailing_zero = 0;
|
}
|
||||||
_BitScanForward(&trailing_zero, mask);
|
ptr += 16;
|
||||||
return offset + trailing_zero;
|
remaining -= 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scalar fallback for remaining bytes
|
||||||
|
size_t current = len - remaining;
|
||||||
|
return find_next_json_quotable_character_scalar(view, current);
|
||||||
|
}
|
||||||
|
#elif SIMDJSON_EXPERIMENTAL_HAS_LSX
|
||||||
|
simdjson_inline size_t
|
||||||
|
find_next_json_quotable_character(const std::string_view view,
|
||||||
|
size_t location) noexcept {
|
||||||
|
const size_t len = view.size();
|
||||||
|
const uint8_t *ptr =
|
||||||
|
reinterpret_cast<const uint8_t *>(view.data()) + location;
|
||||||
|
size_t remaining = len - location;
|
||||||
|
|
||||||
|
//SIMD constants for characters requiring escape
|
||||||
|
__m128i v34 = __lsx_vreplgr2vr_b(34); // '"'
|
||||||
|
__m128i v92 = __lsx_vreplgr2vr_b(92); // '\\'
|
||||||
|
__m128i v32 = __lsx_vreplgr2vr_b(32); // control char threshold
|
||||||
|
|
||||||
|
while (remaining >= 16){
|
||||||
|
__m128i word = __lsx_vld(ptr, 0);
|
||||||
|
|
||||||
|
//Check for the quotable characters: '"', '\\', or control char (<32)
|
||||||
|
__m128i needs_escape = __lsx_vseq_b(word, v34);
|
||||||
|
needs_escape = __lsx_vor_v(needs_escape, __lsx_vseq_b(word, v92));
|
||||||
|
needs_escape = __lsx_vor_v(needs_escape, __lsx_vslt_bu(word, v32));
|
||||||
|
|
||||||
|
if (!__lsx_bz_v(needs_escape)){
|
||||||
|
|
||||||
|
//Found quotable character - extract exact byte position
|
||||||
|
uint64_t lo = __lsx_vpickve2gr_du(needs_escape,0);
|
||||||
|
uint64_t hi = __lsx_vpickve2gr_du(needs_escape,1);
|
||||||
|
size_t offset = ptr - reinterpret_cast<const uint8_t *>(view.data());
|
||||||
|
if ( lo != 0) {
|
||||||
|
return offset + trailing_zeroes(lo) / 8;
|
||||||
|
} else {
|
||||||
|
return offset + 8 + trailing_zeroes(hi) / 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ptr += 16;
|
||||||
|
remaining -= 16;
|
||||||
|
}
|
||||||
|
size_t current = len - remaining;
|
||||||
|
return find_next_json_quotable_character_scalar(view, current);
|
||||||
|
}
|
||||||
|
#elif SIMDJSON_EXPERIMENTAL_HAS_RVV
|
||||||
|
simdjson_inline size_t
|
||||||
|
find_next_json_quotable_character(const std::string_view view,
|
||||||
|
size_t location) noexcept {
|
||||||
|
const size_t len = view.size();
|
||||||
|
const uint8_t *ptr =
|
||||||
|
reinterpret_cast<const uint8_t *>(view.data()) + location;
|
||||||
|
size_t remaining = len - location;
|
||||||
|
|
||||||
|
while (remaining > 0) {
|
||||||
|
size_t vl = __riscv_vsetvl_e8m1(remaining);
|
||||||
|
vuint8m1_t word = __riscv_vle8_v_u8m1(ptr, vl);
|
||||||
|
|
||||||
|
// Check for quotable characters: '"', '\\', or control chars (< 32)
|
||||||
|
vbool8_t needs_escape = __riscv_vmseq(word, (uint8_t)34, vl);
|
||||||
|
needs_escape = __riscv_vmor(needs_escape,
|
||||||
|
__riscv_vmseq(word, (uint8_t)92, vl), vl);
|
||||||
|
needs_escape = __riscv_vmor(needs_escape,
|
||||||
|
__riscv_vmsltu(word, (uint8_t)32, vl), vl);
|
||||||
|
|
||||||
|
long first = __riscv_vfirst(needs_escape, vl);
|
||||||
|
if (first >= 0) {
|
||||||
|
size_t offset = ptr - reinterpret_cast<const uint8_t *>(view.data());
|
||||||
|
return offset + first;
|
||||||
|
}
|
||||||
|
ptr += vl;
|
||||||
|
remaining -= vl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
#elif SIMDJSON_EXPERIMENTAL_HAS_PPC64
|
||||||
|
simdjson_inline size_t
|
||||||
|
find_next_json_quotable_character(const std::string_view view,
|
||||||
|
size_t location) noexcept {
|
||||||
|
const size_t len = view.size();
|
||||||
|
const uint8_t *ptr =
|
||||||
|
reinterpret_cast<const uint8_t *>(view.data()) + location;
|
||||||
|
size_t remaining = len - location;
|
||||||
|
|
||||||
|
// SIMD constants for characters requiring escape
|
||||||
|
__vector unsigned char v34 = vec_splats((unsigned char)34); // '"'
|
||||||
|
__vector unsigned char v92 = vec_splats((unsigned char)92); // '\\'
|
||||||
|
__vector unsigned char v32 = vec_splats((unsigned char)32); // control char threshold
|
||||||
|
|
||||||
|
// Bitmask for vec_vbpermq to extract one bit per byte
|
||||||
|
const __vector unsigned char perm_mask = {0x78, 0x70, 0x68, 0x60, 0x58, 0x50,
|
||||||
|
0x48, 0x40, 0x38, 0x30, 0x28, 0x20,
|
||||||
|
0x18, 0x10, 0x08, 0x00};
|
||||||
|
|
||||||
|
while (remaining >= 16) {
|
||||||
|
__vector unsigned char word =
|
||||||
|
vec_vsx_ld(0, reinterpret_cast<const unsigned char *>(ptr));
|
||||||
|
|
||||||
|
// Check for quotable characters: '"', '\\', or control chars (< 32)
|
||||||
|
__vector unsigned char needs_escape =
|
||||||
|
(__vector unsigned char)vec_cmpeq(word, v34);
|
||||||
|
needs_escape = vec_or(needs_escape,
|
||||||
|
(__vector unsigned char)vec_cmpeq(word, v92));
|
||||||
|
needs_escape = vec_or(needs_escape,
|
||||||
|
(__vector unsigned char)vec_cmplt(word, v32));
|
||||||
|
|
||||||
|
__vector unsigned long long result =
|
||||||
|
(__vector unsigned long long)vec_vbpermq(needs_escape, perm_mask);
|
||||||
|
#ifdef __LITTLE_ENDIAN__
|
||||||
|
unsigned int mask = static_cast<unsigned int>(result[1]);
|
||||||
#else
|
#else
|
||||||
return offset + __builtin_ctz(mask);
|
unsigned int mask = static_cast<unsigned int>(result[0]);
|
||||||
#endif
|
#endif
|
||||||
|
if (mask != 0) {
|
||||||
|
size_t offset = ptr - reinterpret_cast<const uint8_t *>(view.data());
|
||||||
|
return offset + __builtin_ctz(mask);
|
||||||
}
|
}
|
||||||
ptr += 16;
|
ptr += 16;
|
||||||
remaining -= 16;
|
remaining -= 16;
|
||||||
@@ -258,7 +418,7 @@ find_next_json_quotable_character(const std::string_view view,
|
|||||||
return find_next_json_quotable_character_scalar(view, current);
|
return find_next_json_quotable_character_scalar(view, current);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
SIMDJSON_CONSTEXPR_LAMBDA inline size_t
|
SIMDJSON_CONSTEXPR_LAMBDA simdjson_inline size_t
|
||||||
find_next_json_quotable_character(const std::string_view view,
|
find_next_json_quotable_character(const std::string_view view,
|
||||||
size_t location) noexcept {
|
size_t location) noexcept {
|
||||||
return find_next_json_quotable_character_scalar(view, location);
|
return find_next_json_quotable_character_scalar(view, location);
|
||||||
@@ -277,7 +437,7 @@ SIMDJSON_CONSTEXPR_LAMBDA static std::string_view control_chars[] = {
|
|||||||
// control characters (U+0000 through U+001F). There are two-character sequence
|
// control characters (U+0000 through U+001F). There are two-character sequence
|
||||||
// escape representations of some popular characters:
|
// escape representations of some popular characters:
|
||||||
// \", \\, \b, \f, \n, \r, \t.
|
// \", \\, \b, \f, \n, \r, \t.
|
||||||
SIMDJSON_CONSTEXPR_LAMBDA void escape_json_char(char c, char *&out) {
|
SIMDJSON_CONSTEXPR_LAMBDA simdjson_inline void escape_json_char(char c, char *&out) {
|
||||||
if (c == '"') {
|
if (c == '"') {
|
||||||
memcpy(out, "\\\"", 2);
|
memcpy(out, "\\\"", 2);
|
||||||
out += 2;
|
out += 2;
|
||||||
@@ -336,7 +496,7 @@ simdjson_inline bool string_builder::capacity_check(size_t upcoming_bytes) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// check for overflow, most of the time there is no overflow
|
// check for overflow, most of the time there is no overflow
|
||||||
if (simdjson_likely(position + upcoming_bytes < position)) {
|
if (simdjson_unlikely(position + upcoming_bytes < position)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// We will rarely get here.
|
// We will rarely get here.
|
||||||
@@ -345,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;
|
||||||
}
|
}
|
||||||
@@ -682,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
|
||||||
|
|||||||
@@ -10,6 +10,14 @@
|
|||||||
#include <climits>
|
#include <climits>
|
||||||
#include <cwchar>
|
#include <cwchar>
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace simdjson {
|
namespace simdjson {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
@@ -160,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) {
|
||||||
@@ -215,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) {
|
||||||
@@ -341,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;
|
||||||
@@ -350,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) {
|
||||||
@@ -366,6 +384,57 @@ inline bool padded_string_builder::reserve(size_t additional) noexcept {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
simdjson_inline padded_memory_map::padded_memory_map(const char *filename) noexcept {
|
||||||
|
|
||||||
|
int fd = open(filename, O_RDONLY);
|
||||||
|
if (fd == -1) {
|
||||||
|
return; // file not found or cannot be opened, data will be nullptr
|
||||||
|
}
|
||||||
|
struct stat st;
|
||||||
|
if (fstat(fd, &st) == -1) {
|
||||||
|
close(fd);
|
||||||
|
return; // failed to get file size, data will be nullptr
|
||||||
|
}
|
||||||
|
size = static_cast<size_t>(st.st_size);
|
||||||
|
size_t total_size = size + simdjson::SIMDJSON_PADDING;
|
||||||
|
void *anon_map =
|
||||||
|
mmap(NULL, total_size, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||||
|
if (anon_map == MAP_FAILED) {
|
||||||
|
close(fd);
|
||||||
|
return; // failed to create anonymous mapping, data will be nullptr
|
||||||
|
}
|
||||||
|
void *file_map =
|
||||||
|
mmap(anon_map, size, PROT_READ, MAP_SHARED | MAP_FIXED, fd, 0);
|
||||||
|
if (file_map == MAP_FAILED) {
|
||||||
|
munmap(anon_map, total_size);
|
||||||
|
close(fd);
|
||||||
|
return; // failed to mmap file, data will be nullptr
|
||||||
|
}
|
||||||
|
data = static_cast<const char *>(file_map);
|
||||||
|
close(fd); // no longer needed after mapping
|
||||||
|
}
|
||||||
|
|
||||||
|
simdjson_inline padded_memory_map::~padded_memory_map() noexcept {
|
||||||
|
if (data != nullptr) {
|
||||||
|
munmap(const_cast<char *>(data), size + simdjson::SIMDJSON_PADDING);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
simdjson_inline simdjson::padded_string_view padded_memory_map::view() const noexcept simdjson_lifetime_bound {
|
||||||
|
if(!is_valid()) {
|
||||||
|
return simdjson::padded_string_view(); // return an empty view if mapping failed
|
||||||
|
}
|
||||||
|
return simdjson::padded_string_view(data, size, size + simdjson::SIMDJSON_PADDING);
|
||||||
|
}
|
||||||
|
|
||||||
|
simdjson_inline bool padded_memory_map::is_valid() const noexcept {
|
||||||
|
return data != nullptr;
|
||||||
|
}
|
||||||
|
#endif // _WIN32
|
||||||
|
|
||||||
} // namespace simdjson
|
} // namespace simdjson
|
||||||
|
|
||||||
inline simdjson::padded_string operator ""_padded(const char *str, size_t len) {
|
inline simdjson::padded_string operator ""_padded(const char *str, size_t len) {
|
||||||
@@ -376,4 +445,5 @@ inline simdjson::padded_string operator ""_padded(const char8_t *str, size_t len
|
|||||||
return simdjson::padded_string(reinterpret_cast<const char *>(str), len);
|
return simdjson::padded_string(reinterpret_cast<const char *>(str), len);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // SIMDJSON_PADDED_STRING_INL_H
|
#endif // SIMDJSON_PADDED_STRING_INL_H
|
||||||
|
|||||||
@@ -277,6 +277,62 @@ inline std::ostream& operator<<(std::ostream& out, const padded_string& s) { ret
|
|||||||
inline std::ostream& operator<<(std::ostream& out, simdjson_result<padded_string> &s) noexcept(false) { return out << s.value(); }
|
inline std::ostream& operator<<(std::ostream& out, simdjson_result<padded_string> &s) noexcept(false) { return out << s.value(); }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
/**
|
||||||
|
* A class representing a memory-mapped file with padding.
|
||||||
|
* It is only available on non-Windows platforms, as Windows has different APIs for memory mapping.
|
||||||
|
*/
|
||||||
|
class padded_memory_map {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Create a new padded memory map for the given file.
|
||||||
|
* After creating the memory map, you can call view() to get a padded_string_view of the file content.
|
||||||
|
* The memory map will be automatically released when the padded_memory_map instance is destroyed.
|
||||||
|
* Note that the file content is not copied, so this is efficient for large files. However,
|
||||||
|
* the file must remain unchanged while the memory map is in use. In case of error (e.g., file not found,
|
||||||
|
* permission denied, etc.), the memory map will be invalid and view() will return an empty view.
|
||||||
|
* You can check if the memory map is valid by calling is_valid() before using view().
|
||||||
|
*
|
||||||
|
* @param filename the path to the file to memory-map.
|
||||||
|
*/
|
||||||
|
simdjson_inline padded_memory_map(const char *filename) noexcept;
|
||||||
|
/**
|
||||||
|
* Destroy the padded memory map and release any resources.
|
||||||
|
*/
|
||||||
|
simdjson_inline ~padded_memory_map() noexcept;
|
||||||
|
|
||||||
|
// lifetime of the view is tied to the memory map, so we can return a view
|
||||||
|
// directly
|
||||||
|
/**
|
||||||
|
* Get a view of the memory-mapped file. It always succeeds, but the view may be empty
|
||||||
|
* if the memory map is invalid (e.g., due to file not found, permission denied, etc.).
|
||||||
|
* You can check if the memory map is valid by calling is_valid() before using the view.
|
||||||
|
*
|
||||||
|
* Lifetime of the view is tied to the memory map, so the view should not be used after the
|
||||||
|
* padded_memory_map instance is destroyed.
|
||||||
|
*
|
||||||
|
* @return a padded_string_view representing the memory-mapped file, or an empty view if the memory map is invalid.
|
||||||
|
*/
|
||||||
|
simdjson_inline simdjson::padded_string_view view() const noexcept simdjson_lifetime_bound;
|
||||||
|
/**
|
||||||
|
* Check if the memory map is valid.
|
||||||
|
*
|
||||||
|
* @return true if the memory map is valid, false otherwise.
|
||||||
|
*/
|
||||||
|
simdjson_inline bool is_valid() const noexcept;
|
||||||
|
|
||||||
|
private:
|
||||||
|
padded_memory_map() = delete;
|
||||||
|
padded_memory_map(const padded_memory_map &) = delete;
|
||||||
|
padded_memory_map &operator=(const padded_memory_map &) = delete;
|
||||||
|
const char *data{nullptr};
|
||||||
|
size_t size{0};
|
||||||
|
};
|
||||||
|
#endif // _WIN32
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace simdjson
|
} // namespace simdjson
|
||||||
|
|
||||||
// This is deliberately outside of simdjson so that people get it without having to use the namespace
|
// This is deliberately outside of simdjson so that people get it without having to use the namespace
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ namespace simdjson {
|
|||||||
*/
|
*/
|
||||||
class padded_string_view : public std::string_view {
|
class padded_string_view : public std::string_view {
|
||||||
private:
|
private:
|
||||||
size_t _capacity;
|
size_t _capacity{0};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/** Create an empty padded_string_view. */
|
/** Create an empty padded_string_view. */
|
||||||
|
|||||||
@@ -66,6 +66,25 @@ using std::size_t;
|
|||||||
#define SIMDJSON_IS_LASX 1 // We can always run both
|
#define SIMDJSON_IS_LASX 1 // We can always run both
|
||||||
#elif defined(__loongarch_sx)
|
#elif defined(__loongarch_sx)
|
||||||
#define SIMDJSON_IS_LSX 1
|
#define SIMDJSON_IS_LSX 1
|
||||||
|
|
||||||
|
// Adjust for runtime dispatching support.
|
||||||
|
#if defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER) && !defined(__NVCOMPILER)
|
||||||
|
#if __GNUC__ > 15 || (__GNUC__ == 15 && __GNUC_MINOR__ >= 0)
|
||||||
|
// We are ok, we will support runtime dispatch for LASX.
|
||||||
|
#else
|
||||||
|
// We disable runtime dispatch for LASX, which means that we will not be able to use LASX
|
||||||
|
// even if it is supported by the hardware.
|
||||||
|
// Loongson users should update to GCC 15 or better.
|
||||||
|
#define SIMDJSON_IMPLEMENTATION_LASX 0
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
// We are not using GCC, so we assume that we can support runtime dispatch for LASX.
|
||||||
|
// https://godbolt.org/z/jcMnrjYhs
|
||||||
|
#define SIMDJSON_IMPLEMENTATION_LASX 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
#elif defined(__PPC64__) || defined(_M_PPC64)
|
#elif defined(__PPC64__) || defined(_M_PPC64)
|
||||||
#define SIMDJSON_IS_PPC64 1
|
#define SIMDJSON_IS_PPC64 1
|
||||||
|
|||||||
@@ -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.2.4"
|
#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 = 2,
|
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 = 4
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
+7070
-95
File diff suppressed because it is too large
Load Diff
+26009
-593
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
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ link_libraries(simdjson)
|
|||||||
add_cpp_test(unicode_tests LABELS dom acceptance per_implementation)
|
add_cpp_test(unicode_tests LABELS dom acceptance per_implementation)
|
||||||
add_cpp_test(minify_tests LABELS other acceptance per_implementation)
|
add_cpp_test(minify_tests LABELS other acceptance per_implementation)
|
||||||
add_cpp_test(padded_string_tests LABELS other acceptance )
|
add_cpp_test(padded_string_tests LABELS other acceptance )
|
||||||
|
add_cpp_test(memory_map_tests LABELS other acceptance )
|
||||||
add_cpp_test(prettify_tests LABELS other acceptance per_implementation)
|
add_cpp_test(prettify_tests LABELS other acceptance per_implementation)
|
||||||
add_cpp_test(fractured_json_tests LABELS other acceptance per_implementation)
|
add_cpp_test(fractured_json_tests LABELS other acceptance per_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 {
|
||||||
|
|||||||
@@ -25,3 +25,8 @@ if (SIMDJSON_EXCEPTIONS)
|
|||||||
add_dual_compile_test(dangling_parser_parse_padstring)
|
add_dual_compile_test(dangling_parser_parse_padstring)
|
||||||
add_dual_compile_test(unsafe_parse_many)
|
add_dual_compile_test(unsafe_parse_many)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(NOT BUILD_SHARED_LIBS)
|
||||||
|
# We only check that it builds
|
||||||
|
add_subdirectory(multiple_include)
|
||||||
|
endif()
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
add_library(mylib mylib.cpp)
|
||||||
|
target_link_libraries(mylib PUBLIC simdjson::simdjson)
|
||||||
|
target_include_directories(mylib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
add_executable(myexe main.cpp)
|
||||||
|
target_link_libraries(myexe PRIVATE mylib)
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
#include "mylib.h"
|
||||||
|
#include <simdjson.h>
|
||||||
|
#include <iostream>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
simdjson::padded_string json = R"([ 1, 2, 3, 4 ])"_padded;
|
||||||
|
simdjson::padded_string minified = minify_json(json);
|
||||||
|
std::cout << "Minified: " << std::string_view(minified) << std::endl;
|
||||||
|
|
||||||
|
// Also directly use minify
|
||||||
|
size_t length = json.size();
|
||||||
|
std::unique_ptr<char[]> buffer{new char[length]};
|
||||||
|
size_t new_length{};
|
||||||
|
auto error = simdjson::minify(json.data(), length, buffer.get(), new_length);
|
||||||
|
if (error) {
|
||||||
|
std::cerr << "Error: " << simdjson::error_message(error) << std::endl;
|
||||||
|
} else {
|
||||||
|
std::cout << "Direct minified: " << std::string(buffer.get(), new_length) << std::endl;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
#include "mylib.h"
|
||||||
|
#include <simdjson.h>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
simdjson::padded_string minify_json(const simdjson::padded_string& json) {
|
||||||
|
size_t length = json.size();
|
||||||
|
std::unique_ptr<char[]> buffer{new char[length]};
|
||||||
|
size_t new_length{};
|
||||||
|
auto error = simdjson::minify(json.data(), length, buffer.get(), new_length);
|
||||||
|
if (error) {
|
||||||
|
return simdjson::padded_string();
|
||||||
|
}
|
||||||
|
return simdjson::padded_string(std::string_view(buffer.get(), new_length));
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
#ifndef MYLIB_H
|
||||||
|
#define MYLIB_H
|
||||||
|
|
||||||
|
#include <simdjson.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
simdjson::padded_string minify_json(const simdjson::padded_string& json);
|
||||||
|
|
||||||
|
#endif // MYLIB_H
|
||||||
@@ -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;
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
#ifdef _WIN32
|
||||||
|
#include <cstdlib>
|
||||||
|
// This test is not supported on Windows because it relies on POSIX APIs like
|
||||||
|
// mmap. Please run it on a POSIX-compliant system.
|
||||||
|
int main() { return EXIT_SUCCESS; }
|
||||||
|
#else
|
||||||
|
|
||||||
|
#include "simdjson.h"
|
||||||
|
#include "test_macros.h"
|
||||||
|
|
||||||
|
#if SIMDJSON_EXCEPTIONS
|
||||||
|
bool test_memory_map_exception() {
|
||||||
|
TEST_START();
|
||||||
|
simdjson::padded_memory_map map(TWITTER_JSON);
|
||||||
|
ASSERT_TRUE(map.is_valid());
|
||||||
|
simdjson::padded_string_view view = map.view();
|
||||||
|
simdjson::ondemand::document doc = simdjson::ondemand::parser::get_parser().iterate(view);
|
||||||
|
ASSERT_TRUE(doc["search_metadata"]["count"].get_uint64() == 100);
|
||||||
|
TEST_SUCCEED();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool test_memory_map_noexception() {
|
||||||
|
TEST_START();
|
||||||
|
simdjson::padded_memory_map map(TWITTER_JSON);
|
||||||
|
if (!map.is_valid()) {
|
||||||
|
std::cerr << "Failed to memory-map the file " << TWITTER_JSON << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
simdjson::padded_string_view view = map.view();
|
||||||
|
simdjson::ondemand::parser parser;
|
||||||
|
simdjson::ondemand::document doc;
|
||||||
|
ASSERT_SUCCESS( parser.iterate(view).get(doc) );
|
||||||
|
uint64_t count;
|
||||||
|
ASSERT_SUCCESS( doc["search_metadata"]["count"].get(count) );
|
||||||
|
ASSERT_EQUAL(count, 100);
|
||||||
|
TEST_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
#if SIMDJSON_EXCEPTIONS
|
||||||
|
return (test_memory_map_exception() && test_memory_map_noexception()) ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||||
|
#else
|
||||||
|
return test_memory_map_noexception() ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -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() &&
|
||||||
|
|||||||
@@ -764,7 +764,7 @@ bool basics_1() {
|
|||||||
TEST_START();
|
TEST_START();
|
||||||
|
|
||||||
ondemand::parser parser;
|
ondemand::parser parser;
|
||||||
auto json = padded_string::load("twitter.json");
|
auto json = padded_string::load("twitter.json"); // this is a simdjson_result<padded_string>
|
||||||
ondemand::document doc = parser.iterate(json); // load and parse a file
|
ondemand::document doc = parser.iterate(json); // load and parse a file
|
||||||
|
|
||||||
simdjson_unused auto unused_doc = doc.get_object();
|
simdjson_unused auto unused_doc = doc.get_object();
|
||||||
|
|||||||
@@ -20,6 +20,26 @@ namespace twitter_tests {
|
|||||||
TEST_SUCCEED();
|
TEST_SUCCEED();
|
||||||
}
|
}
|
||||||
#if SIMDJSON_EXCEPTIONS
|
#if SIMDJSON_EXCEPTIONS
|
||||||
|
bool twitter_result_example() {
|
||||||
|
TEST_START();
|
||||||
|
simdjson_result<padded_string> json = padded_string::load(TWITTER_JSON);
|
||||||
|
ondemand::parser parser;
|
||||||
|
auto doc = parser.iterate(json);
|
||||||
|
for (ondemand::object tweet : doc["statuses"]) {
|
||||||
|
uint64_t id = tweet["id"];
|
||||||
|
std::string_view text = tweet["text"];
|
||||||
|
std::string_view screen_name = tweet["user"]["screen_name"];
|
||||||
|
uint64_t retweets = tweet["retweet_count"];
|
||||||
|
uint64_t favorites = tweet["favorite_count"];
|
||||||
|
(void) id;
|
||||||
|
(void) text;
|
||||||
|
(void) retweets;
|
||||||
|
(void) favorites;
|
||||||
|
(void) screen_name;
|
||||||
|
}
|
||||||
|
TEST_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
bool twitter_example() {
|
bool twitter_example() {
|
||||||
TEST_START();
|
TEST_START();
|
||||||
padded_string json;
|
padded_string json;
|
||||||
@@ -182,6 +202,7 @@ namespace twitter_tests {
|
|||||||
twitter_default_profile() &&
|
twitter_default_profile() &&
|
||||||
twitter_image_sizes() &&
|
twitter_image_sizes() &&
|
||||||
#if SIMDJSON_EXCEPTIONS
|
#if SIMDJSON_EXCEPTIONS
|
||||||
|
twitter_result_example() &&
|
||||||
twitter_count_exception() &&
|
twitter_count_exception() &&
|
||||||
twitter_example() &&
|
twitter_example() &&
|
||||||
twitter_default_profile_exception() &&
|
twitter_default_profile_exception() &&
|
||||||
|
|||||||
@@ -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