mirror of
https://github.com/simdjson/simdjson
synced 2026-06-08 17:27:07 +00:00
Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 16796797a8 | |||
| fb83b114ef | |||
| 542cd7af71 | |||
| 769364abb2 | |||
| f25d5f9fc2 | |||
| 12fb30ae9c | |||
| c0a952687d | |||
| 307ddd4415 | |||
| 21657455ed | |||
| afb1c9f4b1 | |||
| 9973f7b3a3 | |||
| 18d612df15 | |||
| bddb23177e | |||
| 2c5de6c6ed |
+97
-83
@@ -12,7 +12,7 @@ endif()
|
||||
project(
|
||||
simdjson
|
||||
# The version number is modified by tools/release.py
|
||||
VERSION 4.4.2
|
||||
VERSION 4.6.2
|
||||
DESCRIPTION "Parsing gigabytes of JSON per second"
|
||||
HOMEPAGE_URL "https://simdjson.org/"
|
||||
LANGUAGES CXX C
|
||||
@@ -29,8 +29,8 @@ string(
|
||||
# ---- Options, variables ----
|
||||
|
||||
# These version numbers are modified by tools/release.py
|
||||
set(SIMDJSON_LIB_VERSION "31.0.0" CACHE STRING "simdjson library version")
|
||||
set(SIMDJSON_LIB_SOVERSION "31" CACHE STRING "simdjson library soversion")
|
||||
set(SIMDJSON_LIB_VERSION "33.0.0" CACHE STRING "simdjson library version")
|
||||
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)
|
||||
if(SIMDJSON_BUILD_STATIC_LIB AND NOT BUILD_SHARED_LIBS)
|
||||
@@ -76,9 +76,12 @@ if(SIMDJSON_DEVELOPMENT_CHECKS)
|
||||
endif()
|
||||
|
||||
if(is_top_project)
|
||||
option(SIMDJSON_INSTALL "Enable target install" ON)
|
||||
option(SIMDJSON_DEVELOPER_MODE "Enable targets for developing simdjson" OFF)
|
||||
option(BUILD_SHARED_LIBS "Build simdjson as a shared library" OFF)
|
||||
option(SIMDJSON_SINGLEHEADER "Disable singleheader generation" ON)
|
||||
else()
|
||||
option(SIMDJSON_INSTALL "Enable target install" ${BUILD_SHARED_LIBS})
|
||||
endif()
|
||||
|
||||
include(cmake/handle-deprecations.cmake)
|
||||
@@ -92,13 +95,16 @@ add_library(simdjson ${SIMDJSON_SOURCES})
|
||||
add_library(simdjson::simdjson ALIAS 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
|
||||
if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.16")
|
||||
target_precompile_headers(simdjson PRIVATE
|
||||
set(SIMDJSON_PRECOMPILE_HEADERS
|
||||
<algorithm>
|
||||
<array>
|
||||
<atomic>
|
||||
<bit>
|
||||
<cassert>
|
||||
<cctype>
|
||||
<cerrno>
|
||||
@@ -111,6 +117,12 @@ if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.16")
|
||||
<utility>
|
||||
<vector>
|
||||
)
|
||||
|
||||
if(SIMDJSON_HAS_BIT_HEADER)
|
||||
list(APPEND SIMDJSON_PRECOMPILE_HEADERS <bit>)
|
||||
endif()
|
||||
|
||||
target_precompile_headers(simdjson PRIVATE ${SIMDJSON_PRECOMPILE_HEADERS})
|
||||
endif()
|
||||
|
||||
if(SIMDJSON_BUILD_STATIC_LIB)
|
||||
@@ -216,87 +228,89 @@ endif()
|
||||
|
||||
# ---- Install rules ----
|
||||
|
||||
include(CMakePackageConfigHelpers)
|
||||
include(GNUInstallDirs)
|
||||
if(SIMDJSON_INSTALL)
|
||||
include(CMakePackageConfigHelpers)
|
||||
include(GNUInstallDirs)
|
||||
|
||||
if(SIMDJSON_SINGLEHEADER)
|
||||
install(
|
||||
FILES singleheader/simdjson.h
|
||||
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
|
||||
COMPONENT simdjson_Development
|
||||
)
|
||||
if(SIMDJSON_SINGLEHEADER)
|
||||
install(
|
||||
FILES singleheader/simdjson.h
|
||||
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
|
||||
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()
|
||||
|
||||
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
|
||||
#
|
||||
|
||||
@@ -38,7 +38,7 @@ PROJECT_NAME = simdjson
|
||||
# could be handy for archiving the generated documentation or if some version
|
||||
# control system is used.
|
||||
|
||||
PROJECT_NUMBER = "4.4.2"
|
||||
PROJECT_NUMBER = "4.6.2"
|
||||
|
||||
# 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
|
||||
|
||||
+3
-3
@@ -436,7 +436,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:
|
||||
`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()`,
|
||||
`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 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,
|
||||
@@ -446,8 +446,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
|
||||
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).
|
||||
When calling `get_uint64()` and `get_int64()`, if the number does not fit in a corresponding
|
||||
64-bit integer type, it is also considered an error. When parsing numbers or other scalar values, the library checks
|
||||
When calling `get_uint64()`, `get_int64()`, `get_uint32()` or `get_int32()`, if the number does not fit in the
|
||||
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
|
||||
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.
|
||||
|
||||
|
||||
+18
-1
@@ -168,6 +168,23 @@ Once you have an element, you can navigate it with idiomatic C++ iterators, oper
|
||||
`SIMDJSON_MINUS_ZERO_AS_FLOAT` to `1` when building simdjson, you can get that `-0` is mapped to `-0.0`
|
||||
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`.
|
||||
* **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"]`.
|
||||
* **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) { ... }`
|
||||
@@ -180,7 +197,7 @@ Once you have an element, you can navigate it with idiomatic C++ iterators, oper
|
||||
* **Array and Object size** Given an array or an object, you can get its size (number of elements or keys)
|
||||
with the `size()` method.
|
||||
* **Checking an Element Type:** You can check an element's type with `element.type()`. It
|
||||
returns an `element_type` with values such as `simdjson::dom::element_type::ARRAY`, `simdjson::dom::element_type::OBJECT`, `simdjson::dom::element_type::INT64`, `simdjson::dom::element_type::UINT64`,`simdjson::dom::element_type::DOUBLE`, `simdjson::dom::element_type::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`).
|
||||
|
||||
### Examples
|
||||
|
||||
@@ -93,6 +93,14 @@ Float values are represented as two 64-bit tape elements:
|
||||
|
||||
Performance consideration: We store numbers of the main tape because we believe that locality of reference is helpful for performance.
|
||||
|
||||
## 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
|
||||
|
||||
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:
|
||||
os << "null" << endl;
|
||||
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) {
|
||||
|
||||
@@ -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
|
||||
// should we be hitting the root node?
|
||||
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:
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -81,6 +81,10 @@ simdjson_inline simdjson_result<bool> simdjson_result<dom::element>::get_bool()
|
||||
if (error()) { return error(); }
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
if (error()) { return error(); }
|
||||
@@ -218,6 +225,15 @@ inline simdjson_result<bool> element::get_bool() const noexcept {
|
||||
}
|
||||
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 {
|
||||
SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
|
||||
switch (tape.tape_ref_type()) {
|
||||
@@ -360,6 +376,10 @@ inline bool element::is_null() const noexcept {
|
||||
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
|
||||
|
||||
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";
|
||||
case element_type::NULL_VALUE:
|
||||
return out << "null";
|
||||
case element_type::BIGINT:
|
||||
return out << "bigint";
|
||||
default:
|
||||
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.
|
||||
STRING = '"', ///< std::string_view
|
||||
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;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
@@ -175,6 +184,11 @@ public:
|
||||
*/
|
||||
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).
|
||||
*
|
||||
@@ -533,6 +547,7 @@ public:
|
||||
simdjson_inline simdjson_result<uint64_t> get_uint64() const noexcept;
|
||||
simdjson_inline simdjson_result<double> get_double() 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_object() const noexcept;
|
||||
@@ -543,6 +558,7 @@ public:
|
||||
simdjson_inline bool is_number() const noexcept;
|
||||
simdjson_inline bool is_bool() 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[](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 {
|
||||
const std::string path_copy(path);
|
||||
// Open the file
|
||||
SIMDJSON_PUSH_DISABLE_WARNINGS
|
||||
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
|
||||
|
||||
if (fp == nullptr) {
|
||||
@@ -132,6 +133,7 @@ inline simdjson_result<element> parser::parse_into_document(document& provided_d
|
||||
buf += 3;
|
||||
len -= 3;
|
||||
}
|
||||
implementation->_number_as_string = _number_as_string;
|
||||
_error = implementation->parse(buf, len, provided_doc);
|
||||
|
||||
if (_error) { return _error; }
|
||||
|
||||
@@ -610,6 +610,13 @@ public:
|
||||
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:
|
||||
/**
|
||||
* The maximum document length this parser will automatically support.
|
||||
@@ -618,6 +625,9 @@ private:
|
||||
*/
|
||||
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)
|
||||
*/
|
||||
|
||||
@@ -460,6 +460,12 @@ inline void string_builder<serializer>::append(simdjson::dom::element value) {
|
||||
case tape_type::STRING:
|
||||
format.string(iter.get_string_view());
|
||||
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:
|
||||
format.number(iter.next_tape_value<int64_t>());
|
||||
iter.json_index++; // numbers take up 2 spots, so we need to increment
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
#include "simdjson/generic/ondemand/deserialize.h"
|
||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
#include <limits>
|
||||
|
||||
namespace simdjson {
|
||||
namespace SIMDJSON_IMPLEMENTATION {
|
||||
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 {
|
||||
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 {
|
||||
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<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<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<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(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(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(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(); }
|
||||
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 {
|
||||
if (error()) { return error(); }
|
||||
return first.get_double();
|
||||
@@ -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<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<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_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); }
|
||||
@@ -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<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<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<value> document_reference::get() & noexcept { return get_value(); }
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
@@ -879,6 +919,14 @@ simdjson_inline simdjson_result<int64_t> simdjson_result<SIMDJSON_IMPLEMENTATION
|
||||
if (error()) { return error(); }
|
||||
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 {
|
||||
if (error()) { return error(); }
|
||||
return first.get_double();
|
||||
|
||||
@@ -76,6 +76,26 @@ public:
|
||||
* @returns INCORRECT_TYPE If the JSON value is not a 64-bit integer.
|
||||
*/
|
||||
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.
|
||||
*
|
||||
@@ -829,6 +849,8 @@ public:
|
||||
simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
|
||||
simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
|
||||
simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
|
||||
simdjson_inline simdjson_result<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_in_string() noexcept;
|
||||
simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement = false) noexcept;
|
||||
@@ -982,6 +1004,8 @@ public:
|
||||
simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
|
||||
simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
|
||||
simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
|
||||
simdjson_inline simdjson_result<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_in_string() noexcept;
|
||||
simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement = false) noexcept;
|
||||
@@ -1069,6 +1093,8 @@ public:
|
||||
simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
|
||||
simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
|
||||
simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
|
||||
simdjson_inline simdjson_result<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_in_string() noexcept;
|
||||
simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement = false) 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 {
|
||||
if(max_capacity < dom::MINIMAL_DOCUMENT_CAPACITY) {
|
||||
if(max_capacity > dom::MINIMAL_DOCUMENT_CAPACITY) {
|
||||
_max_capacity = max_capacity;
|
||||
} else {
|
||||
_max_capacity = dom::MINIMAL_DOCUMENT_CAPACITY;
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
#include "simdjson/generic/ondemand/value.h"
|
||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
#include <limits>
|
||||
|
||||
namespace simdjson {
|
||||
namespace SIMDJSON_IMPLEMENTATION {
|
||||
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 {
|
||||
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 {
|
||||
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<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<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(); }
|
||||
|
||||
|
||||
@@ -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(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(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); }
|
||||
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
@@ -401,6 +419,14 @@ simdjson_inline simdjson_result<int64_t> simdjson_result<SIMDJSON_IMPLEMENTATION
|
||||
if (error()) { return error(); }
|
||||
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 {
|
||||
if (error()) { return error(); }
|
||||
return first.get_double();
|
||||
|
||||
@@ -161,6 +161,28 @@ public:
|
||||
*/
|
||||
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.
|
||||
*
|
||||
@@ -746,6 +768,8 @@ public:
|
||||
simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
|
||||
simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
|
||||
simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
|
||||
simdjson_inline simdjson_result<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_in_string() 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};
|
||||
|
||||
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.
|
||||
simdjson_inline dom_parser_implementation() noexcept;
|
||||
simdjson_inline dom_parser_implementation(dom_parser_implementation &&other) noexcept;
|
||||
|
||||
@@ -19,7 +19,8 @@ enum class tape_type {
|
||||
DOUBLE = 'd',
|
||||
TRUE_VALUE = 't',
|
||||
FALSE_VALUE = 'f',
|
||||
NULL_VALUE = 'n'
|
||||
NULL_VALUE = 'n',
|
||||
BIGINT = 'Z' // Big integer stored as string in string buffer
|
||||
}; // enum class tape_type
|
||||
|
||||
} // namespace internal
|
||||
|
||||
@@ -168,10 +168,13 @@ inline padded_string::operator padded_string_view() const noexcept simdjson_life
|
||||
}
|
||||
|
||||
inline simdjson_result<padded_string> padded_string::load(std::string_view filename) noexcept {
|
||||
// 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
|
||||
SIMDJSON_PUSH_DISABLE_WARNINGS
|
||||
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
|
||||
|
||||
if (fp == nullptr) {
|
||||
@@ -223,10 +226,13 @@ inline simdjson_result<padded_string> padded_string::load(std::string_view filen
|
||||
|
||||
#if defined(_WIN32) && SIMDJSON_CPLUSPLUS17
|
||||
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
|
||||
SIMDJSON_PUSH_DISABLE_WARNINGS
|
||||
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
|
||||
|
||||
if (fp == nullptr) {
|
||||
@@ -349,6 +355,9 @@ inline padded_string padded_string_builder::convert() noexcept {
|
||||
}
|
||||
|
||||
inline bool padded_string_builder::reserve(size_t additional) noexcept {
|
||||
if (simdjson_unlikely(additional + size < size)) {
|
||||
return false; // overflow: cannot satisfy request
|
||||
}
|
||||
size_t needed = size + additional;
|
||||
if (needed <= capacity) {
|
||||
return true;
|
||||
@@ -358,8 +367,9 @@ inline bool padded_string_builder::reserve(size_t additional) noexcept {
|
||||
// repeated allocations.
|
||||
if (new_capacity < 4096) {
|
||||
new_capacity *= 2;
|
||||
} else {
|
||||
new_capacity += new_capacity/2; // grow by 1.5x
|
||||
// overflow guard: ensure new_capacity + new_capacity/2 does not overflow
|
||||
} 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);
|
||||
if (new_data == nullptr) {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#define SIMDJSON_SIMDJSON_VERSION_H
|
||||
|
||||
/** The version of simdjson being used (major.minor.revision) */
|
||||
#define SIMDJSON_VERSION "4.4.2"
|
||||
#define SIMDJSON_VERSION "4.6.2"
|
||||
|
||||
namespace simdjson {
|
||||
enum {
|
||||
@@ -15,7 +15,7 @@ enum {
|
||||
/**
|
||||
* The minor version (major.MINOR.revision) of simdjson being used.
|
||||
*/
|
||||
SIMDJSON_VERSION_MINOR = 4,
|
||||
SIMDJSON_VERSION_MINOR = 6,
|
||||
/**
|
||||
* The revision (major.minor.REVISION) of simdjson being used.
|
||||
*/
|
||||
|
||||
+297
-11
@@ -1,4 +1,4 @@
|
||||
/* auto-generated on 2026-03-20 11:11:38 -0400. version 4.4.2 Do not edit! */
|
||||
/* auto-generated on 2026-04-03 15:26:12 -0400. version 4.6.2 Do not edit! */
|
||||
/* including simdjson.cpp: */
|
||||
/* begin file simdjson.cpp */
|
||||
#define SIMDJSON_SRC_SIMDJSON_CPP
|
||||
@@ -7308,6 +7308,12 @@ protected:
|
||||
*/
|
||||
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.
|
||||
simdjson_inline dom_parser_implementation() noexcept;
|
||||
simdjson_inline dom_parser_implementation(dom_parser_implementation &&other) noexcept;
|
||||
@@ -7883,7 +7889,8 @@ enum class tape_type {
|
||||
DOUBLE = 'd',
|
||||
TRUE_VALUE = 't',
|
||||
FALSE_VALUE = 'f',
|
||||
NULL_VALUE = 'n'
|
||||
NULL_VALUE = 'n',
|
||||
BIGINT = 'Z' // Big integer stored as string in string buffer
|
||||
}; // enum class tape_type
|
||||
|
||||
} // namespace internal
|
||||
@@ -14178,6 +14185,9 @@ struct tape_writer {
|
||||
/** Write a double value to tape. */
|
||||
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).
|
||||
*/
|
||||
@@ -14261,6 +14271,18 @@ simdjson_inline void tape_writer::write(uint64_t &tape_loc, uint64_t val, intern
|
||||
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
|
||||
} // unnamed namespace
|
||||
} // namespace arm64
|
||||
@@ -15198,7 +15220,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 {
|
||||
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 {
|
||||
@@ -20539,6 +20577,9 @@ struct tape_writer {
|
||||
/** Write a double value to tape. */
|
||||
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).
|
||||
*/
|
||||
@@ -20622,6 +20663,18 @@ simdjson_inline void tape_writer::write(uint64_t &tape_loc, uint64_t val, intern
|
||||
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
|
||||
} // unnamed namespace
|
||||
} // namespace haswell
|
||||
@@ -21559,7 +21612,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 {
|
||||
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 {
|
||||
@@ -26895,6 +26964,9 @@ struct tape_writer {
|
||||
/** Write a double value to tape. */
|
||||
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).
|
||||
*/
|
||||
@@ -26978,6 +27050,18 @@ simdjson_inline void tape_writer::write(uint64_t &tape_loc, uint64_t val, intern
|
||||
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
|
||||
} // unnamed namespace
|
||||
} // namespace icelake
|
||||
@@ -27915,7 +27999,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 {
|
||||
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 {
|
||||
@@ -33522,6 +33622,9 @@ struct tape_writer {
|
||||
/** Write a double value to tape. */
|
||||
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).
|
||||
*/
|
||||
@@ -33605,6 +33708,18 @@ simdjson_inline void tape_writer::write(uint64_t &tape_loc, uint64_t val, intern
|
||||
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
|
||||
} // unnamed namespace
|
||||
} // namespace ppc64
|
||||
@@ -34542,7 +34657,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 {
|
||||
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 {
|
||||
@@ -40711,6 +40842,9 @@ struct tape_writer {
|
||||
/** Write a double value to tape. */
|
||||
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).
|
||||
*/
|
||||
@@ -40794,6 +40928,18 @@ simdjson_inline void tape_writer::write(uint64_t &tape_loc, uint64_t val, intern
|
||||
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
|
||||
} // unnamed namespace
|
||||
} // namespace westmere
|
||||
@@ -41731,7 +41877,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 {
|
||||
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 {
|
||||
@@ -46931,6 +47093,9 @@ struct tape_writer {
|
||||
/** Write a double value to tape. */
|
||||
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).
|
||||
*/
|
||||
@@ -47014,6 +47179,18 @@ simdjson_inline void tape_writer::write(uint64_t &tape_loc, uint64_t val, intern
|
||||
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
|
||||
} // unnamed namespace
|
||||
} // namespace lasx
|
||||
@@ -47951,7 +48128,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 {
|
||||
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 {
|
||||
@@ -53055,6 +53248,9 @@ struct tape_writer {
|
||||
/** Write a double value to tape. */
|
||||
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).
|
||||
*/
|
||||
@@ -53138,6 +53334,18 @@ simdjson_inline void tape_writer::write(uint64_t &tape_loc, uint64_t val, intern
|
||||
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
|
||||
} // unnamed namespace
|
||||
} // namespace lsx
|
||||
@@ -54075,7 +54283,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 {
|
||||
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 {
|
||||
@@ -59598,6 +59822,9 @@ struct tape_writer {
|
||||
/** Write a double value to tape. */
|
||||
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).
|
||||
*/
|
||||
@@ -59681,6 +59908,18 @@ simdjson_inline void tape_writer::write(uint64_t &tape_loc, uint64_t val, intern
|
||||
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
|
||||
} // unnamed namespace
|
||||
} // namespace rvv_vls
|
||||
@@ -60618,7 +60857,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 {
|
||||
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 {
|
||||
@@ -64189,6 +64444,9 @@ struct tape_writer {
|
||||
/** Write a double value to tape. */
|
||||
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).
|
||||
*/
|
||||
@@ -64272,6 +64530,18 @@ simdjson_inline void tape_writer::write(uint64_t &tape_loc, uint64_t val, intern
|
||||
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
|
||||
} // unnamed namespace
|
||||
} // namespace fallback
|
||||
@@ -64455,7 +64725,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 {
|
||||
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 {
|
||||
|
||||
+1217
-19
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 {
|
||||
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 {
|
||||
|
||||
@@ -26,6 +26,9 @@ struct tape_writer {
|
||||
/** Write a double value to tape. */
|
||||
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).
|
||||
*/
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
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
|
||||
} // unnamed namespace
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
|
||||
@@ -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(extracting_values_example 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(json_path_tests 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();
|
||||
}
|
||||
|
||||
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() {
|
||||
TEST_START();
|
||||
dom::parser parser;
|
||||
@@ -136,6 +150,7 @@ namespace parser_load {
|
||||
&& parser_load_nonexistent()
|
||||
&& parser_load_many_nonexistent()
|
||||
&& padded_string_load_nonexistent()
|
||||
&& parser_load_string_view_subpath()
|
||||
&& parser_load_chain()
|
||||
&& parser_load_many_chain()
|
||||
&& parser_parse_many_documents_error_in_the_middle()
|
||||
|
||||
@@ -273,6 +273,9 @@ namespace treewalk_1 {
|
||||
case dom::element_type::NULL_VALUE:
|
||||
cout << "null" << endl;
|
||||
break;
|
||||
case dom::element_type::BIGINT:
|
||||
cout << element.get_bigint().value_unsafe() << endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -884,6 +884,30 @@ namespace document_stream_tests {
|
||||
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() {
|
||||
TEST_START();
|
||||
auto json = R"( 133 badstuff )"_padded;
|
||||
@@ -931,6 +955,8 @@ namespace document_stream_tests {
|
||||
string_with_trailing() &&
|
||||
uint64_with_trailing() &&
|
||||
int64_with_trailing() &&
|
||||
uint32_with_trailing() &&
|
||||
int32_with_trailing() &&
|
||||
bool_with_trailing() &&
|
||||
null_with_trailing() &&
|
||||
truncated_utf8() &&
|
||||
|
||||
@@ -171,6 +171,17 @@ namespace error_tests {
|
||||
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() {
|
||||
TEST_START();
|
||||
ondemand::parser parser;
|
||||
@@ -212,7 +223,11 @@ namespace error_tests {
|
||||
ASSERT_ERROR( val.get_double(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_uint64(), 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_int32(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_uint32(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_int64(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_uint64(), 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_uint64(), 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_int32(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_uint32(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_int64(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_uint64(), 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_uint64(), 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_int32(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_uint32(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_int64(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_uint64(), 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_uint64(), 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_int32(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_uint32(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_int64(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_uint64(), 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_uint64(), 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_int32(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_uint32(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_int64(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_uint64(), 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_uint64(), 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_int32(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_uint32(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_int64(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_uint64(), 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_uint64(), 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_int32(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_uint32(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_int64(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_uint64(), 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_uint64(), 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_int32(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_uint32(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_int64(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_uint64(), INCORRECT_TYPE );
|
||||
ASSERT_ERROR( val.get_double(), INCORRECT_TYPE );
|
||||
@@ -432,6 +475,7 @@ namespace error_tests {
|
||||
raw_json_string_error() &&
|
||||
empty_document_error() &&
|
||||
parser_max_capacity() &&
|
||||
parser_set_max_capacity() &&
|
||||
get_fail_then_succeed_bool() &&
|
||||
get_fail_then_succeed_null() &&
|
||||
simple_error_example() &&
|
||||
|
||||
@@ -545,8 +545,111 @@ namespace number_tests {
|
||||
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() {
|
||||
return minus_zero() &&
|
||||
return get_int32_values() &&
|
||||
get_uint32_values() &&
|
||||
minus_zero() &&
|
||||
gigantic_big_int() &&
|
||||
big_int_not_zero() &&
|
||||
negative_big_int() &&
|
||||
|
||||
Reference in New Issue
Block a user