mirror of
https://github.com/simdjson/simdjson
synced 2026-06-08 17:27:07 +00:00
3c0d032ded
* tag_invoke based custom types (#2219) * tag_invoke based custom types Now you can use tag_invoke to add a custom type or a group of custom types. * Fixing macro usage + Fixing noexcept * Fixing the usage of #include We don't need <concepts> at all seems like it * Fixing tag_invoke impl for MSVC * Making `tag_invoke` to support `ondemand::document` as well + docs (#2228) * Making `tag_invoke` to support `ondemand::document` as well + docs * Fix typos and doc update by @lemire Co-authored-by: Daniel Lemire <daniel@lemire.me> * Better docs by @lemire Co-authored-by: Daniel Lemire <daniel@lemire.me> * Preserving the old, disallowing in the new I'm disabling `document::get() &&` if the user has provided a `tag_invoke`d version; otherwise, we retain the compatibility. --------- Co-authored-by: Daniel Lemire <daniel@lemire.me> * fix: correct small issues with deserialize (#2232) * Extending the deserialization code with more defaults + docs (#2233) * Make custom types easier with some predefined cases + docs * missing include * adding Ubuntu 24 CXX 20 * using concepts all the way * minor tweak * tiny tweak * tweaks * more tweaking * saving --------- Co-authored-by: Daniel Lemire <dlemire@lemire.me> * Making `tag_invoke` a "put" as opposed to a "get" (#2256) * fix: add tests related to issue 2227 (#2229) * fix: add tests related to issue 2227 * avoiding name clash * pedantic fix * deprecate rvalue get on document * selectively deprecating * Fix ndjson spec link (#2234) * fix ndjson spec link The link in the readme of parse_many links to a casino spam site * fix link * [no-ci] Update README.md * Make simdjson compile again * Enable SIMDJSON_SINGLEHEADER=OFF in VS Code With singleheader on, clangd can't find the right include files. * Add missing include directives to static build targets of simdjson. (#2240) * adding a warning * adding warning regarding SIMDJSON_BUILD_STATIC_LIB * release candidate * pedantic viable size * Making tag_invoke a feeder instead of a producer * adding missing undef silencer (#2253) * Ignore pragma once when amalgamating source files (#2248) With gcc it causes an error in `simdjson.cpp`: ``` simdjson.cpp:548:9: warning: #pragma once in main file 548 | #pragma once | ^~~~ ``` It had previously been commented out in: https://github.com/simdjson/simdjson/commit/6ef555e6fb79363fae057a9a46b52cd208d9e305 However, this was lost in an upgrade: https://github.com/simdjson/simdjson/commit/2a4ff7346813b120f2b5b40e95d69352b593cc9c * Update CI (#2254) * adding missing undef silencer * Updating CI * more fixes * fix * big endian fix * Moving to the new tag_invoke signature * Fix nlohmann ambiguity on C++23-enabled clang * Revert "Merge branch 'master' of https://github.com/simdjson/simdjson into builder_development_branch_extra" This reverts commit3eeecbab34, reversing changes made to6858b208b4. --------- Co-authored-by: Daniel Lemire <daniel@lemire.me> Co-authored-by: Sasha Lopoukhine <superlopuh@gmail.com> Co-authored-by: John Keiser <john@johnkeiser.com> Co-authored-by: Tan Li Boon <undisputed-seraphim@users.noreply.github.com> Co-authored-by: tobil4sk <tobil4sk@outlook.com> * update CI on the builder_development_branch (no code change) (#2262) * typo * General madness simpler, no simpler!!! (#2267) * Minimal tag_invokes for STL types * simpler madness * adding a comment * missing file * minor tweaks to style * fixing incorrect max/min usage * updating single * simplify * validating the idea * putting back the concept * moving the include * guarding * Cheap General Madness (#2268) * Some General Concepts and their deserializations * Resolving ambiguity * Add missing #include * C++20 custom deserializer: better documentation (#2269) * mostly a documentation update. * missing cpp * [no-ci] fix comment * various minor fixes --------- Co-authored-by: Daniel Lemire <dlemire@lemire.me> --------- Co-authored-by: M. Bahoosh <12122474+the-moisrex@users.noreply.github.com> Co-authored-by: Daniel Lemire <dlemire@lemire.me> Co-authored-by: M. Bahoosh <moisrex@gmail.com> * minor update * More documentation regarding builder (#2270) * minor update * more improvment to our documentation (builder branch) * putting back missing functions * merge candidate --------- Co-authored-by: M. Bahoosh <moisrex@gmail.com> Co-authored-by: Daniel Lemire <dlemire@lemire.me> Co-authored-by: Sasha Lopoukhine <superlopuh@gmail.com> Co-authored-by: John Keiser <john@johnkeiser.com> Co-authored-by: Tan Li Boon <undisputed-seraphim@users.noreply.github.com> Co-authored-by: tobil4sk <tobil4sk@outlook.com> Co-authored-by: M. Bahoosh <12122474+the-moisrex@users.noreply.github.com>
167 lines
5.4 KiB
C++
167 lines
5.4 KiB
C++
#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
|