diff options
author | robot-contrib <robot-contrib@yandex-team.com> | 2024-12-08 19:25:55 +0300 |
---|---|---|
committer | robot-contrib <robot-contrib@yandex-team.com> | 2024-12-08 19:46:16 +0300 |
commit | 693f03f7f9738d7e7a68f03477725f24dfd3d2b6 (patch) | |
tree | b6d0ceba9765598d4e9f7dd8d26bf4746854d988 /contrib/libs/simdjson/include | |
parent | 2d3a24a6684d588b572cc791c2cacaca3e5146e8 (diff) | |
download | ydb-693f03f7f9738d7e7a68f03477725f24dfd3d2b6.tar.gz |
Update contrib/libs/simdjson to 3.11.1
commit_hash:14237b152d8d41e7d920835693370e646b91ae42
Diffstat (limited to 'contrib/libs/simdjson/include')
42 files changed, 1011 insertions, 122 deletions
diff --git a/contrib/libs/simdjson/include/simdjson.h b/contrib/libs/simdjson/include/simdjson.h index f77ab12b3e..194435f520 100644 --- a/contrib/libs/simdjson/include/simdjson.h +++ b/contrib/libs/simdjson/include/simdjson.h @@ -53,5 +53,4 @@ #include "simdjson/dom.h" #include "simdjson/ondemand.h" - #endif // SIMDJSON_H diff --git a/contrib/libs/simdjson/include/simdjson/arm64/bitmanipulation.h b/contrib/libs/simdjson/include/simdjson/arm64/bitmanipulation.h index 019869b1b0..fc51beafae 100644 --- a/contrib/libs/simdjson/include/simdjson/arm64/bitmanipulation.h +++ b/contrib/libs/simdjson/include/simdjson/arm64/bitmanipulation.h @@ -19,7 +19,7 @@ SIMDJSON_NO_SANITIZE_UNDEFINED // See issue https://github.com/simdjson/simdjson/issues/1965 SIMDJSON_NO_SANITIZE_MEMORY simdjson_inline int trailing_zeroes(uint64_t input_num) { -#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO +#if SIMDJSON_REGULAR_VISUAL_STUDIO unsigned long ret; // Search the mask data from least significant bit (LSB) // to the most significant bit (MSB) for a set bit (1). @@ -35,9 +35,15 @@ simdjson_inline uint64_t clear_lowest_bit(uint64_t input_num) { return input_num & (input_num-1); } +// We sometimes call leading_zeroes on inputs that are zero, +// but the algorithms do not end up using the returned value. +// Sadly, sanitizers are not smart enough to figure it out. +// Applies only when SIMDJSON_PREFER_REVERSE_BITS is defined and true. +// (See below.) +SIMDJSON_NO_SANITIZE_UNDEFINED /* result might be undefined when input_num is zero */ simdjson_inline int leading_zeroes(uint64_t input_num) { -#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO +#if SIMDJSON_REGULAR_VISUAL_STUDIO unsigned long leading_zero = 0; // Search the mask data from most significant bit (MSB) // to least significant bit (LSB) for a set bit (1). @@ -90,7 +96,7 @@ simdjson_inline uint64_t zero_leading_bit(uint64_t rev_bits, int leading_zeroes) #endif simdjson_inline bool add_overflow(uint64_t value1, uint64_t value2, uint64_t *result) { -#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO +#if SIMDJSON_REGULAR_VISUAL_STUDIO *result = value1 + value2; return *result < value1; #else diff --git a/contrib/libs/simdjson/include/simdjson/arm64/numberparsing_defs.h b/contrib/libs/simdjson/include/simdjson/arm64/numberparsing_defs.h index f5e85b7477..a765cb9a42 100644 --- a/contrib/libs/simdjson/include/simdjson/arm64/numberparsing_defs.h +++ b/contrib/libs/simdjson/include/simdjson/arm64/numberparsing_defs.h @@ -51,6 +51,12 @@ simdjson_inline internal::value128 full_multiplication(uint64_t value1, uint64_t } // namespace arm64 } // namespace simdjson +#ifndef SIMDJSON_SWAR_NUMBER_PARSING +#if SIMDJSON_IS_BIG_ENDIAN +#define SIMDJSON_SWAR_NUMBER_PARSING 0 +#else #define SIMDJSON_SWAR_NUMBER_PARSING 1 +#endif +#endif #endif // SIMDJSON_ARM64_NUMBERPARSING_DEFS_H diff --git a/contrib/libs/simdjson/include/simdjson/arm64/simd.h b/contrib/libs/simdjson/include/simdjson/arm64/simd.h index 3b0fa844f4..3881e7db7a 100644 --- a/contrib/libs/simdjson/include/simdjson/arm64/simd.h +++ b/contrib/libs/simdjson/include/simdjson/arm64/simd.h @@ -12,7 +12,7 @@ namespace arm64 { namespace { namespace simd { -#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO +#if SIMDJSON_REGULAR_VISUAL_STUDIO namespace { // Start of private section with Visual Studio workaround @@ -121,7 +121,7 @@ namespace { // We return uint32_t instead of uint16_t because that seems to be more efficient for most // purposes (cutting it down to uint16_t costs performance in some compilers). simdjson_inline uint32_t to_bitmask() const { -#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO +#if SIMDJSON_REGULAR_VISUAL_STUDIO const uint8x16_t bit_mask = simdjson_make_uint8x16_t(0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80); #else @@ -152,7 +152,7 @@ namespace { // Splat constructor simdjson_inline simd8(uint8_t _value) : simd8(splat(_value)) {} // Member-by-member initialization -#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO +#if SIMDJSON_REGULAR_VISUAL_STUDIO simdjson_inline simd8( uint8_t v0, uint8_t v1, uint8_t v2, uint8_t v3, uint8_t v4, uint8_t v5, uint8_t v6, uint8_t v7, uint8_t v8, uint8_t v9, uint8_t v10, uint8_t v11, uint8_t v12, uint8_t v13, uint8_t v14, uint8_t v15 @@ -246,7 +246,7 @@ namespace { uint64x2_t shufmask64 = {thintable_epi8[mask1], thintable_epi8[mask2]}; uint8x16_t shufmask = vreinterpretq_u8_u64(shufmask64); // we increment by 0x08 the second half of the mask -#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO +#if SIMDJSON_REGULAR_VISUAL_STUDIO uint8x16_t inc = simdjson_make_uint8x16_t(0, 0, 0, 0, 0, 0, 0, 0, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08); #else uint8x16_t inc = {0, 0, 0, 0, 0, 0, 0, 0, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08}; @@ -276,7 +276,7 @@ namespace { uint8x8_t compactmask1 = vcreate_u8(thintable_epi8[mask1]); uint8x8_t compactmask2 = vcreate_u8(thintable_epi8[mask2]); // we increment by 0x08 the second half of the mask -#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO +#if SIMDJSON_REGULAR_VISUAL_STUDIO uint8x8_t inc = simdjson_make_uint8x8_t(0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08); #else uint8x8_t inc = {0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08}; @@ -328,7 +328,7 @@ namespace { // Array constructor simdjson_inline simd8(const int8_t* values) : simd8(load(values)) {} // Member-by-member initialization -#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO +#if SIMDJSON_REGULAR_VISUAL_STUDIO simdjson_inline simd8( int8_t v0, int8_t v1, int8_t v2, int8_t v3, int8_t v4, int8_t v5, int8_t v6, int8_t v7, int8_t v8, int8_t v9, int8_t v10, int8_t v11, int8_t v12, int8_t v13, int8_t v14, int8_t v15 @@ -449,7 +449,7 @@ namespace { } simdjson_inline uint64_t to_bitmask() const { -#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO +#if SIMDJSON_REGULAR_VISUAL_STUDIO const uint8x16_t bit_mask = simdjson_make_uint8x16_t( 0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80 diff --git a/contrib/libs/simdjson/include/simdjson/base.h b/contrib/libs/simdjson/include/simdjson/base.h index a73b84bd08..e6e2ab9bfe 100644 --- a/contrib/libs/simdjson/include/simdjson/base.h +++ b/contrib/libs/simdjson/include/simdjson/base.h @@ -9,6 +9,7 @@ #include "simdjson/compiler_check.h" #include "simdjson/error.h" #include "simdjson/portability.h" +#include "simdjson/concepts.h" /** * @brief The top level simdjson namespace, containing everything the library provides. diff --git a/contrib/libs/simdjson/include/simdjson/compiler_check.h b/contrib/libs/simdjson/include/simdjson/compiler_check.h index 1d0d03d154..848fdddf0e 100644 --- a/contrib/libs/simdjson/include/simdjson/compiler_check.h +++ b/contrib/libs/simdjson/include/simdjson/compiler_check.h @@ -50,4 +50,16 @@ #endif #endif +#ifdef __has_include +#if __has_include(<version>) +#include <version> +#endif +#endif + +#ifdef __cpp_concepts +#include <utility> +#define SIMDJSON_SUPPORTS_DESERIALIZATION 1 +#else // __cpp_concepts +#define SIMDJSON_SUPPORTS_DESERIALIZATION 0 +#endif #endif // SIMDJSON_COMPILER_CHECK_H diff --git a/contrib/libs/simdjson/include/simdjson/concepts.h b/contrib/libs/simdjson/include/simdjson/concepts.h new file mode 100644 index 0000000000..494d2d294e --- /dev/null +++ b/contrib/libs/simdjson/include/simdjson/concepts.h @@ -0,0 +1,113 @@ +#ifndef SIMDJSON_CONCEPTS_H +#define SIMDJSON_CONCEPTS_H +#if SIMDJSON_SUPPORTS_DESERIALIZATION + +#include <concepts> +#include <type_traits> + +namespace simdjson { +namespace concepts { + +namespace details { +#define SIMDJSON_IMPL_CONCEPT(name, method) \ + template <typename T> \ + concept supports_##name = !std::is_const_v<T> && requires { \ + typename std::remove_cvref_t<T>::value_type; \ + requires requires(typename std::remove_cvref_t<T>::value_type &&val, \ + T obj) { \ + obj.method(std::move(val)); \ + requires !requires { obj = std::move(val); }; \ + }; \ + }; + +SIMDJSON_IMPL_CONCEPT(emplace_back, emplace_back); +SIMDJSON_IMPL_CONCEPT(emplace, emplace); +SIMDJSON_IMPL_CONCEPT(push_back, push_back); +SIMDJSON_IMPL_CONCEPT(add, add); +SIMDJSON_IMPL_CONCEPT(push, push); +SIMDJSON_IMPL_CONCEPT(append, append); +SIMDJSON_IMPL_CONCEPT(insert, insert); +SIMDJSON_IMPL_CONCEPT(op_append, operator+=); + +#undef SIMDJSON_IMPL_CONCEPT +} // namespace details + +/// Check if T is a container that we can append to, including: +/// std::vector, std::deque, std::list, std::string, ... +template <typename T> +concept appendable_containers = + details::supports_emplace_back<T> || details::supports_emplace<T> || + details::supports_push_back<T> || details::supports_push<T> || + details::supports_add<T> || details::supports_append<T> || + details::supports_insert<T>; + +/// Insert into the container however possible +template <appendable_containers T, typename... Args> +constexpr decltype(auto) emplace_one(T &vec, Args &&...args) { + if constexpr (details::supports_emplace_back<T>) { + return vec.emplace_back(std::forward<Args>(args)...); + } else if constexpr (details::supports_emplace<T>) { + return vec.emplace(std::forward<Args>(args)...); + } else if constexpr (details::supports_push_back<T>) { + return vec.push_back(std::forward<Args>(args)...); + } else if constexpr (details::supports_push<T>) { + return vec.push(std::forward<Args>(args)...); + } else if constexpr (details::supports_add<T>) { + return vec.add(std::forward<Args>(args)...); + } else if constexpr (details::supports_append<T>) { + return vec.append(std::forward<Args>(args)...); + } else if constexpr (details::supports_insert<T>) { + return vec.insert(std::forward<Args>(args)...); + } else if constexpr (details::supports_op_append<T> && sizeof...(Args) == 1) { + return vec.operator+=(std::forward<Args>(args)...); + } else { + static_assert(!sizeof(T *), + "We don't know how to add things to this container"); + } +} + +/// This checks if the container will return a reference to the newly added +/// element after an insert which for example `std::vector::emplace_back` does +/// since C++17; this will allow some optimizations. +template <typename T> +concept returns_reference = appendable_containers<T> && requires { + typename std::remove_cvref_t<T>::reference; + requires requires(typename std::remove_cvref_t<T>::value_type &&val, T obj) { + { + emplace_one(obj, std::move(val)) + } -> std::same_as<typename std::remove_cvref_t<T>::reference>; + }; +}; + +template <typename T> +concept smart_pointer = requires(std::remove_cvref_t<T> ptr) { + // Check if T has a member type named element_type + typename std::remove_cvref_t<T>::element_type; + + // Check if T has a get() member function + { + ptr.get() + } -> std::same_as<typename std::remove_cvref_t<T>::element_type *>; + + // Check if T can be dereferenced + { *ptr } -> std::same_as<typename std::remove_cvref_t<T>::element_type &>; +}; + +template <typename T> +concept optional_type = requires(std::remove_cvref_t<T> obj) { + typename std::remove_cvref_t<T>::value_type; + { obj.value() } -> std::same_as<typename std::remove_cvref_t<T>::value_type&>; + requires requires(typename std::remove_cvref_t<T>::value_type &&val) { + obj.emplace(std::move(val)); + obj = std::move(val); + { + obj.value_or(val) + } -> std::convertible_to<typename std::remove_cvref_t<T>::value_type>; + }; + { static_cast<bool>(obj) } -> std::same_as<bool>; // convertible to bool +}; + +} // namespace concepts +} // namespace simdjson +#endif // SIMDJSON_SUPPORTS_DESERIALIZATION +#endif // SIMDJSON_CONCEPTS_H diff --git a/contrib/libs/simdjson/include/simdjson/dom/array-inl.h b/contrib/libs/simdjson/include/simdjson/dom/array-inl.h index 6a29ef8553..f0b587dc6e 100644 --- a/contrib/libs/simdjson/include/simdjson/dom/array-inl.h +++ b/contrib/libs/simdjson/include/simdjson/dom/array-inl.h @@ -7,6 +7,7 @@ #include "simdjson/dom/array.h" #include "simdjson/dom/element.h" #include "simdjson/error-inl.h" +#include "simdjson/jsonpathutil.h" #include "simdjson/internal/tape_ref-inl.h" #include <limits> @@ -44,6 +45,13 @@ inline simdjson_result<dom::element> simdjson_result<dom::array>::at_pointer(std if (error()) { return error(); } return first.at_pointer(json_pointer); } + + inline simdjson_result<dom::element> simdjson_result<dom::array>::at_path(std::string_view json_path) const noexcept { + auto json_pointer = json_path_to_pointer_conversion(json_path); + if (json_pointer == "-1") { return INVALID_JSON_POINTER; } + return at_pointer(json_pointer); + } + inline simdjson_result<dom::element> simdjson_result<dom::array>::at(size_t index) const noexcept { if (error()) { return error(); } return first.at(index); @@ -113,6 +121,12 @@ inline simdjson_result<element> array::at_pointer(std::string_view json_pointer) return child; } +inline simdjson_result<element> array::at_path(std::string_view json_path) const noexcept { + auto json_pointer = json_path_to_pointer_conversion(json_path); + if (json_pointer == "-1") { return INVALID_JSON_POINTER; } + return at_pointer(json_pointer); +} + inline simdjson_result<element> array::at(size_t index) const noexcept { SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914 size_t i=0; diff --git a/contrib/libs/simdjson/include/simdjson/dom/array.h b/contrib/libs/simdjson/include/simdjson/dom/array.h index a90813a450..f54e3bc19e 100644 --- a/contrib/libs/simdjson/include/simdjson/dom/array.h +++ b/contrib/libs/simdjson/include/simdjson/dom/array.h @@ -109,6 +109,21 @@ public: inline simdjson_result<element> at_pointer(std::string_view json_pointer) const noexcept; /** + * Get the value associated with the given JSONPath expression. We only support + * JSONPath queries that trivially convertible to JSON Pointer queries: key + * names and array indices. + * + * https://datatracker.ietf.org/doc/html/draft-normington-jsonpath-00 + * + * @return The value associated with the given JSONPath expression, or: + * - INVALID_JSON_POINTER if the JSONPath to JSON Pointer conversion fails + * - NO_SUCH_FIELD if a field does not exist in an object + * - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length + * - INCORRECT_TYPE if a non-integer is used to access an array + */ + inline simdjson_result<element> at_path(std::string_view json_path) const noexcept; + + /** * Get the value at the given index. This function has linear-time complexity and * is equivalent to the following: * @@ -152,6 +167,7 @@ public: simdjson_inline simdjson_result(error_code error) noexcept; ///< @private inline simdjson_result<dom::element> at_pointer(std::string_view json_pointer) const noexcept; + inline simdjson_result<dom::element> at_path(std::string_view json_path) const noexcept; inline simdjson_result<dom::element> at(size_t index) const noexcept; #if SIMDJSON_EXCEPTIONS diff --git a/contrib/libs/simdjson/include/simdjson/dom/element-inl.h b/contrib/libs/simdjson/include/simdjson/dom/element-inl.h index cab313beb9..1466609c2b 100644 --- a/contrib/libs/simdjson/include/simdjson/dom/element-inl.h +++ b/contrib/libs/simdjson/include/simdjson/dom/element-inl.h @@ -9,6 +9,7 @@ #include "simdjson/dom/object-inl.h" #include "simdjson/error-inl.h" +#include "simdjson/jsonpathutil.h" #include <ostream> #include <limits> @@ -122,6 +123,11 @@ simdjson_inline simdjson_result<dom::element> simdjson_result<dom::element>::at_ if (error()) { return error(); } return first.at_pointer(json_pointer); } +simdjson_inline simdjson_result<dom::element> simdjson_result<dom::element>::at_path(const std::string_view json_path) const noexcept { + auto json_pointer = json_path_to_pointer_conversion(json_path); + if (json_pointer == "-1") { return INVALID_JSON_POINTER; } + return at_pointer(json_pointer); +} #ifndef SIMDJSON_DISABLE_DEPRECATED_API [[deprecated("For standard compliance, use at_pointer instead, and prefix your pointers with a slash '/', see RFC6901 ")]] simdjson_inline simdjson_result<dom::element> simdjson_result<dom::element>::at(const std::string_view json_pointer) const noexcept { @@ -412,6 +418,11 @@ inline simdjson_result<element> element::at_pointer(std::string_view json_pointe } } } +inline simdjson_result<element> element::at_path(std::string_view json_path) const noexcept { + auto json_pointer = json_path_to_pointer_conversion(json_path); + if (json_pointer == "-1") { return INVALID_JSON_POINTER; } + return at_pointer(json_pointer); +} #ifndef SIMDJSON_DISABLE_DEPRECATED_API [[deprecated("For standard compliance, use at_pointer instead, and prefix your pointers with a slash '/', see RFC6901 ")]] inline simdjson_result<element> element::at(std::string_view json_pointer) const noexcept { diff --git a/contrib/libs/simdjson/include/simdjson/dom/element.h b/contrib/libs/simdjson/include/simdjson/dom/element.h index 732b89e41a..d39c835763 100644 --- a/contrib/libs/simdjson/include/simdjson/dom/element.h +++ b/contrib/libs/simdjson/include/simdjson/dom/element.h @@ -372,6 +372,8 @@ public: * - INCORRECT_TYPE if this is not an object */ inline simdjson_result<element> operator[](const char *key) const noexcept; + simdjson_result<element> operator[](int) const noexcept = delete; + /** * Get the value associated with the given JSON pointer. We use the RFC 6901 @@ -397,6 +399,21 @@ public: */ inline simdjson_result<element> at_pointer(const std::string_view json_pointer) const noexcept; + /** + * Get the value associated with the given JSONPath expression. We only support + * JSONPath queries that trivially convertible to JSON Pointer queries: key + * names and array indices. + * + * https://datatracker.ietf.org/doc/html/draft-normington-jsonpath-00 + * + * @return The value associated with the given JSONPath expression, or: + * - INVALID_JSON_POINTER if the JSONPath to JSON Pointer conversion fails + * - NO_SUCH_FIELD if a field does not exist in an object + * - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length + * - INCORRECT_TYPE if a non-integer is used to access an array + */ + inline simdjson_result<element> at_path(std::string_view json_path) const noexcept; + #ifndef SIMDJSON_DISABLE_DEPRECATED_API /** * @@ -525,7 +542,9 @@ public: simdjson_inline simdjson_result<dom::element> operator[](std::string_view key) const noexcept; simdjson_inline simdjson_result<dom::element> operator[](const char *key) const noexcept; + simdjson_result<dom::element> operator[](int) const noexcept = delete; simdjson_inline simdjson_result<dom::element> at_pointer(const std::string_view json_pointer) const noexcept; + simdjson_inline simdjson_result<dom::element> at_path(const std::string_view json_path) const noexcept; [[deprecated("For standard compliance, use at_pointer instead, and prefix your pointers with a slash '/', see RFC6901 ")]] simdjson_inline simdjson_result<dom::element> at(const std::string_view json_pointer) const noexcept; simdjson_inline simdjson_result<dom::element> at(size_t index) const noexcept; diff --git a/contrib/libs/simdjson/include/simdjson/dom/object-inl.h b/contrib/libs/simdjson/include/simdjson/dom/object-inl.h index c72ab3feb4..3bfd7a051c 100644 --- a/contrib/libs/simdjson/include/simdjson/dom/object-inl.h +++ b/contrib/libs/simdjson/include/simdjson/dom/object-inl.h @@ -7,6 +7,7 @@ #include "simdjson/dom/element-inl.h" #include "simdjson/error-inl.h" +#include "simdjson/jsonpathutil.h" #include <cstring> @@ -34,6 +35,11 @@ inline simdjson_result<dom::element> simdjson_result<dom::object>::at_pointer(st if (error()) { return error(); } return first.at_pointer(json_pointer); } +inline simdjson_result<dom::element> simdjson_result<dom::object>::at_path(std::string_view json_path) const noexcept { + auto json_pointer = json_path_to_pointer_conversion(json_path); + if (json_pointer == "-1") { return INVALID_JSON_POINTER; } + return at_pointer(json_pointer); +} inline simdjson_result<dom::element> simdjson_result<dom::object>::at_key(std::string_view key) const noexcept { if (error()) { return error(); } return first.at_key(key); @@ -131,6 +137,12 @@ inline simdjson_result<element> object::at_pointer(std::string_view json_pointer return child; } +inline simdjson_result<element> object::at_path(std::string_view json_path) const noexcept { + auto json_pointer = json_path_to_pointer_conversion(json_path); + if (json_pointer == "-1") { return INVALID_JSON_POINTER; } + return at_pointer(json_pointer); +} + inline simdjson_result<element> object::at_key(std::string_view key) const noexcept { iterator end_field = end(); for (iterator field = begin(); field != end_field; ++field) { diff --git a/contrib/libs/simdjson/include/simdjson/dom/object.h b/contrib/libs/simdjson/include/simdjson/dom/object.h index 8f6884baf1..83f1392d99 100644 --- a/contrib/libs/simdjson/include/simdjson/dom/object.h +++ b/contrib/libs/simdjson/include/simdjson/dom/object.h @@ -145,6 +145,7 @@ public: * - INCORRECT_TYPE if this is not an object */ inline simdjson_result<element> operator[](const char *key) const noexcept; + simdjson_result<element> operator[](int) const noexcept = delete; /** * Get the value associated with the given JSON pointer. We use the RFC 6901 @@ -172,6 +173,21 @@ public: inline simdjson_result<element> at_pointer(std::string_view json_pointer) const noexcept; /** + * Get the value associated with the given JSONPath expression. We only support + * JSONPath queries that trivially convertible to JSON Pointer queries: key + * names and array indices. + * + * https://datatracker.ietf.org/doc/html/draft-normington-jsonpath-00 + * + * @return The value associated with the given JSONPath expression, or: + * - INVALID_JSON_POINTER if the JSONPath to JSON Pointer conversion fails + * - NO_SUCH_FIELD if a field does not exist in an object + * - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length + * - INCORRECT_TYPE if a non-integer is used to access an array + */ + inline simdjson_result<element> at_path(std::string_view json_path) const noexcept; + + /** * Get the value associated with the given key. * * The key will be matched against **unescaped** JSON: @@ -243,7 +259,9 @@ public: inline simdjson_result<dom::element> operator[](std::string_view key) const noexcept; inline simdjson_result<dom::element> operator[](const char *key) const noexcept; + simdjson_result<dom::element> operator[](int) const noexcept = delete; inline simdjson_result<dom::element> at_pointer(std::string_view json_pointer) const noexcept; + inline simdjson_result<dom::element> at_path(std::string_view json_path) const noexcept; inline simdjson_result<dom::element> at_key(std::string_view key) const noexcept; inline simdjson_result<dom::element> at_key_case_insensitive(std::string_view key) const noexcept; diff --git a/contrib/libs/simdjson/include/simdjson/dom/parser.h b/contrib/libs/simdjson/include/simdjson/dom/parser.h index a22a1a68b1..7c28a712f0 100644 --- a/contrib/libs/simdjson/include/simdjson/dom/parser.h +++ b/contrib/libs/simdjson/include/simdjson/dom/parser.h @@ -202,6 +202,22 @@ public: * simdjson::dom::parser parser; * simdjson::dom::element element = parser.parse(padded_json_copy.get(), json_len, false); * + * ### std::string references + * + * If you pass a mutable std::string reference (std::string&), the parser will seek to extend + * its capacity to SIMDJSON_PADDING bytes beyond the end of the string. + * + * Whenever you pass an std::string reference, the parser will access the bytes beyond the end of + * the string but before the end of the allocated memory (std::string::capacity()). + * If you are using a sanitizer that checks for reading uninitialized bytes or std::string's + * container-overflow checks, you may encounter sanitizer warnings. + * You can safely ignore these warnings. Or you can call simdjson::pad(std::string&) to pad the + * string with SIMDJSON_PADDING spaces: this function returns a simdjson::padding_string_view + * which can be be passed to the parser's parse function: + * + * std::string json = R"({ "foo": 1 } { "foo": 2 } { "foo": 3 } )"; + * element doc = parser.parse(simdjson::pad(json)); + * * ### Parser Capacity * * If the parser's current capacity is less than len, it will allocate enough capacity @@ -549,9 +565,14 @@ public: /** * The parser instance can use threads when they are available to speed up some * operations. It is enabled by default. Changing this attribute will change the - * behavior of the parser for future operations. + * behavior of the parser for future operations. Set to true by default. */ bool threaded{true}; +#else + /** + * When SIMDJSON_THREADS_ENABLED is not defined, the parser instance cannot use threads. + */ + bool threaded{false}; #endif /** @private Use the new DOM API instead */ class Iterator; diff --git a/contrib/libs/simdjson/include/simdjson/error.h b/contrib/libs/simdjson/include/simdjson/error.h index 4848f6ef91..2f3443d9b6 100644 --- a/contrib/libs/simdjson/include/simdjson/error.h +++ b/contrib/libs/simdjson/include/simdjson/error.h @@ -86,7 +86,7 @@ struct simdjson_error : public std::exception { */ simdjson_error(error_code error) noexcept : _error{error} { } /** The error message */ - const char *what() const noexcept { return error_message(error()); } + const char *what() const noexcept override { return error_message(error()); } /** The error code */ error_code error() const noexcept { return _error; } private: diff --git a/contrib/libs/simdjson/include/simdjson/fallback/numberparsing_defs.h b/contrib/libs/simdjson/include/simdjson/fallback/numberparsing_defs.h index e807423e6f..490a298dda 100644 --- a/contrib/libs/simdjson/include/simdjson/fallback/numberparsing_defs.h +++ b/contrib/libs/simdjson/include/simdjson/fallback/numberparsing_defs.h @@ -75,6 +75,12 @@ simdjson_inline internal::value128 full_multiplication(uint64_t value1, uint64_t } // namespace fallback } // namespace simdjson +#ifndef SIMDJSON_SWAR_NUMBER_PARSING +#if SIMDJSON_IS_BIG_ENDIAN +#define SIMDJSON_SWAR_NUMBER_PARSING 0 +#else #define SIMDJSON_SWAR_NUMBER_PARSING 1 +#endif +#endif #endif // SIMDJSON_FALLBACK_NUMBERPARSING_DEFS_H diff --git a/contrib/libs/simdjson/include/simdjson/generic/dependencies.h b/contrib/libs/simdjson/include/simdjson/generic/dependencies.h index 28d9749f27..1720ddb0aa 100644 --- a/contrib/libs/simdjson/include/simdjson/generic/dependencies.h +++ b/contrib/libs/simdjson/include/simdjson/generic/dependencies.h @@ -16,5 +16,4 @@ #include "simdjson/internal/jsoncharutils_tables.h" #include "simdjson/internal/numberparsing_tables.h" #include "simdjson/internal/simdprune_tables.h" - #endif // SIMDJSON_GENERIC_DEPENDENCIES_H
\ No newline at end of file diff --git a/contrib/libs/simdjson/include/simdjson/generic/numberparsing.h b/contrib/libs/simdjson/include/simdjson/generic/numberparsing.h index facc2acc6f..5b8fdfcd78 100644 --- a/contrib/libs/simdjson/include/simdjson/generic/numberparsing.h +++ b/contrib/libs/simdjson/include/simdjson/generic/numberparsing.h @@ -574,7 +574,6 @@ simdjson_unused simdjson_inline simdjson_result<number_type> get_number_type(con // Our objective is accurate parsing (ULP of 0) at high speed. template<typename W> simdjson_inline error_code parse_number(const uint8_t *const src, W &writer) { - // // Check for minus sign // diff --git a/contrib/libs/simdjson/include/simdjson/generic/ondemand/amalgamated.h b/contrib/libs/simdjson/include/simdjson/generic/ondemand/amalgamated.h index d53e7316df..e1fac8d2ab 100644 --- a/contrib/libs/simdjson/include/simdjson/generic/ondemand/amalgamated.h +++ b/contrib/libs/simdjson/include/simdjson/generic/ondemand/amalgamated.h @@ -4,6 +4,7 @@ // Stuff other things depend on #include "simdjson/generic/ondemand/base.h" +#include "simdjson/generic/ondemand/deserialize.h" #include "simdjson/generic/ondemand/value_iterator.h" #include "simdjson/generic/ondemand/value.h" #include "simdjson/generic/ondemand/logger.h" @@ -23,9 +24,13 @@ #include "simdjson/generic/ondemand/object_iterator.h" #include "simdjson/generic/ondemand/serialization.h" +// Deserialization for standard types +#include "simdjson/generic/ondemand/std_deserialize.h" + // Inline definitions #include "simdjson/generic/ondemand/array-inl.h" #include "simdjson/generic/ondemand/array_iterator-inl.h" +#include "simdjson/generic/ondemand/value-inl.h" #include "simdjson/generic/ondemand/document-inl.h" #include "simdjson/generic/ondemand/document_stream-inl.h" #include "simdjson/generic/ondemand/field-inl.h" @@ -38,5 +43,6 @@ #include "simdjson/generic/ondemand/raw_json_string-inl.h" #include "simdjson/generic/ondemand/serialization-inl.h" #include "simdjson/generic/ondemand/token_iterator-inl.h" -#include "simdjson/generic/ondemand/value-inl.h" #include "simdjson/generic/ondemand/value_iterator-inl.h" + + diff --git a/contrib/libs/simdjson/include/simdjson/generic/ondemand/array-inl.h b/contrib/libs/simdjson/include/simdjson/generic/ondemand/array-inl.h index b699ea4a03..e7bc89d9b1 100644 --- a/contrib/libs/simdjson/include/simdjson/generic/ondemand/array-inl.h +++ b/contrib/libs/simdjson/include/simdjson/generic/ondemand/array-inl.h @@ -2,6 +2,7 @@ #ifndef SIMDJSON_CONDITIONAL_INCLUDE #define SIMDJSON_GENERIC_ONDEMAND_ARRAY_INL_H +#include "simdjson/jsonpathutil.h" #include "simdjson/generic/ondemand/base.h" #include "simdjson/generic/ondemand/array.h" #include "simdjson/generic/ondemand/array_iterator-inl.h" @@ -163,53 +164,6 @@ inline simdjson_result<value> array::at_pointer(std::string_view json_pointer) n return child; } -inline std::string json_path_to_pointer_conversion(std::string_view json_path) { - if (json_path.empty() || (json_path.front() != '.' && - json_path.front() != '[')) { - return "-1"; // This is just a sentinel value, the caller should check for this and return an error. - } - - std::string result; - // Reserve space to reduce allocations, adjusting for potential increases due - // to escaping. - result.reserve(json_path.size() * 2); - - size_t i = 0; - - while (i < json_path.length()) { - if (json_path[i] == '.') { - result += '/'; - } else if (json_path[i] == '[') { - result += '/'; - ++i; // Move past the '[' - while (i < json_path.length() && json_path[i] != ']') { - if (json_path[i] == '~') { - result += "~0"; - } else if (json_path[i] == '/') { - result += "~1"; - } else { - result += json_path[i]; - } - ++i; - } - if (i == json_path.length() || json_path[i] != ']') { - return "-1"; // Using sentinel value that will be handled as an error by the caller. - } - } else { - if (json_path[i] == '~') { - result += "~0"; - } else if (json_path[i] == '/') { - result += "~1"; - } else { - result += json_path[i]; - } - } - ++i; - } - - return result; -} - inline simdjson_result<value> array::at_path(std::string_view json_path) noexcept { auto json_pointer = json_path_to_pointer_conversion(json_path); if (json_pointer == "-1") { return INVALID_JSON_POINTER; } diff --git a/contrib/libs/simdjson/include/simdjson/generic/ondemand/array.h b/contrib/libs/simdjson/include/simdjson/generic/ondemand/array.h index e6095d27c2..0d1cbbd4e8 100644 --- a/contrib/libs/simdjson/include/simdjson/generic/ondemand/array.h +++ b/contrib/libs/simdjson/include/simdjson/generic/ondemand/array.h @@ -44,7 +44,8 @@ public: * calling this function, if successful, the array is 'rewinded' at its * beginning as if it had never been accessed. If the JSON is malformed (e.g., * there is a missing comma), then an error is returned and it is no longer - * safe to continue. + * safe to continue. Note that count_elements() does not validate the JSON values, + * only the structure of the array. * * To check that an array is empty, it is more performant to use * the is_empty() method. diff --git a/contrib/libs/simdjson/include/simdjson/generic/ondemand/dependencies.h b/contrib/libs/simdjson/include/simdjson/generic/ondemand/dependencies.h index 7fd9da72ef..3c4fdc3a62 100644 --- a/contrib/libs/simdjson/include/simdjson/generic/ondemand/dependencies.h +++ b/contrib/libs/simdjson/include/simdjson/generic/ondemand/dependencies.h @@ -13,5 +13,6 @@ #include "simdjson/padded_string.h" #include "simdjson/padded_string_view.h" #include "simdjson/internal/dom_parser_implementation.h" +#include "simdjson/jsonpathutil.h" #endif // SIMDJSON_GENERIC_ONDEMAND_DEPENDENCIES_H
\ No newline at end of file diff --git a/contrib/libs/simdjson/include/simdjson/generic/ondemand/deserialize.h b/contrib/libs/simdjson/include/simdjson/generic/ondemand/deserialize.h new file mode 100644 index 0000000000..02abed33ab --- /dev/null +++ b/contrib/libs/simdjson/include/simdjson/generic/ondemand/deserialize.h @@ -0,0 +1,123 @@ +#if SIMDJSON_SUPPORTS_DESERIALIZATION + +#ifndef SIMDJSON_ONDEMAND_DESERIALIZE_H +#ifndef SIMDJSON_CONDITIONAL_INCLUDE +#define SIMDJSON_ONDEMAND_DESERIALIZE_H +#include "simdjson/generic/ondemand/base.h" +#include "simdjson/generic/ondemand/array.h" +#endif // SIMDJSON_CONDITIONAL_INCLUDE + +#include <concepts> +namespace simdjson { + +namespace tag_invoke_fn_ns { +void tag_invoke(); + +struct tag_invoke_fn { + template <typename Tag, typename... Args> + requires requires(Tag tag, Args &&...args) { + tag_invoke(std::forward<Tag>(tag), std::forward<Args>(args)...); + } + constexpr auto operator()(Tag tag, Args &&...args) const + noexcept(noexcept(tag_invoke(std::forward<Tag>(tag), + std::forward<Args>(args)...))) + -> decltype(tag_invoke(std::forward<Tag>(tag), + std::forward<Args>(args)...)) { + return tag_invoke(std::forward<Tag>(tag), std::forward<Args>(args)...); + } +}; +} // namespace tag_invoke_fn_ns + +inline namespace tag_invoke_ns { +inline constexpr tag_invoke_fn_ns::tag_invoke_fn tag_invoke = {}; +} // namespace tag_invoke_ns + +template <typename Tag, typename... Args> +concept tag_invocable = requires(Tag tag, Args... args) { + tag_invoke(std::forward<Tag>(tag), std::forward<Args>(args)...); +}; + +template <typename Tag, typename... Args> +concept nothrow_tag_invocable = + tag_invocable<Tag, Args...> && requires(Tag tag, Args... args) { + { + tag_invoke(std::forward<Tag>(tag), std::forward<Args>(args)...) + } noexcept; + }; + +template <typename Tag, typename... Args> +using tag_invoke_result = + std::invoke_result<decltype(tag_invoke), Tag, Args...>; + +template <typename Tag, typename... Args> +using tag_invoke_result_t = + std::invoke_result_t<decltype(tag_invoke), Tag, Args...>; + +template <auto &Tag> using tag_t = std::decay_t<decltype(Tag)>; + + +struct deserialize_tag; + +/// These types are deserializable in a built-in way +template <typename> struct is_builtin_deserializable : std::false_type {}; +template <> struct is_builtin_deserializable<int64_t> : std::true_type {}; +template <> struct is_builtin_deserializable<uint64_t> : std::true_type {}; +template <> struct is_builtin_deserializable<double> : std::true_type {}; +template <> struct is_builtin_deserializable<bool> : std::true_type {}; +template <> struct is_builtin_deserializable<SIMDJSON_IMPLEMENTATION::ondemand::array> : std::true_type {}; +template <> struct is_builtin_deserializable<SIMDJSON_IMPLEMENTATION::ondemand::object> : std::true_type {}; +template <> struct is_builtin_deserializable<SIMDJSON_IMPLEMENTATION::ondemand::value> : std::true_type {}; +template <> struct is_builtin_deserializable<SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string> : std::true_type {}; +template <> struct is_builtin_deserializable<std::string_view> : std::true_type {}; + +template <typename T> +concept is_builtin_deserializable_v = is_builtin_deserializable<T>::value; + +template <typename T, typename ValT = SIMDJSON_IMPLEMENTATION::ondemand::value> +concept custom_deserializable = tag_invocable<deserialize_tag, ValT&, T&>; + +template <typename T, typename ValT = SIMDJSON_IMPLEMENTATION::ondemand::value> +concept deserializable = custom_deserializable<T, ValT> || is_builtin_deserializable_v<T>; + +template <typename T, typename ValT = SIMDJSON_IMPLEMENTATION::ondemand::value> +concept nothrow_custom_deserializable = nothrow_tag_invocable<deserialize_tag, ValT&, T&>; + +// built-in types are noexcept and if an error happens, the value simply gets ignored and the error is returned. +template <typename T, typename ValT = SIMDJSON_IMPLEMENTATION::ondemand::value> +concept nothrow_deserializable = nothrow_custom_deserializable<T, ValT> || is_builtin_deserializable_v<T>; + +/// Deserialize Tag +inline constexpr struct deserialize_tag { + using value_type = SIMDJSON_IMPLEMENTATION::ondemand::value; + using document_type = SIMDJSON_IMPLEMENTATION::ondemand::document; + using document_reference_type = SIMDJSON_IMPLEMENTATION::ondemand::document_reference; + + // Customization Point for value + template <typename T> + requires custom_deserializable<T, value_type> + [[nodiscard]] constexpr /* error_code */ auto operator()(value_type &object, T& output) const noexcept(nothrow_custom_deserializable<T, value_type>) { + return tag_invoke(*this, object, output); + } + + // Customization Point for document + template <typename T> + requires custom_deserializable<T, document_type> + [[nodiscard]] constexpr /* error_code */ auto operator()(document_type &object, T& output) const noexcept(nothrow_custom_deserializable<T, document_type>) { + return tag_invoke(*this, object, output); + } + + // Customization Point for document reference + template <typename T> + requires custom_deserializable<T, document_reference_type> + [[nodiscard]] constexpr /* error_code */ auto operator()(document_reference_type &object, T& output) const noexcept(nothrow_custom_deserializable<T, document_reference_type>) { + return tag_invoke(*this, object, output); + } + + +} deserialize{}; + +} // namespace simdjson + +#endif // SIMDJSON_ONDEMAND_DESERIALIZE_H +#endif // SIMDJSON_SUPPORTS_DESERIALIZATION + diff --git a/contrib/libs/simdjson/include/simdjson/generic/ondemand/document-inl.h b/contrib/libs/simdjson/include/simdjson/generic/ondemand/document-inl.h index 3af60b0877..4dd44f4984 100644 --- a/contrib/libs/simdjson/include/simdjson/generic/ondemand/document-inl.h +++ b/contrib/libs/simdjson/include/simdjson/generic/ondemand/document-inl.h @@ -8,10 +8,12 @@ #include "simdjson/generic/ondemand/json_type.h" #include "simdjson/generic/ondemand/raw_json_string.h" #include "simdjson/generic/ondemand/value.h" +#include "simdjson/generic/ondemand/value-inl.h" #include "simdjson/generic/ondemand/array-inl.h" #include "simdjson/generic/ondemand/json_iterator-inl.h" #include "simdjson/generic/ondemand/object-inl.h" #include "simdjson/generic/ondemand/value_iterator-inl.h" +#include "simdjson/generic/ondemand/deserialize.h" #endif // SIMDJSON_CONDITIONAL_INCLUDE namespace simdjson { @@ -165,6 +167,16 @@ template<> simdjson_inline simdjson_result<int64_t> document::get() & noexcept { template<> simdjson_inline simdjson_result<bool> document::get() & noexcept { return get_bool(); } template<> simdjson_inline simdjson_result<value> document::get() & noexcept { return get_value(); } +template<> simdjson_inline error_code document::get(array& out) & noexcept { return get_array().get(out); } +template<> simdjson_inline error_code document::get(object& out) & noexcept { return get_object().get(out); } +template<> simdjson_inline error_code document::get(raw_json_string& out) & noexcept { return get_raw_json_string().get(out); } +template<> simdjson_inline error_code document::get(std::string_view& out) & noexcept { return get_string(false).get(out); } +template<> simdjson_inline error_code document::get(double& out) & noexcept { return get_double().get(out); } +template<> simdjson_inline error_code document::get(uint64_t& out) & noexcept { return get_uint64().get(out); } +template<> simdjson_inline error_code document::get(int64_t& out) & noexcept { return get_int64().get(out); } +template<> simdjson_inline error_code document::get(bool& out) & noexcept { return get_bool().get(out); } +template<> simdjson_inline error_code document::get(value& out) & noexcept { return get_value().get(out); } + template<> simdjson_deprecated simdjson_inline simdjson_result<raw_json_string> document::get() && noexcept { return get_raw_json_string(); } template<> simdjson_deprecated simdjson_inline simdjson_result<std::string_view> document::get() && noexcept { return get_string(false); } template<> simdjson_deprecated simdjson_inline simdjson_result<double> document::get() && noexcept { return std::forward<document>(*this).get_double(); } @@ -173,13 +185,6 @@ template<> simdjson_deprecated simdjson_inline simdjson_result<int64_t> document template<> simdjson_deprecated simdjson_inline simdjson_result<bool> document::get() && noexcept { return std::forward<document>(*this).get_bool(); } template<> simdjson_deprecated simdjson_inline simdjson_result<value> document::get() && noexcept { return get_value(); } -template<typename T> simdjson_inline error_code document::get(T &out) & noexcept { - return get<T>().get(out); -} -template<typename T> simdjson_deprecated simdjson_inline error_code document::get(T &out) && noexcept { - return std::forward<document>(*this).get<T>().get(out); -} - #if SIMDJSON_EXCEPTIONS template <class T> simdjson_deprecated simdjson_inline document::operator T() && noexcept(false) { return get<T>(); } @@ -818,6 +823,26 @@ simdjson_inline simdjson_result<bool> simdjson_result<SIMDJSON_IMPLEMENTATION::o if (error()) { return error(); } return first.is_null(); } +template<typename T> +simdjson_inline simdjson_result<T> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::get() & noexcept { + if (error()) { return error(); } + return first.get<T>(); +} +template<typename T> +simdjson_inline simdjson_result<T> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::get() && noexcept { + if (error()) { return error(); } + return std::forward<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>(first).get<T>(); +} +template <class T> +simdjson_inline error_code simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::get(T &out) & noexcept { + if (error()) { return error(); } + return first.get<T>(out); +} +template <class T> +simdjson_inline error_code simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::get(T &out) && noexcept { + if (error()) { return error(); } + return std::forward<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>(first).get<T>(out); +} simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::json_type> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::type() noexcept { if (error()) { return error(); } return first.type(); @@ -830,6 +855,18 @@ simdjson_inline simdjson_result<bool> simdjson_result<SIMDJSON_IMPLEMENTATION::o if (error()) { return error(); } return first.is_string(); } +template <> +simdjson_inline error_code simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::get(SIMDJSON_IMPLEMENTATION::ondemand::document_reference &out) & noexcept { + if (error()) { return error(); } + out = first; + return SUCCESS; +} +template <> +simdjson_inline error_code simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::get(SIMDJSON_IMPLEMENTATION::ondemand::document_reference &out) && noexcept { + if (error()) { return error(); } + out = first; + return SUCCESS; +} simdjson_inline simdjson_result<bool> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::is_negative() noexcept { if (error()) { return error(); } return first.is_negative(); @@ -847,10 +884,12 @@ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::number> simdj return first.get_number(); } #if SIMDJSON_EXCEPTIONS -template <class T, typename std::enable_if<std::is_same<T, SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::value == false>::type> +template <class T> simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::operator T() noexcept(false) { + static_assert(std::is_same<T, SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::value == false, "You should not call get<T> when T is a document"); + static_assert(std::is_same<T, SIMDJSON_IMPLEMENTATION::ondemand::document>::value == false, "You should not call get<T> when T is a document"); if (error()) { throw simdjson_error(error()); } - return first; + return first.get<T>(); } simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::operator SIMDJSON_IMPLEMENTATION::ondemand::array() & noexcept(false) { if (error()) { throw simdjson_error(error()); } diff --git a/contrib/libs/simdjson/include/simdjson/generic/ondemand/document.h b/contrib/libs/simdjson/include/simdjson/generic/ondemand/document.h index 390180e6f4..c109f15b8b 100644 --- a/contrib/libs/simdjson/include/simdjson/generic/ondemand/document.h +++ b/contrib/libs/simdjson/include/simdjson/generic/ondemand/document.h @@ -4,8 +4,11 @@ #define SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_H #include "simdjson/generic/ondemand/base.h" #include "simdjson/generic/ondemand/json_iterator.h" +#include "simdjson/generic/ondemand/deserialize.h" +#include "simdjson/generic/ondemand/value.h" #endif // SIMDJSON_CONDITIONAL_INCLUDE + namespace simdjson { namespace SIMDJSON_IMPLEMENTATION { namespace ondemand { @@ -178,24 +181,39 @@ public: * @returns A value of the given type, parsed from the JSON. * @returns INCORRECT_TYPE If the JSON value is not the given type. */ - template<typename T> simdjson_inline simdjson_result<T> get() & noexcept { - // Unless the simdjson library or the user provides an inline implementation, calling this method should - // immediately fail. - static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. " - "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " - "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), " - " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template." - " You may also add support for custom types, see our documentation."); + template <typename T> + simdjson_inline simdjson_result<T> get() & +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable<T, document> ? nothrow_custom_deserializable<T, document> : true) +#else + noexcept +#endif + { + static_assert(std::is_default_constructible<T>::value, "Cannot initialize the specified type."); + T out{}; + SIMDJSON_TRY(get<T>(out)); + return out; } - /** @overload template<typename T> simdjson_result<T> get() & noexcept */ - template<typename T> simdjson_deprecated simdjson_inline simdjson_result<T> get() && noexcept { - // Unless the simdjson library or the user provides an inline implementation, calling this method should - // immediately fail. - static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. " - "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " - "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), " - " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template." - " You may also add support for custom types, see our documentation."); + /** + * @overload template<typename T> simdjson_result<T> get() & noexcept + * + * We disallow the use tag_invoke CPO on a moved document; it may create UB + * if user uses `ondemand::array` or `ondemand::object` in their custom type. + * + * The member function is still remains specialize-able for compatibility + * reasons, but we completely disallow its use when a tag_invoke customization + * is provided. + */ + template<typename T> + simdjson_inline simdjson_result<T> get() && +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable<T, document> ? nothrow_custom_deserializable<T, document> : true) +#else + noexcept +#endif + { + static_assert(!std::is_same<T, array>::value && !std::is_same<T, object>::value, "You should never hold either an ondemand::array or ondemand::object without a corresponding ondemand::document being alive; that would be Undefined Behaviour."); + return static_cast<document&>(*this).get<T>(); } /** @@ -209,7 +227,32 @@ public: * @returns INCORRECT_TYPE If the JSON value is not an object. * @returns SUCCESS If the parse succeeded and the out parameter was set to the value. */ - template<typename T> simdjson_inline error_code get(T &out) & noexcept; + template<typename T> + simdjson_inline error_code get(T &out) & +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable<T, document> ? nothrow_custom_deserializable<T, document> : true) +#else + noexcept +#endif + { +#if SIMDJSON_SUPPORTS_DESERIALIZATION + if constexpr (custom_deserializable<T, document>) { + return deserialize(*this, out); + } else { +#endif // SIMDJSON_SUPPORTS_DESERIALIZATION + // Unless the simdjson library or the user provides an inline implementation, calling this method should + // immediately fail. + static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. " + "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " + "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), " + " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template." + " You may also add support for custom types, see our documentation."); + static_cast<void>(out); // to get rid of unused errors + return UNINITIALIZED; +#if SIMDJSON_SUPPORTS_DESERIALIZATION + } +#endif + } /** @overload template<typename T> error_code get(T &out) & noexcept */ template<typename T> simdjson_deprecated simdjson_inline error_code get(T &out) && noexcept; @@ -311,7 +354,8 @@ public: * calling this function, if successful, the array is 'rewinded' at its * beginning as if it had never been accessed. If the JSON is malformed (e.g., * there is a missing comma), then an error is returned and it is no longer - * safe to continue. + * safe to continue. Note that count_elements() does not validate the JSON values, + * only the structure of the array. */ simdjson_inline simdjson_result<size_t> count_elements() & noexcept; /** @@ -423,6 +467,7 @@ public: simdjson_inline simdjson_result<value> operator[](std::string_view key) & noexcept; /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */ simdjson_inline simdjson_result<value> operator[](const char *key) & noexcept; + simdjson_result<value> operator[](int) & noexcept = delete; /** * Get the type of this JSON value. It does not validate or consume the value. @@ -691,6 +736,11 @@ protected: /** * A document_reference is a thin wrapper around a document reference instance. + * The document_reference instances are used primarily/solely for streams of JSON + * documents. They differ from document instances when parsing a scalar value + * (a document that is not an array or an object). In the case of a document, + * we expect the document to be fully consumed. In the case of a document_reference, + * we allow trailing content. */ class document_reference { public: @@ -716,7 +766,70 @@ public: simdjson_inline simdjson_result<value> get_value() noexcept; simdjson_inline simdjson_result<bool> is_null() noexcept; - template<typename T> simdjson_inline simdjson_result<T> get() & noexcept; + template <typename T> + simdjson_inline simdjson_result<T> get() & +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable<T, document> ? nothrow_custom_deserializable<T, document> : true) +#else + noexcept +#endif + { + static_assert(std::is_default_constructible<T>::value, "Cannot initialize the specified type."); + T out{}; + SIMDJSON_TRY(get<T>(out)); + return out; + } + template<typename T> + simdjson_inline simdjson_result<T> get() && +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable<T, document> ? nothrow_custom_deserializable<T, document> : true) +#else + noexcept +#endif + { + static_assert(!std::is_same<T, array>::value && !std::is_same<T, object>::value, "You should never hold either an ondemand::array or ondemand::object without a corresponding ondemand::document_reference being alive; that would be Undefined Behaviour."); + return static_cast<document&>(*this).get<T>(); + } + + /** + * Get this value as the given type. + * + * Supported types: object, array, raw_json_string, string_view, uint64_t, int64_t, double, bool, value + * + * Be mindful that the document instance must remain in scope while you are accessing object, array and value instances. + * + * @param out This is set to a value of the given type, parsed from the JSON. If there is an error, this may not be initialized. + * @returns INCORRECT_TYPE If the JSON value is not an object. + * @returns SUCCESS If the parse succeeded and the out parameter was set to the value. + */ + template<typename T> + simdjson_inline error_code get(T &out) & +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable<T, document> ? nothrow_custom_deserializable<T, document_reference> : true) +#else + noexcept +#endif + { +#if SIMDJSON_SUPPORTS_DESERIALIZATION + if constexpr (custom_deserializable<T, document_reference>) { + return deserialize(*this, out); + } else { +#endif // SIMDJSON_SUPPORTS_DESERIALIZATION + // Unless the simdjson library or the user provides an inline implementation, calling this method should + // immediately fail. + static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. " + "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " + "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), " + " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template." + " You may also add support for custom types, see our documentation."); + static_cast<void>(out); // to get rid of unused errors + return UNINITIALIZED; +#if SIMDJSON_SUPPORTS_DESERIALIZATION + } +#endif + } + /** @overload template<typename T> error_code get(T &out) & noexcept */ + template<typename T> simdjson_inline error_code get(T &out) && noexcept; simdjson_inline simdjson_result<std::string_view> raw_json() noexcept; simdjson_inline operator document&() const noexcept; #if SIMDJSON_EXCEPTIONS @@ -741,6 +854,7 @@ public: simdjson_inline simdjson_result<value> find_field(const char *key) & noexcept; simdjson_inline simdjson_result<value> operator[](std::string_view key) & noexcept; simdjson_inline simdjson_result<value> operator[](const char *key) & noexcept; + simdjson_result<value> operator[](int) & noexcept = delete; simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; simdjson_inline simdjson_result<value> find_field_unordered(const char *key) & noexcept; @@ -819,6 +933,7 @@ public: simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field(const char *key) & noexcept; simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> operator[](std::string_view key) & noexcept; simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> operator[](const char *key) & noexcept; + simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> operator[](int) & noexcept = delete; simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field_unordered(std::string_view key) & noexcept; simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field_unordered(const char *key) & noexcept; simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::json_type> type() noexcept; @@ -868,8 +983,14 @@ public: simdjson_inline simdjson_result<bool> get_bool() noexcept; simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> get_value() noexcept; simdjson_inline simdjson_result<bool> is_null() noexcept; + + template<typename T> simdjson_inline simdjson_result<T> get() & noexcept; + template<typename T> simdjson_inline simdjson_result<T> get() && noexcept; + + template<typename T> simdjson_inline error_code get(T &out) & noexcept; + template<typename T> simdjson_inline error_code get(T &out) && noexcept; #if SIMDJSON_EXCEPTIONS - template <class T, typename std::enable_if<std::is_same<T, SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::value == false>::type> + template <class T> explicit simdjson_inline operator T() noexcept(false); simdjson_inline operator SIMDJSON_IMPLEMENTATION::ondemand::array() & noexcept(false); simdjson_inline operator SIMDJSON_IMPLEMENTATION::ondemand::object() & noexcept(false); @@ -890,6 +1011,7 @@ public: simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field(const char *key) & noexcept; simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> operator[](std::string_view key) & noexcept; simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> operator[](const char *key) & noexcept; + simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> operator[](int) & noexcept = delete; simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field_unordered(std::string_view key) & noexcept; simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field_unordered(const char *key) & noexcept; simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::json_type> type() noexcept; diff --git a/contrib/libs/simdjson/include/simdjson/generic/ondemand/document_stream-inl.h b/contrib/libs/simdjson/include/simdjson/generic/ondemand/document_stream-inl.h index 059ad0ec5f..0dd10feac2 100644 --- a/contrib/libs/simdjson/include/simdjson/generic/ondemand/document_stream-inl.h +++ b/contrib/libs/simdjson/include/simdjson/generic/ondemand/document_stream-inl.h @@ -152,7 +152,6 @@ simdjson_inline document_stream::iterator::iterator(document_stream* _stream, bo } simdjson_inline simdjson_result<ondemand::document_reference> document_stream::iterator::operator*() noexcept { - //if(stream->error) { return stream->error; } return simdjson_result<ondemand::document_reference>(stream->doc, stream->error); } diff --git a/contrib/libs/simdjson/include/simdjson/generic/ondemand/parser.h b/contrib/libs/simdjson/include/simdjson/generic/ondemand/parser.h index f1f86d4843..5e22f55543 100644 --- a/contrib/libs/simdjson/include/simdjson/generic/ondemand/parser.h +++ b/contrib/libs/simdjson/include/simdjson/generic/ondemand/parser.h @@ -84,6 +84,22 @@ public: * using a sanitizer that verifies that no uninitialized byte is read, then you should initialize the * SIMDJSON_PADDING bytes to avoid runtime warnings. * + * ### std::string references + * + * If you pass a mutable std::string reference (std::string&), the parser will seek to extend + * its capacity to SIMDJSON_PADDING bytes beyond the end of the string. + * + * Whenever you pass an std::string reference, the parser will access the bytes beyond the end of + * the string but before the end of the allocated memory (std::string::capacity()). + * If you are using a sanitizer that checks for reading uninitialized bytes or std::string's + * container-overflow checks, you may encounter sanitizer warnings. + * You can safely ignore these warnings. Or you can call simdjson::pad(std::string&) to pad the + * string with SIMDJSON_PADDING spaces: this function returns a simdjson::padding_string_view + * which can be be passed to the parser's iterate function: + * + * std::string json = R"({ "foo": 1 } { "foo": 2 } { "foo": 3 } )"; + * document doc = parser.iterate(simdjson::pad(json)); + * * @param json The JSON to parse. * @param len The length of the JSON. * @param capacity The number of bytes allocated in the JSON (must be at least len+SIMDJSON_PADDING). @@ -278,8 +294,12 @@ public: * behavior of the parser for future operations. */ bool threaded{true}; + #else + /** + * When SIMDJSON_THREADS_ENABLED is not defined, the parser instance cannot use threads. + */ + bool threaded{false}; #endif - /** * Unescape this JSON string, replacing \\ with \, \n with newline, etc. to a user-provided buffer. * The result must be valid UTF-8. diff --git a/contrib/libs/simdjson/include/simdjson/generic/ondemand/std_deserialize.h b/contrib/libs/simdjson/include/simdjson/generic/ondemand/std_deserialize.h new file mode 100644 index 0000000000..ce8b9fa3fe --- /dev/null +++ b/contrib/libs/simdjson/include/simdjson/generic/ondemand/std_deserialize.h @@ -0,0 +1,166 @@ +#if SIMDJSON_SUPPORTS_DESERIALIZATION + +#ifndef SIMDJSON_ONDEMAND_DESERIALIZE_H +#ifndef SIMDJSON_CONDITIONAL_INCLUDE +#define SIMDJSON_ONDEMAND_DESERIALIZE_H +#include "simdjson/generic/ondemand/array.h" +#include "simdjson/generic/ondemand/base.h" +#endif // SIMDJSON_CONDITIONAL_INCLUDE + +#include <concepts> +#include <limits> + +namespace simdjson { +template <typename T> +constexpr bool require_custom_serialization = false; + +////////////////////////////// +// Number deserialization +////////////////////////////// + +template <std::unsigned_integral T> + requires(!require_custom_serialization<T>) +error_code tag_invoke(deserialize_tag, auto &val, T &out) noexcept { + using limits = std::numeric_limits<T>; + + uint64_t x; + SIMDJSON_TRY(val.get_uint64().get(x)); + if (x > (limits::max)()) { + return NUMBER_OUT_OF_RANGE; + } + out = static_cast<T>(x); + return SUCCESS; +} + +template <std::floating_point T> + requires(!require_custom_serialization<T>) +error_code tag_invoke(deserialize_tag, auto &val, T &out) noexcept { + double x; + SIMDJSON_TRY(val.get_double().get(x)); + out = static_cast<T>(x); + return SUCCESS; +} + +template <std::signed_integral T> + requires(!require_custom_serialization<T>) +error_code tag_invoke(deserialize_tag, auto &val, T &out) noexcept { + using limits = std::numeric_limits<T>; + + int64_t x; + SIMDJSON_TRY(val.get_int64().get(x)); + if (x > (limits::max)() || x < (limits::min)()) { + return NUMBER_OUT_OF_RANGE; + } + out = static_cast<T>(x); + return SUCCESS; +} + +/** + * STL containers have several constructors including one that takes a single + * size argument. Thus, some compilers (Visual Studio) will not be able to + * disambiguate between the size and container constructor. Users should + * explicitly specify the type of the container as needed: e.g., + * doc.get<std::vector<int>>(). + */ +template <concepts::appendable_containers T, typename ValT> + requires(!require_custom_serialization<T>) +error_code tag_invoke(deserialize_tag, ValT &val, T &out) noexcept(false) { + using value_type = typename std::remove_cvref_t<T>::value_type; + static_assert( + deserializable<value_type, ValT>, + "The specified type inside the container must itself be deserializable"); + static_assert( + std::is_default_constructible_v<value_type>, + "The specified type inside the container must default constructible."); + + SIMDJSON_IMPLEMENTATION::ondemand::array arr; + SIMDJSON_TRY(val.get_array().get(arr)); + for (auto v : arr) { + if constexpr (concepts::returns_reference<T>) { + if (auto const err = v.get<value_type>().get(concepts::emplace_one(out)); + err) { + // If an error occurs, the empty element that we just inserted gets + // removed. We're not using a temp variable because if T is a heavy + // type, we want the valid path to be the fast path and the slow path be + // the path that has errors in it. + if constexpr (requires { out.pop_back(); }) { + static_cast<void>(out.pop_back()); + } + return err; + } + } else { + value_type temp; + if (auto const err = v.get<value_type>().get(temp); err) { + return err; + } + concepts::emplace_one(out, std::move(temp)); + } + } + return SUCCESS; +} + + + +/** + * This CPO (Customization Point Object) will help deserialize into + * smart pointers. + * + * If constructing T is nothrow, this conversion should be nothrow as well since + * we return MEMALLOC if we're not able to allocate memory instead of throwing + * the error message. + * + * @tparam T The type inside the smart pointer + * @tparam ValT document/value type + * @param val document/value + * @param out a reference to the smart pointer + * @return status of the conversion + */ +template <concepts::smart_pointer T, typename ValT> + requires(!require_custom_serialization<T>) +error_code tag_invoke(deserialize_tag, ValT &val, T &out) noexcept(nothrow_deserializable<typename std::remove_cvref_t<T>::element_type, ValT>) { + using element_type = typename std::remove_cvref_t<T>::element_type; + + // For better error messages, don't use these as constraints on + // the tag_invoke CPO. + static_assert( + deserializable<element_type, ValT>, + "The specified type inside the unique_ptr must itself be deserializable"); + static_assert( + std::is_default_constructible_v<element_type>, + "The specified type inside the unique_ptr must default constructible."); + + auto ptr = new (std::nothrow) element_type(); + if (ptr == nullptr) { + return MEMALLOC; + } + SIMDJSON_TRY(val.template get<element_type>(*ptr)); + out.reset(ptr); + return SUCCESS; +} + +/** + * This CPO (Customization Point Object) will help deserialize into optional types. + */ +template <concepts::optional_type T, typename ValT> + requires(!require_custom_serialization<T>) +error_code tag_invoke(deserialize_tag, ValT &val, T &out) noexcept(nothrow_deserializable<typename std::remove_cvref_t<T>::value_type, ValT>) { + using value_type = typename std::remove_cvref_t<T>::value_type; + + static_assert( + deserializable<value_type, ValT>, + "The specified type inside the unique_ptr must itself be deserializable"); + static_assert( + std::is_default_constructible_v<value_type>, + "The specified type inside the unique_ptr must default constructible."); + + if (!out) { + out.emplace(); + } + SIMDJSON_TRY(val.template get<value_type>(out.value())); + return SUCCESS; +} + +} // namespace simdjson + +#endif // SIMDJSON_ONDEMAND_DESERIALIZE_H +#endif // SIMDJSON_SUPPORTS_DESERIALIZATION diff --git a/contrib/libs/simdjson/include/simdjson/generic/ondemand/value-inl.h b/contrib/libs/simdjson/include/simdjson/generic/ondemand/value-inl.h index 886bb9d050..a28809095c 100644 --- a/contrib/libs/simdjson/include/simdjson/generic/ondemand/value-inl.h +++ b/contrib/libs/simdjson/include/simdjson/generic/ondemand/value-inl.h @@ -78,6 +78,7 @@ simdjson_inline simdjson_result<bool> value::get_bool() noexcept { simdjson_inline simdjson_result<bool> value::is_null() noexcept { return iter.is_null(); } + template<> simdjson_inline simdjson_result<array> value::get() noexcept { return get_array(); } template<> simdjson_inline simdjson_result<object> value::get() noexcept { return get_object(); } template<> simdjson_inline simdjson_result<raw_json_string> value::get() noexcept { return get_raw_json_string(); } @@ -88,9 +89,16 @@ template<> simdjson_inline simdjson_result<uint64_t> value::get() noexcept { ret template<> simdjson_inline simdjson_result<int64_t> value::get() noexcept { return get_int64(); } template<> simdjson_inline simdjson_result<bool> value::get() noexcept { return get_bool(); } -template<typename T> simdjson_inline error_code value::get(T &out) noexcept { - return get<T>().get(out); -} + +template<> simdjson_inline error_code value::get(array& out) noexcept { return get_array().get(out); } +template<> simdjson_inline error_code value::get(object& out) noexcept { return get_object().get(out); } +template<> simdjson_inline error_code value::get(raw_json_string& out) noexcept { return get_raw_json_string().get(out); } +template<> simdjson_inline error_code value::get(std::string_view& out) noexcept { return get_string(false).get(out); } +template<> simdjson_inline error_code value::get(number& out) noexcept { return get_number().get(out); } +template<> simdjson_inline error_code value::get(double& out) noexcept { return get_double().get(out); } +template<> simdjson_inline error_code value::get(uint64_t& out) noexcept { return get_uint64().get(out); } +template<> simdjson_inline error_code value::get(int64_t& out) noexcept { return get_int64().get(out); } +template<> simdjson_inline error_code value::get(bool& out) noexcept { return get_bool().get(out); } #if SIMDJSON_EXCEPTIONS template <class T> @@ -414,6 +422,12 @@ simdjson_inline simdjson_result<bool> simdjson_result<SIMDJSON_IMPLEMENTATION::o return first.is_null(); } +template<> simdjson_inline error_code simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::get<SIMDJSON_IMPLEMENTATION::ondemand::value>(SIMDJSON_IMPLEMENTATION::ondemand::value &out) noexcept { + if (error()) { return error(); } + out = first; + return SUCCESS; +} + template<typename T> simdjson_inline simdjson_result<T> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::get() noexcept { if (error()) { return error(); } return first.get<T>(); @@ -427,11 +441,6 @@ template<> simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::va if (error()) { return error(); } return std::move(first); } -template<> simdjson_inline error_code simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::get<SIMDJSON_IMPLEMENTATION::ondemand::value>(SIMDJSON_IMPLEMENTATION::ondemand::value &out) noexcept { - if (error()) { return error(); } - out = first; - return SUCCESS; -} simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::json_type> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::type() noexcept { if (error()) { return error(); } @@ -465,7 +474,7 @@ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::number> simdj template <class T> simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::operator T() noexcept(false) { if (error()) { throw simdjson_error(error()); } - return static_cast<T>(first); + return first.get<T>(); } simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::operator SIMDJSON_IMPLEMENTATION::ondemand::array() noexcept(false) { if (error()) { throw simdjson_error(error()); } diff --git a/contrib/libs/simdjson/include/simdjson/generic/ondemand/value.h b/contrib/libs/simdjson/include/simdjson/generic/ondemand/value.h index bd6b74ed32..7fa9d1ad25 100644 --- a/contrib/libs/simdjson/include/simdjson/generic/ondemand/value.h +++ b/contrib/libs/simdjson/include/simdjson/generic/ondemand/value.h @@ -5,12 +5,15 @@ #include "simdjson/generic/ondemand/base.h" #include "simdjson/generic/implementation_simdjson_result_base.h" #include "simdjson/generic/ondemand/value_iterator.h" +#include "simdjson/generic/ondemand/deserialize.h" #endif // SIMDJSON_CONDITIONAL_INCLUDE +#include <type_traits> + namespace simdjson { + namespace SIMDJSON_IMPLEMENTATION { namespace ondemand { - /** * An ephemeral JSON value returned during iteration. It is only valid for as long as you do * not access more data in the JSON document. @@ -35,16 +38,21 @@ public: * @returns A value of the given type, parsed from the JSON. * @returns INCORRECT_TYPE If the JSON value is not the given type. */ - template<typename T> simdjson_inline simdjson_result<T> get() noexcept { - // Unless the simdjson library or the user provides an inline implementation, calling this method should - // immediately fail. - static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. " - "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " - "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), " - " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template." - " You may also add support for custom types, see our documentation."); + template <typename T> + simdjson_inline simdjson_result<T> get() +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable<T, value> ? nothrow_custom_deserializable<T, value> : true) +#else + noexcept +#endif + { + static_assert(std::is_default_constructible<T>::value, "The specified type is not default constructible."); + T out{}; + SIMDJSON_TRY(get<T>(out)); + return out; } + /** * Get this value as the given type. * @@ -54,7 +62,32 @@ public: * @returns INCORRECT_TYPE If the JSON value is not an object. * @returns SUCCESS If the parse succeeded and the out parameter was set to the value. */ - template<typename T> simdjson_inline error_code get(T &out) noexcept; + template <typename T> + simdjson_inline error_code get(T &out) +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable<T, value> ? nothrow_custom_deserializable<T, value> : true) +#else + noexcept +#endif + { +#if SIMDJSON_SUPPORTS_DESERIALIZATION + if constexpr (custom_deserializable<T, value>) { + return deserialize(*this, out); + } else { +#endif // SIMDJSON_SUPPORTS_DESERIALIZATION + // Unless the simdjson library or the user provides an inline implementation, calling this method should + // immediately fail. + static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. " + "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " + "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), " + " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template." + " You may also add support for custom types, see our documentation."); + static_cast<void>(out); // to get rid of unused errors + return UNINITIALIZED; +#if SIMDJSON_SUPPORTS_DESERIALIZATION + } +#endif + } /** * Cast this JSON value to an array. @@ -130,6 +163,17 @@ public: * Important: a value should be consumed once. Calling get_string() twice on the same value * is an error. * + * In some instances, you may want to allow replacement of invalid Unicode sequences. + * You may do so by passing the allow_replacement parameter as true. In the following + * example, the string "431924697b\udff0L\u0001Y" is not valid Unicode. By passing true + * to get_string, we allow the replacement of the invalid Unicode sequences with the Unicode + * replacement character (U+FFFD). + * + * simdjson::ondemand::parser parser; + * auto json = R"({"deviceId":"431924697b\udff0L\u0001Y"})"_padded; + * simdjson::ondemand::document doc = parser.iterate(json); + * auto view = doc["deviceId"].get_string(true); + * * @returns An UTF-8 string. The string is stored in the parser and will be invalidated the next * time it parses a document or when it is destroyed. * @returns INCORRECT_TYPE if the JSON value is not a string. @@ -381,6 +425,7 @@ public: simdjson_inline simdjson_result<value> operator[](std::string_view key) noexcept; /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) noexcept; */ simdjson_inline simdjson_result<value> operator[](const char *key) noexcept; + simdjson_result<value> operator[](int) noexcept = delete; /** * Get the type of this JSON value. It does not validate or consume the value. @@ -748,6 +793,7 @@ public: simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> operator[](std::string_view key) noexcept; /** @overload simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field_unordered(std::string_view key) noexcept; */ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> operator[](const char *key) noexcept; + simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> operator[](int) noexcept = delete; /** * Get the type of this JSON value. diff --git a/contrib/libs/simdjson/include/simdjson/generic/ondemand/value_iterator-inl.h b/contrib/libs/simdjson/include/simdjson/generic/ondemand/value_iterator-inl.h index e67bddaeb1..21016f8b97 100644 --- a/contrib/libs/simdjson/include/simdjson/generic/ondemand/value_iterator-inl.h +++ b/contrib/libs/simdjson/include/simdjson/generic/ondemand/value_iterator-inl.h @@ -799,6 +799,8 @@ simdjson_inline simdjson_result<bool> value_iterator::is_root_null(bool check_tr if(result) { // we have something that looks like a null. if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; } advance_root_scalar("null"); + } else if (json[0] == 'n') { + return incorrect_type_error("Not a null but starts with n"); } return result; } diff --git a/contrib/libs/simdjson/include/simdjson/haswell/begin.h b/contrib/libs/simdjson/include/simdjson/haswell/begin.h index 1be8c192c5..2a245cdc20 100644 --- a/contrib/libs/simdjson/include/simdjson/haswell/begin.h +++ b/contrib/libs/simdjson/include/simdjson/haswell/begin.h @@ -4,8 +4,14 @@ #include "simdjson/haswell/intrinsics.h" #if !SIMDJSON_CAN_ALWAYS_RUN_HASWELL +// We enable bmi2 only if LLVM/clang is used, because GCC may not +// make good use of it. See https://github.com/simdjson/simdjson/pull/2243 +#if defined(__clang__) +SIMDJSON_TARGET_REGION("avx2,bmi,bmi2,pclmul,lzcnt,popcnt") +#else SIMDJSON_TARGET_REGION("avx2,bmi,pclmul,lzcnt,popcnt") #endif +#endif #include "simdjson/haswell/bitmanipulation.h" #include "simdjson/haswell/bitmask.h" diff --git a/contrib/libs/simdjson/include/simdjson/jsonpathutil.h b/contrib/libs/simdjson/include/simdjson/jsonpathutil.h new file mode 100644 index 0000000000..afcc74ccc1 --- /dev/null +++ b/contrib/libs/simdjson/include/simdjson/jsonpathutil.h @@ -0,0 +1,64 @@ +#ifndef SIMDJSON_JSONPATHUTIL_H +#define SIMDJSON_JSONPATHUTIL_H + +#include <string> +#include <string_view> + +namespace simdjson { +/** + * Converts JSONPath to JSON Pointer. + * @param json_path The JSONPath string to be converted. + * @return A string containing the equivalent JSON Pointer. + */ +inline std::string json_path_to_pointer_conversion(std::string_view json_path) { + size_t i = 0; + + // if JSONPath starts with $, skip it + if (!json_path.empty() && json_path.front() == '$') { + i = 1; + } + if (json_path.empty() || (json_path[i] != '.' && + json_path[i] != '[')) { + return "-1"; // This is just a sentinel value, the caller should check for this and return an error. + } + + std::string result; + // Reserve space to reduce allocations, adjusting for potential increases due + // to escaping. + result.reserve(json_path.size() * 2); + + while (i < json_path.length()) { + if (json_path[i] == '.') { + result += '/'; + } else if (json_path[i] == '[') { + result += '/'; + ++i; // Move past the '[' + while (i < json_path.length() && json_path[i] != ']') { + if (json_path[i] == '~') { + result += "~0"; + } else if (json_path[i] == '/') { + result += "~1"; + } else { + result += json_path[i]; + } + ++i; + } + if (i == json_path.length() || json_path[i] != ']') { + return "-1"; // Using sentinel value that will be handled as an error by the caller. + } + } else { + if (json_path[i] == '~') { + result += "~0"; + } else if (json_path[i] == '/') { + result += "~1"; + } else { + result += json_path[i]; + } + } + ++i; + } + + return result; +} +} // namespace simdjson +#endif // SIMDJSON_JSONPATHUTIL_H
\ No newline at end of file diff --git a/contrib/libs/simdjson/include/simdjson/lasx/numberparsing_defs.h b/contrib/libs/simdjson/include/simdjson/lasx/numberparsing_defs.h index cb9278261c..3c4020c65a 100644 --- a/contrib/libs/simdjson/include/simdjson/lasx/numberparsing_defs.h +++ b/contrib/libs/simdjson/include/simdjson/lasx/numberparsing_defs.h @@ -36,6 +36,12 @@ simdjson_inline internal::value128 full_multiplication(uint64_t value1, uint64_t } // namespace lasx } // namespace simdjson +#ifndef SIMDJSON_SWAR_NUMBER_PARSING +#if SIMDJSON_IS_BIG_ENDIAN +#define SIMDJSON_SWAR_NUMBER_PARSING 0 +#else #define SIMDJSON_SWAR_NUMBER_PARSING 1 +#endif +#endif #endif // SIMDJSON_LASX_NUMBERPARSING_DEFS_H diff --git a/contrib/libs/simdjson/include/simdjson/lsx/numberparsing_defs.h b/contrib/libs/simdjson/include/simdjson/lsx/numberparsing_defs.h index 1dfe4264e9..4f90203b23 100644 --- a/contrib/libs/simdjson/include/simdjson/lsx/numberparsing_defs.h +++ b/contrib/libs/simdjson/include/simdjson/lsx/numberparsing_defs.h @@ -36,6 +36,12 @@ simdjson_inline internal::value128 full_multiplication(uint64_t value1, uint64_t } // namespace lsx } // namespace simdjson +#ifndef SIMDJSON_SWAR_NUMBER_PARSING +#if SIMDJSON_IS_BIG_ENDIAN +#define SIMDJSON_SWAR_NUMBER_PARSING 0 +#else #define SIMDJSON_SWAR_NUMBER_PARSING 1 +#endif +#endif #endif // SIMDJSON_LSX_NUMBERPARSING_DEFS_H diff --git a/contrib/libs/simdjson/include/simdjson/padded_string-inl.h b/contrib/libs/simdjson/include/simdjson/padded_string-inl.h index abb566fa32..34cc76cb90 100644 --- a/contrib/libs/simdjson/include/simdjson/padded_string-inl.h +++ b/contrib/libs/simdjson/include/simdjson/padded_string-inl.h @@ -53,6 +53,9 @@ inline padded_string::padded_string(const char *data, size_t length) noexcept if ((data != nullptr) && (data_ptr != nullptr)) { std::memcpy(data_ptr, data, length); } + if (data_ptr == nullptr) { + viable_size = 0; + } } #ifdef __cpp_char8_t inline padded_string::padded_string(const char8_t *data, size_t length) noexcept @@ -60,12 +63,17 @@ inline padded_string::padded_string(const char8_t *data, size_t length) noexcept if ((data != nullptr) && (data_ptr != nullptr)) { std::memcpy(data_ptr, reinterpret_cast<const char *>(data), length); } + if (data_ptr == nullptr) { + viable_size = 0; + } } #endif // note: do not pass std::string arguments by value inline padded_string::padded_string(const std::string & str_ ) noexcept : viable_size(str_.size()), data_ptr(internal::allocate_padded_buffer(str_.size())) { - if (data_ptr != nullptr) { + if (data_ptr == nullptr) { + viable_size = 0; + } else { std::memcpy(data_ptr, str_.data(), str_.size()); } } @@ -179,11 +187,11 @@ inline simdjson_result<padded_string> padded_string::load(std::string_view filen } // namespace simdjson -inline simdjson::padded_string operator "" _padded(const char *str, size_t len) { +inline simdjson::padded_string operator ""_padded(const char *str, size_t len) { return simdjson::padded_string(str, len); } #ifdef __cpp_char8_t -inline simdjson::padded_string operator "" _padded(const char8_t *str, size_t len) { +inline simdjson::padded_string operator ""_padded(const char8_t *str, size_t len) { return simdjson::padded_string(reinterpret_cast<const char8_t *>(str), len); } #endif diff --git a/contrib/libs/simdjson/include/simdjson/padded_string.h b/contrib/libs/simdjson/include/simdjson/padded_string.h index 536669b465..b0ab06d276 100644 --- a/contrib/libs/simdjson/include/simdjson/padded_string.h +++ b/contrib/libs/simdjson/include/simdjson/padded_string.h @@ -161,9 +161,9 @@ inline std::ostream& operator<<(std::ostream& out, simdjson_result<padded_string } // namespace simdjson // This is deliberately outside of simdjson so that people get it without having to use the namespace -inline simdjson::padded_string operator "" _padded(const char *str, size_t len); +inline simdjson::padded_string operator ""_padded(const char *str, size_t len); #ifdef __cpp_char8_t -inline simdjson::padded_string operator "" _padded(const char8_t *str, size_t len); +inline simdjson::padded_string operator ""_padded(const char8_t *str, size_t len); #endif namespace simdjson { diff --git a/contrib/libs/simdjson/include/simdjson/padded_string_view-inl.h b/contrib/libs/simdjson/include/simdjson/padded_string_view-inl.h index 1c1811de4c..3c727dbcd6 100644 --- a/contrib/libs/simdjson/include/simdjson/padded_string_view-inl.h +++ b/contrib/libs/simdjson/include/simdjson/padded_string_view-inl.h @@ -53,6 +53,11 @@ inline bool padded_string_view::remove_utf8_bom() noexcept { inline std::ostream& operator<<(std::ostream& out, simdjson_result<padded_string_view> &s) noexcept(false) { return out << s.value(); } #endif +inline padded_string_view pad(std::string& s) noexcept { + const auto len = s.size(); + s.append(SIMDJSON_PADDING, ' '); + return padded_string_view(s.data(), len, s.size()); +} } // namespace simdjson diff --git a/contrib/libs/simdjson/include/simdjson/padded_string_view.h b/contrib/libs/simdjson/include/simdjson/padded_string_view.h index f8dc59a79c..190c98fec7 100644 --- a/contrib/libs/simdjson/include/simdjson/padded_string_view.h +++ b/contrib/libs/simdjson/include/simdjson/padded_string_view.h @@ -83,6 +83,15 @@ public: inline std::ostream& operator<<(std::ostream& out, simdjson_result<padded_string_view> &s) noexcept(false); #endif +/** + * Create a padded_string_view from a string. The string will be padded with SIMDJSON_PADDING + * space characters. The resulting padded_string_view will have a length equal to the original + * string. + * + * @param s The string. + * @return The padded string. + */ +inline padded_string_view pad(std::string& s) noexcept; } // namespace simdjson #endif // SIMDJSON_PADDED_STRING_VIEW_H diff --git a/contrib/libs/simdjson/include/simdjson/portability.h b/contrib/libs/simdjson/include/simdjson/portability.h index ff65aa9deb..5826903db8 100644 --- a/contrib/libs/simdjson/include/simdjson/portability.h +++ b/contrib/libs/simdjson/include/simdjson/portability.h @@ -201,4 +201,43 @@ using std::size_t; #endif + + +#if defined __BYTE_ORDER__ && defined __ORDER_BIG_ENDIAN__ +#define SIMDJSON_IS_BIG_ENDIAN (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) +#elif defined _WIN32 +#define SIMDJSON_IS_BIG_ENDIAN 0 +#else +#if defined(__APPLE__) || defined(__FreeBSD__) +#include <machine/endian.h> +#elif defined(sun) || defined(__sun) +#error #include <sys/byteorder.h> +#elif defined(__MVS__) +#include <sys/endian.h> +#else +#ifdef __has_include +#if __has_include(<endian.h>) +#include <endian.h> +#endif //__has_include(<endian.h>) +#endif //__has_include +#endif +# +#ifndef __BYTE_ORDER__ +// safe choice +#define SIMDJSON_IS_BIG_ENDIAN 0 +#endif +# +#ifndef __ORDER_LITTLE_ENDIAN__ +// safe choice +#define SIMDJSON_IS_BIG_ENDIAN 0 +#endif +# +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +#define SIMDJSON_IS_BIG_ENDIAN 0 +#else +#define SIMDJSON_IS_BIG_ENDIAN 1 +#endif +#endif + + #endif // SIMDJSON_PORTABILITY_H diff --git a/contrib/libs/simdjson/include/simdjson/ppc64/numberparsing_defs.h b/contrib/libs/simdjson/include/simdjson/ppc64/numberparsing_defs.h index 5ec2f60a6e..b41082cdce 100644 --- a/contrib/libs/simdjson/include/simdjson/ppc64/numberparsing_defs.h +++ b/contrib/libs/simdjson/include/simdjson/ppc64/numberparsing_defs.h @@ -60,6 +60,12 @@ simdjson_inline internal::value128 full_multiplication(uint64_t value1, uint64_t } // namespace ppc64 } // namespace simdjson +#ifndef SIMDJSON_SWAR_NUMBER_PARSING +#if SIMDJSON_IS_BIG_ENDIAN +#define SIMDJSON_SWAR_NUMBER_PARSING 0 +#else #define SIMDJSON_SWAR_NUMBER_PARSING 1 +#endif +#endif #endif // SIMDJSON_PPC64_NUMBERPARSING_DEFS_H diff --git a/contrib/libs/simdjson/include/simdjson/simdjson_version.h b/contrib/libs/simdjson/include/simdjson/simdjson_version.h index 059bb9a501..6a1d79631a 100644 --- a/contrib/libs/simdjson/include/simdjson/simdjson_version.h +++ b/contrib/libs/simdjson/include/simdjson/simdjson_version.h @@ -4,7 +4,7 @@ #define SIMDJSON_SIMDJSON_VERSION_H /** The version of simdjson being used (major.minor.revision) */ -#define SIMDJSON_VERSION "3.10.1" +#define SIMDJSON_VERSION "3.11.1" namespace simdjson { enum { @@ -15,7 +15,7 @@ enum { /** * The minor version (major.MINOR.revision) of simdjson being used. */ - SIMDJSON_VERSION_MINOR = 10, + SIMDJSON_VERSION_MINOR = 11, /** * The revision (major.minor.REVISION) of simdjson being used. */ |