mirror of
https://github.com/simdjson/simdjson
synced 2026-06-08 17:27:07 +00:00
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| db91f62bd7 | |||
| 20cd6e30ee | |||
| e45d8edbd6 | |||
| 6efb8d81bd | |||
| f562878afc | |||
| 60aa25a0c2 | |||
| d01662560d | |||
| bbb3cb80a6 |
@@ -9,7 +9,6 @@
|
|||||||
#include "simdjson/compiler_check.h"
|
#include "simdjson/compiler_check.h"
|
||||||
#include "simdjson/error.h"
|
#include "simdjson/error.h"
|
||||||
#include "simdjson/portability.h"
|
#include "simdjson/portability.h"
|
||||||
#include "simdjson/concepts.h"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The top level simdjson namespace, containing everything the library provides.
|
* @brief The top level simdjson namespace, containing everything the library provides.
|
||||||
|
|||||||
@@ -50,4 +50,16 @@
|
|||||||
#endif
|
#endif
|
||||||
#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
|
#endif // SIMDJSON_COMPILER_CHECK_H
|
||||||
|
|||||||
@@ -1,18 +0,0 @@
|
|||||||
#ifndef SIMDJSON_CONCEPTS_H
|
|
||||||
#define SIMDJSON_CONCEPTS_H
|
|
||||||
#ifdef __has_include
|
|
||||||
#if __has_include(<version>)
|
|
||||||
#include <version>
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __cpp_concepts
|
|
||||||
// Deliberately empty. In the future, if the library needs to define concepts, it
|
|
||||||
// can be done here.
|
|
||||||
namespace simdjson {
|
|
||||||
namespace concepts {
|
|
||||||
} // namespace concepts
|
|
||||||
} // namespace simdjson
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -3,8 +3,8 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Stuff other things depend on
|
// Stuff other things depend on
|
||||||
#include "simdjson/generic/ondemand/deserialize.h"
|
|
||||||
#include "simdjson/generic/ondemand/base.h"
|
#include "simdjson/generic/ondemand/base.h"
|
||||||
|
#include "simdjson/generic/ondemand/deserialize.h"
|
||||||
#include "simdjson/generic/ondemand/value_iterator.h"
|
#include "simdjson/generic/ondemand/value_iterator.h"
|
||||||
#include "simdjson/generic/ondemand/value.h"
|
#include "simdjson/generic/ondemand/value.h"
|
||||||
#include "simdjson/generic/ondemand/logger.h"
|
#include "simdjson/generic/ondemand/logger.h"
|
||||||
@@ -24,6 +24,9 @@
|
|||||||
#include "simdjson/generic/ondemand/object_iterator.h"
|
#include "simdjson/generic/ondemand/object_iterator.h"
|
||||||
#include "simdjson/generic/ondemand/serialization.h"
|
#include "simdjson/generic/ondemand/serialization.h"
|
||||||
|
|
||||||
|
// Deserialization for standard types
|
||||||
|
#include "simdjson/generic/ondemand/std_deserialize.h"
|
||||||
|
|
||||||
// Inline definitions
|
// Inline definitions
|
||||||
#include "simdjson/generic/ondemand/array-inl.h"
|
#include "simdjson/generic/ondemand/array-inl.h"
|
||||||
#include "simdjson/generic/ondemand/array_iterator-inl.h"
|
#include "simdjson/generic/ondemand/array_iterator-inl.h"
|
||||||
@@ -42,4 +45,4 @@
|
|||||||
#include "simdjson/generic/ondemand/token_iterator-inl.h"
|
#include "simdjson/generic/ondemand/token_iterator-inl.h"
|
||||||
#include "simdjson/generic/ondemand/value_iterator-inl.h"
|
#include "simdjson/generic/ondemand/value_iterator-inl.h"
|
||||||
|
|
||||||
#include "simdjson/generic/ondemand/tag_invoke.h"
|
|
||||||
|
|||||||
@@ -1,20 +1,15 @@
|
|||||||
|
#if SIMDJSON_SUPPORTS_DESERIALIZATION
|
||||||
|
|
||||||
#ifndef SIMDJSON_ONDEMAND_DESERIALIZE_H
|
#ifndef SIMDJSON_ONDEMAND_DESERIALIZE_H
|
||||||
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
#define SIMDJSON_ONDEMAND_DESERIALIZE_H
|
#define SIMDJSON_ONDEMAND_DESERIALIZE_H
|
||||||
|
#include "simdjson/generic/ondemand/base.h"
|
||||||
|
#include "simdjson/generic/ondemand/array.h"
|
||||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||||
#ifdef __has_include
|
|
||||||
#if __has_include(<version>)
|
|
||||||
#include <version>
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __cpp_concepts
|
|
||||||
#include <utility>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
#include <concepts>
|
||||||
namespace simdjson {
|
namespace simdjson {
|
||||||
|
|
||||||
#ifdef __cpp_concepts
|
|
||||||
namespace tag_invoke_fn_ns {
|
namespace tag_invoke_fn_ns {
|
||||||
void tag_invoke();
|
void tag_invoke();
|
||||||
|
|
||||||
@@ -60,20 +55,36 @@ using tag_invoke_result_t =
|
|||||||
|
|
||||||
template <auto &Tag> using tag_t = std::decay_t<decltype(Tag)>;
|
template <auto &Tag> using tag_t = std::decay_t<decltype(Tag)>;
|
||||||
|
|
||||||
namespace SIMDJSON_IMPLEMENTATION {
|
|
||||||
namespace ondemand {
|
|
||||||
class value;
|
|
||||||
class document;
|
|
||||||
}
|
|
||||||
} // namespace SIMDJSON_IMPLEMENTATION
|
|
||||||
|
|
||||||
struct deserialize_tag;
|
struct deserialize_tag;
|
||||||
|
|
||||||
template <typename T, typename ValT = SIMDJSON_IMPLEMENTATION::ondemand::value>
|
/// These types are deserializable in a built-in way
|
||||||
concept deserializable = tag_invocable<deserialize_tag, ValT&, T&>;
|
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>
|
template <typename T, typename ValT = SIMDJSON_IMPLEMENTATION::ondemand::value>
|
||||||
concept nothrow_deserializable = nothrow_tag_invocable<deserialize_tag, ValT&, T&>;
|
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
|
/// Deserialize Tag
|
||||||
inline constexpr struct deserialize_tag {
|
inline constexpr struct deserialize_tag {
|
||||||
@@ -82,23 +93,22 @@ inline constexpr struct deserialize_tag {
|
|||||||
|
|
||||||
// Customization Point for value
|
// Customization Point for value
|
||||||
template <typename T>
|
template <typename T>
|
||||||
requires deserializable<T, value_type>
|
requires custom_deserializable<T, value_type>
|
||||||
[[nodiscard]] constexpr /* error_code */ auto operator()(value_type &object, T& output) const noexcept(nothrow_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);
|
return tag_invoke(*this, object, output);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Customization Point for document
|
// Customization Point for document
|
||||||
template <typename T>
|
template <typename T>
|
||||||
requires deserializable<T, document_type>
|
requires custom_deserializable<T, document_type>
|
||||||
[[nodiscard]] constexpr /* error_code */ auto operator()(document_type &object, T& output) const noexcept(nothrow_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);
|
return tag_invoke(*this, object, output);
|
||||||
}
|
}
|
||||||
|
|
||||||
// default implementations can also be done here
|
|
||||||
} deserialize{};
|
} deserialize{};
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} // namespace simdjson
|
} // namespace simdjson
|
||||||
|
|
||||||
#endif // SIMDJSON_ONDEMAND_DESERIALIZE_H
|
#endif // SIMDJSON_ONDEMAND_DESERIALIZE_H
|
||||||
|
#endif // SIMDJSON_SUPPORTS_DESERIALIZATION
|
||||||
|
|
||||||
|
|||||||
@@ -183,8 +183,8 @@ public:
|
|||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
simdjson_inline simdjson_result<T> get() &
|
simdjson_inline simdjson_result<T> get() &
|
||||||
#ifdef __cpp_concepts
|
#if SIMDJSON_SUPPORTS_DESERIALIZATION
|
||||||
noexcept(deserializable<T, document> ? nothrow_deserializable<T, document> : true)
|
noexcept(custom_deserializable<T, document> ? nothrow_custom_deserializable<T, document> : true)
|
||||||
#else
|
#else
|
||||||
noexcept
|
noexcept
|
||||||
#endif
|
#endif
|
||||||
@@ -206,8 +206,8 @@ public:
|
|||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
simdjson_inline simdjson_result<T> get() &&
|
simdjson_inline simdjson_result<T> get() &&
|
||||||
#ifdef __cpp_concepts
|
#if SIMDJSON_SUPPORTS_DESERIALIZATION
|
||||||
noexcept(deserializable<T, document> ? nothrow_deserializable<T, document> : true)
|
noexcept(custom_deserializable<T, document> ? nothrow_custom_deserializable<T, document> : true)
|
||||||
#else
|
#else
|
||||||
noexcept
|
noexcept
|
||||||
#endif
|
#endif
|
||||||
@@ -229,17 +229,17 @@ public:
|
|||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
simdjson_inline error_code get(T &out) &
|
simdjson_inline error_code get(T &out) &
|
||||||
#ifdef __cpp_concepts
|
#if SIMDJSON_SUPPORTS_DESERIALIZATION
|
||||||
noexcept(deserializable<T, document> ? nothrow_deserializable<T, document> : true)
|
noexcept(custom_deserializable<T, document> ? nothrow_custom_deserializable<T, document> : true)
|
||||||
#else
|
#else
|
||||||
noexcept
|
noexcept
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
#ifdef __cpp_concepts
|
#if SIMDJSON_SUPPORTS_DESERIALIZATION
|
||||||
if constexpr (deserializable<T, document>) {
|
if constexpr (custom_deserializable<T, document>) {
|
||||||
return deserialize(*this, out);
|
return deserialize(*this, out);
|
||||||
} else {
|
} else {
|
||||||
#endif // __cpp_concepts
|
#endif // SIMDJSON_SUPPORTS_DESERIALIZATION
|
||||||
// Unless the simdjson library or the user provides an inline implementation, calling this method should
|
// Unless the simdjson library or the user provides an inline implementation, calling this method should
|
||||||
// immediately fail.
|
// immediately fail.
|
||||||
static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. "
|
static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. "
|
||||||
@@ -249,7 +249,7 @@ public:
|
|||||||
" You may also add support for custom types, see our documentation.");
|
" You may also add support for custom types, see our documentation.");
|
||||||
static_cast<void>(out); // to get rid of unused errors
|
static_cast<void>(out); // to get rid of unused errors
|
||||||
return UNINITIALIZED;
|
return UNINITIALIZED;
|
||||||
#ifdef __cpp_concepts
|
#if SIMDJSON_SUPPORTS_DESERIALIZATION
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,196 @@
|
|||||||
|
#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>
|
||||||
|
#include <limits>
|
||||||
|
#include <list>
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace simdjson {
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
// Number deserialization
|
||||||
|
//////////////////////////////
|
||||||
|
|
||||||
|
template <std::unsigned_integral 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>
|
||||||
|
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>
|
||||||
|
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 list deserialization
|
||||||
|
//////////////////////////////
|
||||||
|
|
||||||
|
template <typename T, typename AllocT, typename ValT>
|
||||||
|
error_code tag_invoke(deserialize_tag, ValT &val,
|
||||||
|
std::list<T, AllocT> &out) noexcept(false) {
|
||||||
|
|
||||||
|
// For better error messages, don't use these as constraints on
|
||||||
|
// the tag_invoke CPO.
|
||||||
|
static_assert(
|
||||||
|
deserializable<T, ValT>,
|
||||||
|
"The specified type inside the list must itself be deserializable");
|
||||||
|
static_assert(
|
||||||
|
std::is_default_constructible_v<T>,
|
||||||
|
"The specified type inside the list must default constructible.");
|
||||||
|
|
||||||
|
SIMDJSON_IMPLEMENTATION::ondemand::array arr;
|
||||||
|
SIMDJSON_TRY(val.get_array().get(arr));
|
||||||
|
for (auto v : arr) {
|
||||||
|
if (auto const err = v.get<T>().get(out.emplace_back()); 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.
|
||||||
|
static_cast<void>(out.pop_back());
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
// std::string deserialization
|
||||||
|
//////////////////////////////
|
||||||
|
|
||||||
|
template <typename CharT,
|
||||||
|
typename TraitsT,
|
||||||
|
typename AllocT,
|
||||||
|
typename ValT>
|
||||||
|
error_code tag_invoke(deserialize_tag, ValT &val, std::basic_string<CharT, TraitsT, AllocT> &out) noexcept(false) {
|
||||||
|
using string_type = std::basic_string<CharT, TraitsT, AllocT>;
|
||||||
|
|
||||||
|
if constexpr (std::same_as<string_type, string_type>) {
|
||||||
|
SIMDJSON_TRY(val.get_string(out));
|
||||||
|
} else {
|
||||||
|
// todo: optimize performance
|
||||||
|
std::string tmp;
|
||||||
|
SIMDJSON_TRY(val.get_string(tmp));
|
||||||
|
for (auto const ch : tmp) {
|
||||||
|
out.push_back(ch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
// STL Vector deserialization
|
||||||
|
//////////////////////////////
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 <typename T, typename AllocT, typename ValT>
|
||||||
|
error_code tag_invoke(deserialize_tag, ValT &val,
|
||||||
|
std::vector<T, AllocT> &out) noexcept(false) {
|
||||||
|
|
||||||
|
// For better error messages, don't use these as constraints on
|
||||||
|
// the tag_invoke CPO.
|
||||||
|
static_assert(
|
||||||
|
deserializable<T, ValT>,
|
||||||
|
"The specified type inside the vector must itself be deserializable");
|
||||||
|
static_assert(
|
||||||
|
std::is_default_constructible_v<T>,
|
||||||
|
"The specified type inside the vector must default constructible.");
|
||||||
|
|
||||||
|
SIMDJSON_IMPLEMENTATION::ondemand::array arr;
|
||||||
|
SIMDJSON_TRY(val.get_array().get(arr));
|
||||||
|
for (auto v : arr) {
|
||||||
|
if (auto const err = v.get<T>().get(out.emplace_back()); 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.
|
||||||
|
static_cast<void>(out.pop_back());
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
// std::unique_ptr deserialization
|
||||||
|
//////////////////////////////
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This CPO (Customization Point Object) will help deserialize into
|
||||||
|
* `unique_ptr`s.
|
||||||
|
*
|
||||||
|
* 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 the error message.
|
||||||
|
*
|
||||||
|
* @tparam T The type inside the unique_ptr
|
||||||
|
* @tparam Deleter The Deleter of the unique_ptr
|
||||||
|
* @tparam ValT document/value type
|
||||||
|
* @param val document/value
|
||||||
|
* @param out output unique_ptr
|
||||||
|
* @return status of the conversion
|
||||||
|
*/
|
||||||
|
template <typename T, typename Deleter, typename ValT>
|
||||||
|
error_code tag_invoke(deserialize_tag, ValT &val,
|
||||||
|
std::unique_ptr<T, Deleter>
|
||||||
|
&out) noexcept(nothrow_deserializable<T, ValT>) {
|
||||||
|
|
||||||
|
// For better error messages, don't use these as constraints on
|
||||||
|
// the tag_invoke CPO.
|
||||||
|
static_assert(
|
||||||
|
deserializable<T, ValT>,
|
||||||
|
"The specified type inside the unique_ptr must itself be deserializable");
|
||||||
|
static_assert(
|
||||||
|
std::is_default_constructible_v<T>,
|
||||||
|
"The specified type inside the unique_ptr must default constructible.");
|
||||||
|
|
||||||
|
auto ptr = new (std::nothrow) T();
|
||||||
|
if (ptr == nullptr) {
|
||||||
|
return MEMALLOC;
|
||||||
|
}
|
||||||
|
SIMDJSON_TRY(val.template get<T>(*ptr));
|
||||||
|
out.reset(ptr);
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
} // namespace simdjson
|
||||||
|
|
||||||
|
#endif // SIMDJSON_ONDEMAND_DESERIALIZE_H
|
||||||
|
#endif // SIMDJSON_SUPPORTS_DESERIALIZATION
|
||||||
@@ -1,96 +0,0 @@
|
|||||||
#ifndef SIMDJSON_TAG_INVOKE_H
|
|
||||||
|
|
||||||
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
|
||||||
#define SIMDJSON_TAG_INVOKE_H
|
|
||||||
#include "simdjson/generic/ondemand/base.h"
|
|
||||||
#include "simdjson/generic/ondemand/deserialize.h"
|
|
||||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
|
||||||
#ifdef __has_include
|
|
||||||
#if __has_include(<version>)
|
|
||||||
#include <version>
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __cpp_concepts
|
|
||||||
#include <utility>
|
|
||||||
#include <vector>
|
|
||||||
#include <list>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides convenience functions for deserialization of common types.
|
|
||||||
*/
|
|
||||||
namespace simdjson {
|
|
||||||
namespace SIMDJSON_IMPLEMENTATION {
|
|
||||||
namespace ondemand {
|
|
||||||
|
|
||||||
template <std::unsigned_integral T>
|
|
||||||
error_code tag_invoke(deserialize_tag, auto &val, T& out) noexcept {
|
|
||||||
uint64_t x;
|
|
||||||
SIMDJSON_TRY(val.get_uint64().get(x));
|
|
||||||
if(x > (std::numeric_limits<T>::max)() || x < (std::numeric_limits<T>::min)()) {
|
|
||||||
return NUMBER_OUT_OF_RANGE;
|
|
||||||
}
|
|
||||||
out = static_cast<T>(x);
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <std::floating_point 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>
|
|
||||||
error_code tag_invoke(deserialize_tag, auto &val, T& out) noexcept {
|
|
||||||
int64_t x;
|
|
||||||
SIMDJSON_TRY(val.get_int64().get(x));
|
|
||||||
if(x > (std::numeric_limits<T>::max)() || x < (std::numeric_limits<T>::min)()) {
|
|
||||||
return NUMBER_OUT_OF_RANGE;
|
|
||||||
}
|
|
||||||
out = static_cast<T>(x);
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
error_code tag_invoke(deserialize_tag, auto &val, std::string& out) noexcept {
|
|
||||||
SIMDJSON_TRY(val.get_string(out));
|
|
||||||
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 <typename T, typename AllocT = std::allocator<T>>
|
|
||||||
error_code tag_invoke(deserialize_tag, auto &val, std::vector<T, AllocT>& out) noexcept {
|
|
||||||
array array;
|
|
||||||
SIMDJSON_TRY(val.get_array().get(array));
|
|
||||||
for (auto v : array) {
|
|
||||||
T value;
|
|
||||||
SIMDJSON_TRY(v.get<T>().get(value));
|
|
||||||
out.push_back(value);
|
|
||||||
}
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, typename AllocT = std::allocator<T>>
|
|
||||||
error_code tag_invoke(deserialize_tag, auto &val, std::list<T, AllocT>& out) noexcept {
|
|
||||||
array array;
|
|
||||||
SIMDJSON_TRY(val.get_array().get(array));
|
|
||||||
for (auto v : array) {
|
|
||||||
T value;
|
|
||||||
SIMDJSON_TRY(v.get<T>().get(value));
|
|
||||||
out.push_back(value);
|
|
||||||
}
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif // __cpp_concepts
|
|
||||||
#endif // SIMDJSON_TAG_INVOKE_H
|
|
||||||
@@ -40,8 +40,8 @@ public:
|
|||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
simdjson_inline simdjson_result<T> get()
|
simdjson_inline simdjson_result<T> get()
|
||||||
#ifdef __cpp_concepts
|
#if SIMDJSON_SUPPORTS_DESERIALIZATION
|
||||||
noexcept(deserializable<T, value> ? nothrow_deserializable<T, value> : true)
|
noexcept(custom_deserializable<T, value> ? nothrow_custom_deserializable<T, value> : true)
|
||||||
#else
|
#else
|
||||||
noexcept
|
noexcept
|
||||||
#endif
|
#endif
|
||||||
@@ -64,17 +64,17 @@ public:
|
|||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
simdjson_inline error_code get(T &out)
|
simdjson_inline error_code get(T &out)
|
||||||
#ifdef __cpp_concepts
|
#if SIMDJSON_SUPPORTS_DESERIALIZATION
|
||||||
noexcept(deserializable<T, value> ? nothrow_deserializable<T, value> : true)
|
noexcept(custom_deserializable<T, value> ? nothrow_custom_deserializable<T, value> : true)
|
||||||
#else
|
#else
|
||||||
noexcept
|
noexcept
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
#ifdef __cpp_concepts
|
#if SIMDJSON_SUPPORTS_DESERIALIZATION
|
||||||
if constexpr (deserializable<T, value>) {
|
if constexpr (custom_deserializable<T, value>) {
|
||||||
return deserialize(*this, out);
|
return deserialize(*this, out);
|
||||||
} else {
|
} else {
|
||||||
#endif // __cpp_concepts
|
#endif // SIMDJSON_SUPPORTS_DESERIALIZATION
|
||||||
// Unless the simdjson library or the user provides an inline implementation, calling this method should
|
// Unless the simdjson library or the user provides an inline implementation, calling this method should
|
||||||
// immediately fail.
|
// immediately fail.
|
||||||
static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. "
|
static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. "
|
||||||
@@ -84,7 +84,7 @@ public:
|
|||||||
" You may also add support for custom types, see our documentation.");
|
" You may also add support for custom types, see our documentation.");
|
||||||
static_cast<void>(out); // to get rid of unused errors
|
static_cast<void>(out); // to get rid of unused errors
|
||||||
return UNINITIALIZED;
|
return UNINITIALIZED;
|
||||||
#ifdef __cpp_concepts
|
#if SIMDJSON_SUPPORTS_DESERIALIZATION
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* auto-generated on 2024-08-01 09:31:50 -0400. Do not edit! */
|
/* auto-generated on 2024-07-15 08:51:57 -0400. Do not edit! */
|
||||||
/* including simdjson.cpp: */
|
/* including simdjson.cpp: */
|
||||||
/* begin file simdjson.cpp */
|
/* begin file simdjson.cpp */
|
||||||
#define SIMDJSON_SRC_SIMDJSON_CPP
|
#define SIMDJSON_SRC_SIMDJSON_CPP
|
||||||
@@ -77,6 +77,18 @@
|
|||||||
#endif
|
#endif
|
||||||
#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
|
#endif // SIMDJSON_COMPILER_CHECK_H
|
||||||
/* end file simdjson/compiler_check.h */
|
/* end file simdjson/compiler_check.h */
|
||||||
/* including simdjson/portability.h: #include "simdjson/portability.h" */
|
/* including simdjson/portability.h: #include "simdjson/portability.h" */
|
||||||
|
|||||||
+7941
-4705
File diff suppressed because it is too large
Load Diff
@@ -30,6 +30,7 @@ add_cpp_test(ondemand_wrong_type_error_tests LABELS ondemand acceptance
|
|||||||
add_cpp_test(ondemand_iterate_many_csv LABELS ondemand acceptance per_implementation)
|
add_cpp_test(ondemand_iterate_many_csv LABELS ondemand acceptance per_implementation)
|
||||||
add_cpp_test(ondemand_custom_types_tests LABELS ondemand acceptance per_implementation)
|
add_cpp_test(ondemand_custom_types_tests LABELS ondemand acceptance per_implementation)
|
||||||
add_cpp_test(ondemand_custom_types_document_tests LABELS ondemand acceptance per_implementation)
|
add_cpp_test(ondemand_custom_types_document_tests LABELS ondemand acceptance per_implementation)
|
||||||
|
add_cpp_test(ondemand_stl_types_tests LABELS ondemand acceptance per_implementation)
|
||||||
if(NOT SIMDJSON_SANITIZE)
|
if(NOT SIMDJSON_SANITIZE)
|
||||||
add_cpp_test(ondemand_cacheline LABELS ondemand acceptance per_implementation)
|
add_cpp_test(ondemand_cacheline LABELS ondemand acceptance per_implementation)
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#ifdef __cpp_concepts
|
#if SIMDJSON_SUPPORTS_DESERIALIZATION
|
||||||
|
|
||||||
namespace simdjson {
|
namespace simdjson {
|
||||||
|
|
||||||
@@ -17,7 +17,7 @@ error_code tag_invoke(deserialize_tag, auto &val, std::unique_ptr<T>& out) {
|
|||||||
|
|
||||||
} // namespace simdjson
|
} // namespace simdjson
|
||||||
|
|
||||||
#endif // __cpp_concepts
|
#endif // SIMDJSON_SUPPORTS_DESERIALIZATION
|
||||||
|
|
||||||
namespace doc_custom_types_tests {
|
namespace doc_custom_types_tests {
|
||||||
#if SIMDJSON_EXCEPTIONS && defined(__cpp_concepts)
|
#if SIMDJSON_EXCEPTIONS && defined(__cpp_concepts)
|
||||||
@@ -63,10 +63,10 @@ struct Car {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(simdjson::deserializable<std::unique_ptr<Car>, simdjson::ondemand::value>, "It should be invocable");
|
static_assert(simdjson::custom_deserializable<std::unique_ptr<Car>, simdjson::ondemand::value>, "It should be invocable");
|
||||||
static_assert(simdjson::deserializable<std::unique_ptr<Car>, simdjson::ondemand::document>, "Tag_invoke should work with document as well.");
|
static_assert(simdjson::custom_deserializable<std::unique_ptr<Car>, simdjson::ondemand::document>, "Tag_invoke should work with document as well.");
|
||||||
static_assert(simdjson::deserializable<std::vector<Car>, simdjson::ondemand::value>, "It should be invocable");
|
static_assert(simdjson::custom_deserializable<std::vector<Car>, simdjson::ondemand::value>, "It should be invocable");
|
||||||
static_assert(simdjson::deserializable<std::vector<Car>, simdjson::ondemand::document>, "Tag_invoke should work with document as well.");
|
static_assert(simdjson::custom_deserializable<std::vector<Car>, simdjson::ondemand::document>, "Tag_invoke should work with document as well.");
|
||||||
|
|
||||||
bool custom_test() {
|
bool custom_test() {
|
||||||
TEST_START();
|
TEST_START();
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#ifdef __cpp_concepts
|
#if SIMDJSON_SUPPORTS_DESERIALIZATION
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct is_unique_ptr : std::false_type {
|
struct is_unique_ptr : std::false_type {
|
||||||
@@ -27,7 +27,7 @@ namespace simdjson {
|
|||||||
// This tag_invoke MUST be inside simdjson namespace
|
// This tag_invoke MUST be inside simdjson namespace
|
||||||
template <typename T>
|
template <typename T>
|
||||||
requires is_unique_ptr_v<T>
|
requires is_unique_ptr_v<T>
|
||||||
auto tag_invoke(deserialize_tag, ondemand::value &val, T& out) {
|
auto tag_invoke(deserialize_tag, auto &val, T& out) {
|
||||||
using type = typename T::element_type;
|
using type = typename T::element_type;
|
||||||
out = std::make_unique<type>(val.template get<type>());
|
out = std::make_unique<type>(val.template get<type>());
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
@@ -36,11 +36,11 @@ auto tag_invoke(deserialize_tag, ondemand::value &val, T& out) {
|
|||||||
} // namespace simdjson
|
} // namespace simdjson
|
||||||
|
|
||||||
|
|
||||||
#endif // __cpp_concepts
|
#endif // SIMDJSON_SUPPORTS_DESERIALIZATION
|
||||||
|
|
||||||
|
|
||||||
namespace custom_types_tests {
|
namespace custom_types_tests {
|
||||||
#if SIMDJSON_EXCEPTIONS && defined(__cpp_concepts)
|
#if SIMDJSON_EXCEPTIONS && SIMDJSON_SUPPORTS_DESERIALIZATION
|
||||||
struct Car {
|
struct Car {
|
||||||
std::string make{};
|
std::string make{};
|
||||||
std::string model{};
|
std::string model{};
|
||||||
@@ -87,7 +87,7 @@ struct Car {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(simdjson::deserializable<std::unique_ptr<Car>>, "It should be deserializable");
|
static_assert(simdjson::custom_deserializable<std::unique_ptr<Car>>, "It should be deserializable");
|
||||||
|
|
||||||
bool custom_uniqueptr_test() {
|
bool custom_uniqueptr_test() {
|
||||||
TEST_START();
|
TEST_START();
|
||||||
@@ -214,7 +214,7 @@ bool custom_no_except() {
|
|||||||
#endif // SIMDJSON_EXCEPTIONS
|
#endif // SIMDJSON_EXCEPTIONS
|
||||||
bool run() {
|
bool run() {
|
||||||
return
|
return
|
||||||
#if SIMDJSON_EXCEPTIONS && defined(__cpp_concepts)
|
#if SIMDJSON_EXCEPTIONS && SIMDJSON_SUPPORTS_DESERIALIZATION
|
||||||
custom_test() &&
|
custom_test() &&
|
||||||
custom_uniqueptr_test() &&
|
custom_uniqueptr_test() &&
|
||||||
custom_no_except() &&
|
custom_no_except() &&
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
#include "simdjson.h"
|
||||||
|
#include "test_ondemand.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace stl_types {
|
||||||
|
#if SIMDJSON_EXCEPTIONS && SIMDJSON_SUPPORTS_DESERIALIZATION
|
||||||
|
|
||||||
|
bool basic_general_madness() {
|
||||||
|
TEST_START();
|
||||||
|
simdjson::padded_string json =
|
||||||
|
R"( [ { "codes": [1.2, 3.4, 5.6, 7.8, 9.0] },
|
||||||
|
{ "codes": [2.2, 4.4, 6.6, 8.8, 10.0] } ])"_padded;
|
||||||
|
|
||||||
|
simdjson::ondemand::parser parser;
|
||||||
|
simdjson::ondemand::document doc = parser.iterate(json);
|
||||||
|
std::vector<std::unique_ptr<float>> codes;
|
||||||
|
for (auto val : doc) {
|
||||||
|
simdjson::ondemand::object obj;
|
||||||
|
SIMDJSON_TRY(val.get_object().get(obj));
|
||||||
|
obj["codes"].get(codes); // append to it
|
||||||
|
}
|
||||||
|
|
||||||
|
if (codes.size() != 10) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (*codes[5] != 2.2f || *codes[7] != 6.6f || *codes[9] != 10.0f) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // SIMDJSON_EXCEPTIONS
|
||||||
|
bool run() {
|
||||||
|
return
|
||||||
|
#if SIMDJSON_EXCEPTIONS && SIMDJSON_SUPPORTS_DESERIALIZATION
|
||||||
|
basic_general_madness() &&
|
||||||
|
#endif // SIMDJSON_EXCEPTIONS
|
||||||
|
true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace stl_types
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
return test_main(argc, argv, stl_types::run);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user