JSON-SIMD
view release on metacpan or search on metacpan
simdjson.cpp view on Meta::CPAN
template<typename T>
concept constructible_from_string_view = std::is_constructible_v<T, std::string_view>
&& !std::is_same_v<T, std::string_view>
&& std::is_default_constructible_v<T>;
template<typename M>
concept string_view_keyed_map = string_view_like<typename M::key_type>
&& requires(std::remove_cvref_t<M>& m, typename M::key_type sv, typename M::mapped_type v) {
{ m.emplace(sv, v) } -> std::same_as<std::pair<typename M::iterator, bool>>;
};
/// 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>) && !string_view_keyed_map<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
/* end file simdjson/concepts.h */
/**
* @brief The top level simdjson namespace, containing everything the library provides.
*/
namespace simdjson {
SIMDJSON_PUSH_DISABLE_UNUSED_WARNINGS
/** The maximum document size supported by simdjson. */
constexpr size_t SIMDJSON_MAXSIZE_BYTES = 0xFFFFFFFF;
/**
* The amount of padding needed in a buffer to parse JSON.
*
* The input buf should be readable up to buf + SIMDJSON_PADDING
* this is a stopgap; there should be a better description of the
* main loop and its behavior that abstracts over this
* See https://github.com/simdjson/simdjson/issues/174
*/
constexpr size_t SIMDJSON_PADDING = 64;
/**
* By default, simdjson supports this many nested objects and arrays.
*
* This is the default for parser::max_depth().
*/
constexpr size_t DEFAULT_MAX_DEPTH = 1024;
SIMDJSON_POP_DISABLE_UNUSED_WARNINGS
class implementation;
struct padded_string;
class padded_string_view;
enum class stage1_mode;
namespace internal {
template<typename T>
class atomic_ptr;
class dom_parser_implementation;
class escape_json_string;
simdjson.cpp view on Meta::CPAN
if (ebx & cpuid_avx512er_bit) {
host_isa |= instruction_set::AVX512ER;
}
if (ebx & cpuid_avx512cd_bit) {
host_isa |= instruction_set::AVX512CD;
}
if (ebx & cpuid_avx512bw_bit) {
host_isa |= instruction_set::AVX512BW;
}
if (ebx & cpuid_avx512vl_bit) {
host_isa |= instruction_set::AVX512VL;
}
if (ecx & cpuid_avx512vbmi2_bit) {
host_isa |= instruction_set::AVX512VBMI2;
}
return host_isa;
}
#elif defined(__loongarch_sx) && !defined(__loongarch_asx)
static inline uint32_t detect_supported_architectures() {
return instruction_set::LSX;
}
#elif defined(__loongarch_asx)
static inline uint32_t detect_supported_architectures() {
return instruction_set::LASX;
}
#else // fallback
static inline uint32_t detect_supported_architectures() {
return instruction_set::DEFAULT;
}
#endif // end SIMD extension detection code
} // namespace internal
} // namespace simdjson
#endif // SIMDJSON_INTERNAL_ISADETECTION_H
/* end file internal/isadetection.h */
#include <initializer_list>
#include <type_traits>
namespace simdjson {
bool implementation::supported_by_runtime_system() const {
uint32_t required_instruction_sets = this->required_instruction_sets();
uint32_t supported_instruction_sets = internal::detect_supported_architectures();
return ((supported_instruction_sets & required_instruction_sets) == required_instruction_sets);
}
} // namespace simdjson
/* defining SIMDJSON_CONDITIONAL_INCLUDE */
#define SIMDJSON_CONDITIONAL_INCLUDE
#if SIMDJSON_IMPLEMENTATION_ARM64
/* including simdjson/arm64/implementation.h: #include <simdjson/arm64/implementation.h> */
/* begin file simdjson/arm64/implementation.h */
#ifndef SIMDJSON_ARM64_IMPLEMENTATION_H
#define SIMDJSON_ARM64_IMPLEMENTATION_H
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
/* amalgamation skipped (editor-only): #include "simdjson/base.h" */
/* amalgamation skipped (editor-only): #include "simdjson/implementation.h" */
/* amalgamation skipped (editor-only): #include "simdjson/internal/instruction_set.h" */
/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */
namespace simdjson {
namespace arm64 {
/**
* @private
*/
class implementation final : public simdjson::implementation {
public:
simdjson_inline implementation() : simdjson::implementation("arm64", "ARM NEON", internal::instruction_set::NEON) {}
simdjson_warn_unused error_code create_dom_parser_implementation(
size_t capacity,
size_t max_length,
std::unique_ptr<internal::dom_parser_implementation>& dst
) const noexcept final;
simdjson_warn_unused error_code minify(const uint8_t *buf, size_t len, uint8_t *dst, size_t &dst_len) const noexcept final;
simdjson_warn_unused bool validate_utf8(const char *buf, size_t len) const noexcept final;
};
} // namespace arm64
} // namespace simdjson
#endif // SIMDJSON_ARM64_IMPLEMENTATION_H
/* end file simdjson/arm64/implementation.h */
namespace simdjson {
namespace internal {
static const arm64::implementation* get_arm64_singleton() {
static const arm64::implementation arm64_singleton{};
return &arm64_singleton;
}
} // namespace internal
} // namespace simdjson
#endif // SIMDJSON_IMPLEMENTATION_ARM64
#if SIMDJSON_IMPLEMENTATION_FALLBACK
/* including simdjson/fallback/implementation.h: #include <simdjson/fallback/implementation.h> */
/* begin file simdjson/fallback/implementation.h */
#ifndef SIMDJSON_FALLBACK_IMPLEMENTATION_H
#define SIMDJSON_FALLBACK_IMPLEMENTATION_H
/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */
/* amalgamation skipped (editor-only): #include "simdjson/fallback/base.h" */
simdjson.cpp view on Meta::CPAN
#if SIMDJSON_IMPLEMENTATION_LSX
get_lsx_singleton(),
#endif
#if SIMDJSON_IMPLEMENTATION_LASX
get_lasx_singleton(),
#endif
#if SIMDJSON_IMPLEMENTATION_FALLBACK
get_fallback_singleton(),
#endif
}; // available_implementation_pointers
return available_implementation_pointers;
}
// So we can return UNSUPPORTED_ARCHITECTURE from the parser when there is no support
class unsupported_implementation final : public implementation {
public:
simdjson_warn_unused error_code create_dom_parser_implementation(
size_t,
size_t,
std::unique_ptr<internal::dom_parser_implementation>&
) const noexcept final {
return UNSUPPORTED_ARCHITECTURE;
}
simdjson_warn_unused error_code minify(const uint8_t *, size_t, uint8_t *, size_t &) const noexcept final override {
return UNSUPPORTED_ARCHITECTURE;
}
simdjson_warn_unused bool validate_utf8(const char *, size_t) const noexcept final override {
return false; // Just refuse to validate. Given that we have a fallback implementation
// it seems unlikely that unsupported_implementation will ever be used. If it is used,
// then it will flag all strings as invalid. The alternative is to return an error_code
// from which the user has to figure out whether the string is valid UTF-8... which seems
// like a lot of work just to handle the very unlikely case that we have an unsupported
// implementation. And, when it does happen (that we have an unsupported implementation),
// what are the chances that the programmer has a fallback? Given that *we* provide the
// fallback, it implies that the programmer would need a fallback for our fallback.
}
unsupported_implementation() : implementation("unsupported", "Unsupported CPU (no detected SIMD instructions)", 0) {}
};
static_assert(std::is_trivially_destructible<unsupported_implementation>::value, "unsupported_singleton should be trivially destructible");
const unsupported_implementation* get_unsupported_singleton() {
static const unsupported_implementation unsupported_singleton{};
return &unsupported_singleton;
}
size_t available_implementation_list::size() const noexcept {
return internal::get_available_implementation_pointers().size();
}
const implementation * const *available_implementation_list::begin() const noexcept {
return internal::get_available_implementation_pointers().begin();
}
const implementation * const *available_implementation_list::end() const noexcept {
return internal::get_available_implementation_pointers().end();
}
const implementation *available_implementation_list::detect_best_supported() const noexcept {
// They are prelisted in priority order, so we just go down the list
uint32_t supported_instruction_sets = internal::detect_supported_architectures();
for (const implementation *impl : internal::get_available_implementation_pointers()) {
uint32_t required_instruction_sets = impl->required_instruction_sets();
if ((supported_instruction_sets & required_instruction_sets) == required_instruction_sets) { return impl; }
}
return get_unsupported_singleton(); // this should never happen?
}
const implementation *detect_best_supported_implementation_on_first_use::set_best() const noexcept {
SIMDJSON_PUSH_DISABLE_WARNINGS
SIMDJSON_DISABLE_DEPRECATED_WARNING // Disable CRT_SECURE warning on MSVC: manually verified this is safe
char *force_implementation_name = getenv("SIMDJSON_FORCE_IMPLEMENTATION");
SIMDJSON_POP_DISABLE_WARNINGS
if (force_implementation_name) {
auto force_implementation = get_available_implementations()[force_implementation_name];
if (force_implementation) {
return get_active_implementation() = force_implementation;
} else {
// Note: abort() and stderr usage within the library is forbidden.
return get_active_implementation() = get_unsupported_singleton();
}
}
return get_active_implementation() = get_available_implementations().detect_best_supported();
}
} // namespace internal
SIMDJSON_DLLIMPORTEXPORT const internal::available_implementation_list& get_available_implementations() {
static const internal::available_implementation_list available_implementations{};
return available_implementations;
}
SIMDJSON_DLLIMPORTEXPORT internal::atomic_ptr<const implementation>& get_active_implementation() {
#if SIMDJSON_SINGLE_IMPLEMENTATION
// We immediately select the only implementation we have, skipping the
// detect_best_supported_implementation_on_first_use_singleton.
static internal::atomic_ptr<const implementation> active_implementation{internal::get_single_implementation()};
return active_implementation;
#else
static const internal::detect_best_supported_implementation_on_first_use detect_best_supported_implementation_on_first_use_singleton;
static internal::atomic_ptr<const implementation> active_implementation{&detect_best_supported_implementation_on_first_use_singleton};
return active_implementation;
#endif
}
simdjson_warn_unused error_code minify(const char *buf, size_t len, char *dst, size_t &dst_len) noexcept {
return get_active_implementation()->minify(reinterpret_cast<const uint8_t *>(buf), len, reinterpret_cast<uint8_t *>(dst), dst_len);
}
simdjson_warn_unused bool validate_utf8(const char *buf, size_t len) noexcept {
return get_active_implementation()->validate_utf8(buf, len);
}
const implementation * builtin_implementation() {
static const implementation * builtin_impl = get_available_implementations()[SIMDJSON_STRINGIFY(SIMDJSON_BUILTIN_IMPLEMENTATION)];
assert(builtin_impl);
return builtin_impl;
}
} // namespace simdjson
#endif // SIMDJSON_SRC_IMPLEMENTATION_CPP
/* end file implementation.cpp */
/* defining SIMDJSON_CONDITIONAL_INCLUDE */
( run in 2.746 seconds using v1.01-cache-2.11-cpan-e1769b4cff6 )