mirror of
https://github.com/simdjson/simdjson
synced 2026-06-08 17:27:07 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0aefa38507 |
@@ -13,15 +13,15 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- {gen: Visual Studio 17 2022, arch: x64, build_type: Debug, cxx: 17}
|
||||
- {gen: Visual Studio 17 2022, arch: x64, build_type: Debug, cxx: 20}
|
||||
- {gen: Visual Studio 17 2022, arch: x64, build_type: Release, cxx: 17}
|
||||
- {gen: Visual Studio 17 2022, arch: x64, build_type: Debug}
|
||||
- {gen: Visual Studio 17 2022, arch: x64, build_type: Release}
|
||||
- {gen: Visual Studio 17 2022, arch: x64, build_type: RelWithDebInfo}
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v4
|
||||
- name: Configure
|
||||
run: |
|
||||
cmake -G "${{matrix.gen}}" -A ${{matrix.arch}} -DSIMDJSON_CXX_STANDARD=${{matrix.cxx}} -T ClangCL -DSIMDJSON_DEVELOPER_MODE=ON -DSIMDJSON_COMPETITION=OFF -B build
|
||||
cmake -G "${{matrix.gen}}" -A ${{matrix.arch}} -T ClangCL -DSIMDJSON_DEVELOPER_MODE=ON -DSIMDJSON_COMPETITION=OFF -B build
|
||||
- name: Build
|
||||
run: cmake --build build --config ${{matrix.build_type}} --verbose
|
||||
- name: Run tests
|
||||
|
||||
@@ -24,35 +24,6 @@ struct simdjson_ondemand {
|
||||
|
||||
BENCHMARK_TEMPLATE(kostya, simdjson_ondemand)->UseManualTime();
|
||||
|
||||
|
||||
#if SIMDJSON_SUPPORTS_EXTRACT
|
||||
using namespace simdjson::ondemand;
|
||||
|
||||
struct simdjson_ondemand_extract {
|
||||
static constexpr diff_flags DiffFlags = diff_flags::NONE;
|
||||
|
||||
ondemand::parser parser{};
|
||||
|
||||
bool run(simdjson::padded_string &json, std::vector<point> &result) {
|
||||
auto doc = parser.iterate(json);
|
||||
for (ondemand::object object_point : doc.find_field("coordinates")) {
|
||||
point p;
|
||||
auto error = object_point.extract(
|
||||
to{"x", p.x},
|
||||
to{"y", p.y},
|
||||
to{"z", p.z}
|
||||
);
|
||||
if(error) { return false; }
|
||||
result.push_back(p);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
BENCHMARK_TEMPLATE(kostya, simdjson_ondemand_extract)->UseManualTime();
|
||||
|
||||
#endif // SIMDJSON_SUPPORTS_EXTRACT
|
||||
|
||||
} // namespace kostya
|
||||
|
||||
#endif // SIMDJSON_EXCEPTIONS
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace partial_tweets {
|
||||
using namespace simdjson;
|
||||
|
||||
struct simdjson_ondemand {
|
||||
using StringType = std::string_view;
|
||||
using StringType=std::string_view;
|
||||
|
||||
ondemand::parser parser{};
|
||||
|
||||
@@ -43,48 +43,6 @@ struct simdjson_ondemand {
|
||||
|
||||
BENCHMARK_TEMPLATE(partial_tweets, simdjson_ondemand)->UseManualTime();
|
||||
|
||||
|
||||
#if SIMDJSON_SUPPORTS_EXTRACT
|
||||
|
||||
using namespace simdjson::ondemand;
|
||||
|
||||
struct simdjson_ondemand_extract {
|
||||
using StringType = std::string_view;
|
||||
ondemand::parser parser{};
|
||||
bool run(simdjson::padded_string &json, std::vector<tweet<std::string_view>> &result) {
|
||||
// Walk the document, parsing the tweets as we go
|
||||
auto doc = parser.iterate(json);
|
||||
for (ondemand::object tweet_object : doc.find_field("statuses")) {
|
||||
tweet<std::string_view> t;
|
||||
auto error = tweet_object.extract(
|
||||
to{"created_at", t.created_at},
|
||||
to{"id", t.id},
|
||||
to{"text", t.result},
|
||||
to{"in_reply_to_status_id", [&t](auto val) {
|
||||
if(val.is_null()) {
|
||||
t.in_reply_to_status_id = 0;
|
||||
} else {
|
||||
t.in_reply_to_status_id = val;
|
||||
}
|
||||
}},
|
||||
to{"user", sub{
|
||||
to{"id", t.user.id},
|
||||
to{"screen_name", t.user.screen_name},
|
||||
}},
|
||||
to{"retweet_count", t.retweet_count},
|
||||
to{"favorite_count", t.favorite_count});
|
||||
if(error) { return false; }
|
||||
result.push_back(t);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
BENCHMARK_TEMPLATE(partial_tweets, simdjson_ondemand_extract)->UseManualTime();
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace partial_tweets
|
||||
|
||||
#endif // SIMDJSON_EXCEPTIONS
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace simdjson {
|
||||
namespace fallback {
|
||||
namespace {
|
||||
|
||||
#if SIMDJSON_REGULAR_VISUAL_STUDIO && !defined(_M_ARM64) && !defined(_M_X64)
|
||||
#if defined(_MSC_VER) && !defined(_M_ARM64) && !defined(_M_X64)
|
||||
static inline unsigned char _BitScanForward64(unsigned long* ret, uint64_t x) {
|
||||
unsigned long x0 = (unsigned long)x, top, bottom;
|
||||
_BitScanForward(&top, (unsigned long)(x >> 32));
|
||||
@@ -28,7 +28,7 @@ static unsigned char _BitScanReverse64(unsigned long* ret, uint64_t x) {
|
||||
|
||||
/* result might be undefined when input_num is zero */
|
||||
simdjson_inline int leading_zeroes(uint64_t input_num) {
|
||||
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||
#ifdef _MSC_VER
|
||||
unsigned long leading_zero = 0;
|
||||
// Search the mask data from most significant bit (MSB)
|
||||
// to least significant bit (LSB) for a set bit (1).
|
||||
@@ -38,7 +38,7 @@ simdjson_inline int leading_zeroes(uint64_t input_num) {
|
||||
return 64;
|
||||
#else
|
||||
return __builtin_clzll(input_num);
|
||||
#endif// SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||
#endif// _MSC_VER
|
||||
}
|
||||
|
||||
} // unnamed namespace
|
||||
|
||||
@@ -15,141 +15,6 @@ namespace simdjson {
|
||||
namespace SIMDJSON_IMPLEMENTATION {
|
||||
namespace ondemand {
|
||||
|
||||
|
||||
#ifdef SIMDJSON_SUPPORTS_EXTRACT
|
||||
|
||||
|
||||
#if SIMDJSON_REGULAR_VISUAL_STUDIO
|
||||
template <endpoint ...Funcs>
|
||||
simdjson_inline error_code object::extract(Funcs&&... endpoints) {
|
||||
return iter.on_field_raw([&, eps = std::make_tuple(std::forward<Funcs>(endpoints)...)](auto field_key, error_code& error) mutable {
|
||||
std::apply([&](auto &...endpoints) {
|
||||
std::ignore = ((field_key.unsafe_is_equal(endpoints.key()) ? (error = endpoints(value(iter.child()))) == SUCCESS : true) && ...);
|
||||
}, eps);
|
||||
if (error) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
#else
|
||||
template <endpoint ...Funcs>
|
||||
simdjson_inline error_code object::extract(Funcs&&... endpoints) noexcept((nothrow_endpoint<Funcs> && ...)) {
|
||||
return iter.on_field_raw([&](auto field_key, error_code& error) noexcept((nothrow_endpoint<Funcs> && ...)) {
|
||||
std::ignore = ((field_key.unsafe_is_equal(endpoints.key()) ? (error = endpoints(value(iter.child()))) == SUCCESS : true) && ...);
|
||||
if (error) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
struct to {
|
||||
private:
|
||||
T *pointer;
|
||||
std::string_view m_key;
|
||||
|
||||
public:
|
||||
constexpr explicit(false)
|
||||
to(std::string_view const inp_key, T &obj_ref) noexcept
|
||||
: pointer{std::addressof(obj_ref)}, m_key{inp_key} {}
|
||||
|
||||
constexpr to(to const &) = default;
|
||||
constexpr to(to &&) noexcept = default;
|
||||
constexpr to &operator=(to const &) = default;
|
||||
constexpr to &operator=(to &&) noexcept = default;
|
||||
constexpr ~to() = default;
|
||||
|
||||
[[nodiscard]] constexpr std::string_view key() const noexcept {
|
||||
return m_key;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr error_code operator()(simdjson_result<value> val) noexcept(
|
||||
std::is_nothrow_assignable_v<T, simdjson_result<value>>) {
|
||||
return val.get<T>(*pointer);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Func>
|
||||
requires(std::is_invocable_v<Func, simdjson_result<value>>)
|
||||
struct to<Func> {
|
||||
private:
|
||||
Func func;
|
||||
std::string_view m_key;
|
||||
|
||||
public:
|
||||
constexpr explicit(false)
|
||||
to(std::string_view const inp_key,
|
||||
Func &&inp_func) noexcept(std::is_nothrow_copy_assignable_v<Func>)
|
||||
: func{std::forward<Func>(inp_func)}, m_key{inp_key} {}
|
||||
|
||||
constexpr to(to const &) = default;
|
||||
constexpr to(to &&) noexcept = default;
|
||||
constexpr to& operator=(to const &) = default;
|
||||
constexpr to& operator=(to &&) noexcept = default;
|
||||
constexpr ~to() = default;
|
||||
|
||||
[[nodiscard]] constexpr std::string_view key() const noexcept {
|
||||
return m_key;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr error_code operator()(simdjson_result<value> val) noexcept(
|
||||
std::is_nothrow_invocable_v<Func, simdjson_result<value>>) {
|
||||
if constexpr (std::is_invocable_r_v<error_code, Func, simdjson_result<value>>) {
|
||||
return func(val);
|
||||
} else {
|
||||
static_cast<void>(func(val));
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Func>
|
||||
requires(std::is_invocable_v<Func, simdjson_result<value>>)
|
||||
to(std::string_view, Func &&) -> to<Func>;
|
||||
|
||||
template <typename T>
|
||||
to(std::string_view, T&) -> to<T>;
|
||||
|
||||
template <endpoint... Tos>
|
||||
struct sub {
|
||||
private:
|
||||
using tuple_type = std::tuple<Tos...>;
|
||||
tuple_type tos;
|
||||
|
||||
public:
|
||||
|
||||
// double templating to make perfect forwarding work
|
||||
template <typename ...T>
|
||||
requires ((std::same_as<T, Tos> && ...))
|
||||
explicit constexpr sub(T&&...inp_tos) noexcept(std::is_nothrow_constructible_v<tuple_type, T...>)
|
||||
: tos{std::forward<T>(inp_tos)...} {}
|
||||
|
||||
constexpr sub(sub const &) = default;
|
||||
constexpr sub(sub &&) noexcept = default;
|
||||
constexpr sub &operator=(sub const &) = default;
|
||||
constexpr sub &operator=(sub &&) = default;
|
||||
constexpr ~sub() = default;
|
||||
|
||||
[[nodiscard]] constexpr error_code operator()(simdjson_result<value> val) noexcept((nothrow_endpoint<Tos> && ...)) {
|
||||
object obj;
|
||||
if (auto const err = val.get_object().get(obj); err) {
|
||||
return err;
|
||||
}
|
||||
return std::apply([&obj]<typename... T>(T &&...app_tos) {
|
||||
return obj.extract(std::forward<T>(app_tos)...);
|
||||
}, tos);
|
||||
}
|
||||
};
|
||||
|
||||
template <endpoint... Tos>
|
||||
sub(Tos&&...) -> sub<Tos...>;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
simdjson_inline simdjson_result<value> object::find_field_unordered(const std::string_view key) & noexcept {
|
||||
bool has_value;
|
||||
SIMDJSON_TRY( iter.find_field_unordered_raw(key).get(has_value) );
|
||||
|
||||
@@ -11,20 +11,6 @@ namespace simdjson {
|
||||
namespace SIMDJSON_IMPLEMENTATION {
|
||||
namespace ondemand {
|
||||
|
||||
#if defined(__cpp_concepts) && defined(__cpp_consteval)
|
||||
#define SIMDJSON_SUPPORTS_EXTRACT 1
|
||||
|
||||
template <typename T>
|
||||
concept endpoint = std::is_invocable_r_v<error_code, T, simdjson_result<value>> &&
|
||||
std::is_copy_constructible_v<T> && requires(T to) {
|
||||
{ to.key() } noexcept -> std::convertible_to<std::string_view>;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
concept nothrow_endpoint = endpoint<T> && std::is_nothrow_invocable_r_v<error_code, T, simdjson_result<value>>;
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* A forward-only JSON object field iterator.
|
||||
*/
|
||||
@@ -79,21 +65,6 @@ public:
|
||||
/** @overload simdjson_inline simdjson_result<value> find_field(std::string_view key) & noexcept; */
|
||||
simdjson_inline simdjson_result<value> find_field(std::string_view key) && noexcept;
|
||||
|
||||
#ifdef SIMDJSON_SUPPORTS_EXTRACT
|
||||
/**
|
||||
* Extract all the fields in one go
|
||||
* Funcs are invocables that take a simdjson_result<value> as input.
|
||||
*/
|
||||
template <endpoint ...Funcs>
|
||||
simdjson_inline error_code extract(Funcs&&... endpoints)
|
||||
#ifndef SIMDJSON_REGULAR_VISUAL_STUDIO // msvc thinks noexcept is not the same in definition
|
||||
noexcept((nothrow_endpoint<Funcs> && ...))
|
||||
#endif
|
||||
;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Look up a field by name on an object, without regard to key order.
|
||||
*
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
#include <type_traits>
|
||||
#ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H
|
||||
|
||||
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
@@ -110,108 +109,6 @@ simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::has_n
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Func>
|
||||
simdjson_warn_unused simdjson_inline error_code value_iterator::on_field_raw(Func&& func)
|
||||
#ifdef __cpp_lib_is_invocable
|
||||
noexcept(std::is_nothrow_invocable_r_v<bool, Func, raw_json_string, error_code&>)
|
||||
#else
|
||||
noexcept(false)
|
||||
#endif
|
||||
{
|
||||
#ifdef __cpp_lib_is_invocable
|
||||
static_assert(std::is_invocable_r_v<bool, Func, raw_json_string, error_code&>, "Invalid function provided.");
|
||||
#endif
|
||||
|
||||
error_code error = SUCCESS;
|
||||
bool has_value;
|
||||
//
|
||||
// Initially, the object can be in one of a few different places:
|
||||
//
|
||||
// 1. The start of the object, at the first field:
|
||||
//
|
||||
// ```
|
||||
// { "a": [ 1, 2 ], "b": [ 3, 4 ] }
|
||||
// ^ (depth 2, index 1)
|
||||
// ```
|
||||
if (at_first_field()) {
|
||||
has_value = true;
|
||||
|
||||
//
|
||||
// 2. When a previous search did not yield a value or the object is empty:
|
||||
//
|
||||
// ```
|
||||
// { "a": [ 1, 2 ], "b": [ 3, 4 ] }
|
||||
// ^ (depth 0)
|
||||
// { }
|
||||
// ^ (depth 0, index 2)
|
||||
// ```
|
||||
//
|
||||
} else if (!is_open()) {
|
||||
#if SIMDJSON_DEVELOPMENT_CHECKS
|
||||
// If we're past the end of the object, we're being iterated out of order.
|
||||
// Note: this is not perfect detection. It's possible the user is inside some other object; if so,
|
||||
// this object iterator will blithely scan that object for fields.
|
||||
if (_json_iter->depth() < depth() - 1) { return OUT_OF_ORDER_ITERATION; }
|
||||
#endif
|
||||
return EMPTY;
|
||||
|
||||
// 3. When a previous search found a field or an iterator yielded a value:
|
||||
//
|
||||
// ```
|
||||
// // When a field was not fully consumed (or not even touched at all)
|
||||
// { "a": [ 1, 2 ], "b": [ 3, 4 ] }
|
||||
// ^ (depth 2)
|
||||
// // When a field was fully consumed
|
||||
// { "a": [ 1, 2 ], "b": [ 3, 4 ] }
|
||||
// ^ (depth 1)
|
||||
// // When the last field was fully consumed
|
||||
// { "a": [ 1, 2 ], "b": [ 3, 4 ] }
|
||||
// ^ (depth 1)
|
||||
// ```
|
||||
//
|
||||
} else {
|
||||
if ((error = skip_child() )) { abandon(); return error; }
|
||||
if ((error = has_next_field().get(has_value) )) { abandon(); return error; }
|
||||
#if SIMDJSON_DEVELOPMENT_CHECKS
|
||||
if (_json_iter->start_position(_depth) != start_position()) { return OUT_OF_ORDER_ITERATION; }
|
||||
#endif
|
||||
}
|
||||
while (has_value) {
|
||||
// Get the key and colon, stopping at the value.
|
||||
raw_json_string actual_key;
|
||||
// size_t max_key_length = _json_iter->peek_length() - 2; // -2 for the two quotes
|
||||
// Note: _json_iter->peek_length() - 2 might overflow if _json_iter->peek_length() < 2.
|
||||
// field_key() advances the pointer and checks that '"' is found (corresponding to a key).
|
||||
// The depth is left unchanged by field_key().
|
||||
if ((error = field_key().get(actual_key) )) { abandon(); return error; };
|
||||
// field_value() will advance and check that we find a ':' separating the
|
||||
// key and the value. It will also increment the depth by one.
|
||||
if ((error = field_value() )) { abandon(); return error; }
|
||||
// If it matches, stop and return
|
||||
// We could do it this way if we wanted to allow arbitrary
|
||||
// key content (including escaped quotes).
|
||||
//if (actual_key.unsafe_is_equal(max_key_length, key)) {
|
||||
// Instead we do the following which may trigger buffer overruns if the
|
||||
// user provides an adversarial key (containing a well placed unescaped quote
|
||||
// character and being longer than the number of bytes remaining in the JSON
|
||||
// input).
|
||||
if (func(actual_key, error)) {
|
||||
break;
|
||||
}
|
||||
|
||||
// The call to skip_child is meant to skip over the value corresponding to the key.
|
||||
// After skip_child(), we are right before the next comma (',') or the final brace ('}').
|
||||
SIMDJSON_TRY( skip_child() ); // Skip the value entirely
|
||||
// The has_next_field() advances the pointer and check that either ',' or '}' is found.
|
||||
// It returns true if ',' is found, false otherwise. If anything other than ',' or '}' is found,
|
||||
// then we are in error and we abort.
|
||||
if ((error = has_next_field().get(has_value) )) { abandon(); return error; }
|
||||
}
|
||||
|
||||
// If the loop ended, we're out of fields to look at.
|
||||
return error;
|
||||
}
|
||||
|
||||
simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::find_field_raw(const std::string_view key) noexcept {
|
||||
error_code error;
|
||||
bool has_value;
|
||||
@@ -1191,4 +1088,4 @@ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value_iterato
|
||||
|
||||
} // namespace simdjson
|
||||
|
||||
#endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H
|
||||
#endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H
|
||||
@@ -6,12 +6,6 @@
|
||||
#include "simdjson/generic/implementation_simdjson_result_base.h"
|
||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
#ifdef __has_include
|
||||
#if __has_include (<version>)
|
||||
#include <version>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace simdjson {
|
||||
namespace SIMDJSON_IMPLEMENTATION {
|
||||
namespace ondemand {
|
||||
@@ -204,22 +198,6 @@ public:
|
||||
*/
|
||||
simdjson_warn_unused simdjson_inline simdjson_result<bool> find_field_raw(const std::string_view key) noexcept;
|
||||
|
||||
|
||||
/**
|
||||
* Runs Func on each key found.
|
||||
* Almost same as `find_field_raw` but it runs `func` instead of checking the key ourselves.
|
||||
*
|
||||
* @param Func func(raw_json_string key, error_code& error) noexcept
|
||||
*/
|
||||
template <typename Func>
|
||||
simdjson_warn_unused simdjson_inline error_code on_field_raw(Func&& func)
|
||||
#ifdef __cpp_lib_is_invocable
|
||||
noexcept(std::is_nothrow_invocable_r_v<bool, Func, raw_json_string, error_code&>)
|
||||
#else
|
||||
noexcept(false)
|
||||
#endif
|
||||
;
|
||||
|
||||
/**
|
||||
* Find the field with the given key without regard to order, and *without* unescaping.
|
||||
*
|
||||
@@ -511,4 +489,4 @@ public:
|
||||
|
||||
} // namespace simdjson
|
||||
|
||||
#endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_H
|
||||
#endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_H
|
||||
@@ -4,7 +4,7 @@
|
||||
#include "simdjson/haswell/intrinsics.h"
|
||||
|
||||
#if !SIMDJSON_CAN_ALWAYS_RUN_HASWELL
|
||||
SIMDJSON_TARGET_REGION("avx2,bmi,pclmul,lzcnt,popcnt")
|
||||
SIMDJSON_TARGET_REGION("avx2,bmi,bmi2,pclmul,lzcnt,popcnt")
|
||||
#endif
|
||||
|
||||
#include "simdjson/haswell/bitmanipulation.h"
|
||||
|
||||
@@ -53,9 +53,6 @@ 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
|
||||
@@ -63,17 +60,12 @@ 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) {
|
||||
viable_size = 0;
|
||||
} else {
|
||||
if (data_ptr != nullptr) {
|
||||
std::memcpy(data_ptr, str_.data(), str_.size());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@ add_cpp_test(ondemand_to_string LABELS ondemand acceptance per_impl
|
||||
add_cpp_test(ondemand_twitter_tests LABELS ondemand acceptance per_implementation)
|
||||
add_cpp_test(ondemand_wrong_type_error_tests LABELS ondemand acceptance per_implementation)
|
||||
add_cpp_test(ondemand_iterate_many_csv LABELS ondemand acceptance per_implementation)
|
||||
add_cpp_test(ondemand_extract_tests LABELS ondemand acceptance per_implementation)
|
||||
if(NOT SIMDJSON_SANITIZE)
|
||||
add_cpp_test(ondemand_cacheline LABELS ondemand acceptance per_implementation)
|
||||
endif()
|
||||
|
||||
@@ -1,116 +0,0 @@
|
||||
#include "simdjson.h"
|
||||
#include "test_ondemand.h"
|
||||
|
||||
using namespace simdjson;
|
||||
|
||||
namespace multi_get_tests {
|
||||
#ifdef __cpp_concepts
|
||||
struct Car {
|
||||
std::string_view make;
|
||||
std::string_view model;
|
||||
std::int64_t year = 0;
|
||||
struct wheel_size_type {
|
||||
std::int64_t front = 0;
|
||||
std::int64_t back = 0;
|
||||
} wheels;
|
||||
|
||||
static simdjson_result<Car> create(auto& value) {
|
||||
using ondemand::to;
|
||||
using ondemand::sub;
|
||||
|
||||
simdjson::ondemand::object obj;
|
||||
auto error = value.get_object().get(obj);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
Car car{};
|
||||
// Instead of this:
|
||||
// for (auto field : obj) {
|
||||
// simdjson::ondemand::raw_json_string key;
|
||||
// error = field.key().get(key);
|
||||
// if (error) {
|
||||
// return error;
|
||||
// }
|
||||
// if (key == "make") {
|
||||
// error = field.value().get_string(car.make);
|
||||
// if (error) {
|
||||
// return error;
|
||||
// }
|
||||
// } else if (key == "model") {
|
||||
// error = field.value().get_string(car.model);
|
||||
// if (error) {
|
||||
// return error;
|
||||
// }
|
||||
// } else if (key == "year") {
|
||||
// error = field.value().get(car.year);
|
||||
// if (error) {
|
||||
// return error;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// we can do this now:
|
||||
error = obj.extract(
|
||||
to{"wheels", sub{
|
||||
to{"front", car.wheels.front},
|
||||
to{"back", car.wheels.back},
|
||||
}},
|
||||
to{"make", car.make},
|
||||
to{"model", car.model},
|
||||
to{"year", [&car](auto val) {
|
||||
car.year = val;
|
||||
}});
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
return car;
|
||||
}
|
||||
};
|
||||
|
||||
bool car_example() {
|
||||
TEST_START();
|
||||
simdjson::padded_string json =
|
||||
R"( [ { "make": "Toyota", "model": "Camry", "year": 2018,
|
||||
"tire_pressure": [ 40.1, 39.9 ], "wheels": { "front": 10, "back": 10 } },
|
||||
{ "make": "Kia", "model": "Soul", "year": 2012,
|
||||
"tire_pressure": [ 30.1, 31.0 ], "wheels": { "front": 10, "back": 10 } },
|
||||
{ "make": "Toyota", "model": "Tercel", "year": 1999,
|
||||
"tire_pressure": [ 29.8, 30.0 ], "wheels": { "front": 10, "back": 10 } }
|
||||
])"_padded;
|
||||
|
||||
simdjson::ondemand::parser parser;
|
||||
simdjson::ondemand::document doc = parser.iterate(json);
|
||||
for (auto val : doc) {
|
||||
auto car = Car::create(val);
|
||||
ASSERT_EQUAL(car.error(), SUCCESS);
|
||||
Car const c(car.value());
|
||||
if (c.make != "Toyota" && c.make != "Kia") {
|
||||
return false;
|
||||
}
|
||||
if (c.model != "Camry" && c.model != "Soul" && c.model != "Tercel") {
|
||||
return false;
|
||||
}
|
||||
if (c.year != 2018 && c.year != 2012 && c.year != 1999) {
|
||||
return false;
|
||||
}
|
||||
if (c.wheels.front != 10 || c.wheels.back != 10) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_SUCCEED();
|
||||
}
|
||||
|
||||
#endif
|
||||
bool run() {
|
||||
return
|
||||
#ifdef __cpp_concepts
|
||||
car_example() &&
|
||||
#endif
|
||||
true;
|
||||
}
|
||||
|
||||
} // namespace multi_get_tests
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
return test_main(argc, argv, multi_get_tests::run);
|
||||
}
|
||||
Reference in New Issue
Block a user