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>
263 lines
6.9 KiB
C++
263 lines
6.9 KiB
C++
#include "simdjson.h"
|
|
#include "test_ondemand.h"
|
|
#include <iostream>
|
|
#include <vector>
|
|
|
|
using namespace simdjson;
|
|
|
|
/**
|
|
* A custom type that we want to parse.
|
|
*/
|
|
struct Car {
|
|
std::string make{};
|
|
std::string model{};
|
|
int64_t year{};
|
|
std::vector<double> tire_pressure{};
|
|
bool operator==(const Car &other) const {
|
|
return make == other.make && model == other.model && year == other.year &&
|
|
tire_pressure == other.tire_pressure;
|
|
}
|
|
};
|
|
|
|
std::ostream &operator<<(std::ostream &os, const Car &c) {
|
|
os << c.make << " " << c.model << " " << c.year << " ";
|
|
for (auto p : c.tire_pressure) {
|
|
os << p << " ";
|
|
}
|
|
return os;
|
|
}
|
|
|
|
#if !SIMDJSON_SUPPORTS_DESERIALIZATION
|
|
// This code is not necessary if you have a C++20 compliant system:
|
|
template <>
|
|
simdjson_inline simdjson_result<std::vector<double>>
|
|
simdjson::ondemand::value::get() noexcept {
|
|
ondemand::array array;
|
|
auto error = get_array().get(array);
|
|
if (error) {
|
|
return error;
|
|
}
|
|
std::vector<double> vec;
|
|
for (auto v : array) {
|
|
double val;
|
|
error = v.get_double().get(val);
|
|
if (error) {
|
|
return error;
|
|
}
|
|
vec.push_back(val);
|
|
}
|
|
return vec;
|
|
}
|
|
#endif
|
|
|
|
template <>
|
|
simdjson_inline simdjson_result<Car> simdjson::ondemand::value::get() noexcept {
|
|
ondemand::object obj;
|
|
auto error = get_object().get(obj);
|
|
if (error) {
|
|
return error;
|
|
}
|
|
Car car;
|
|
if ((error = obj["make"].get_string(car.make))) {
|
|
return error;
|
|
}
|
|
if ((error = obj["model"].get_string(car.model))) {
|
|
return error;
|
|
}
|
|
if ((error = obj["year"].get_int64().get(car.year))) {
|
|
return error;
|
|
}
|
|
if ((error = obj["tire_pressure"].get<std::vector<double>>().get(
|
|
car.tire_pressure))) {
|
|
return error;
|
|
}
|
|
return car;
|
|
}
|
|
|
|
template <>
|
|
simdjson_inline simdjson_result<Car>
|
|
simdjson::ondemand::document::get() &noexcept {
|
|
ondemand::object obj;
|
|
auto error = get_object().get(obj);
|
|
if (error) {
|
|
return error;
|
|
}
|
|
Car car;
|
|
if ((error = obj["make"].get_string(car.make))) {
|
|
return error;
|
|
}
|
|
if ((error = obj["model"].get_string(car.model))) {
|
|
return error;
|
|
}
|
|
if ((error = obj["year"].get_int64().get(car.year))) {
|
|
return error;
|
|
}
|
|
if ((error = obj["tire_pressure"].get<std::vector<double>>().get(
|
|
car.tire_pressure))) {
|
|
return error;
|
|
}
|
|
return car;
|
|
}
|
|
|
|
|
|
template <>
|
|
simdjson_inline simdjson_result<Car>
|
|
simdjson::ondemand::document_reference::get() &noexcept {
|
|
ondemand::object obj;
|
|
auto error = get_object().get(obj);
|
|
if (error) {
|
|
return error;
|
|
}
|
|
Car car;
|
|
if ((error = obj["make"].get_string(car.make))) {
|
|
return error;
|
|
}
|
|
if ((error = obj["model"].get_string(car.model))) {
|
|
return error;
|
|
}
|
|
if ((error = obj["year"].get_int64().get(car.year))) {
|
|
return error;
|
|
}
|
|
if ((error = obj["tire_pressure"].get<std::vector<double>>().get(
|
|
car.tire_pressure))) {
|
|
return error;
|
|
}
|
|
return car;
|
|
}
|
|
|
|
int main_should_compile(void) {
|
|
padded_string json =
|
|
R"( [ { "make": "Toyota", "model": "Camry", "year": 2018,
|
|
"tire_pressure": [ 40.1, 39.9 ] },
|
|
{ "make": "Kia", "model": "Soul", "year": 2012,
|
|
"tire_pressure": [ 30.1, 31.0 ] },
|
|
{ "make": "Toyota", "model": "Tercel", "year": 1999,
|
|
"tire_pressure": [ 29.8, 30.0 ] }
|
|
])"_padded;
|
|
ondemand::parser parser;
|
|
ondemand::document doc;
|
|
[[maybe_unused]] auto doc_error = parser.iterate(json).get(doc);
|
|
for (auto val : doc) {
|
|
#if SIMDJSON_EXCEPTIONS
|
|
Car c(val); // an exception may be thrown
|
|
#else
|
|
Car c;
|
|
if (auto error = val.get<Car>().get(c)) {
|
|
std::cerr << error << std::endl;
|
|
return EXIT_FAILURE;
|
|
}
|
|
#endif
|
|
}
|
|
return EXIT_SUCCESS;
|
|
}
|
|
|
|
namespace car_error_tests {
|
|
bool car_deserialize() {
|
|
TEST_START();
|
|
padded_string json =
|
|
R"( [ { "make": "Toyota", "model": "Camry", "year": 2018,
|
|
"tire_pressure": [ 40.1, 39.9 ] },
|
|
{ "make": "Kia", "model": "Soul", "year": 2012,
|
|
"tire_pressure": [ 30.1, 31.0 ] },
|
|
{ "make": "Toyota", "model": "Tercel", "year": 1999,
|
|
"tire_pressure": [ 29.8, 30.0 ] }
|
|
])"_padded;
|
|
ondemand::parser parser;
|
|
ondemand::document doc;
|
|
[[maybe_unused]] auto doc_error = parser.iterate(json).get(doc);
|
|
std::vector<Car> cars;
|
|
for (auto val : doc) {
|
|
#if SIMDJSON_EXCEPTIONS
|
|
Car c(val); // an exception may be thrown
|
|
#else
|
|
Car c;
|
|
if (auto error = val.get<Car>().get(c)) {
|
|
std::cerr << error << std::endl;
|
|
return EXIT_FAILURE;
|
|
}
|
|
#endif
|
|
cars.push_back(c);
|
|
std::cout << c.make << std::endl;
|
|
}
|
|
std::vector<Car> expected = {{"Toyota", "Camry", 2018, {40.1, 39.9}},
|
|
{"Kia", "Soul", 2012, {30.1, 31.0}},
|
|
{"Toyota", "Tercel", 1999, {29.8, 30.0}}};
|
|
ASSERT_EQUAL(cars.size(), expected.size());
|
|
for (size_t i = 0; i < cars.size(); i++) {
|
|
ASSERT_EQUAL(cars[i], expected[i]);
|
|
}
|
|
TEST_SUCCEED();
|
|
}
|
|
|
|
bool car_doc_deserialize() {
|
|
TEST_START();
|
|
padded_string json = R"( { "make": "Toyota", "model": "Camry", "year": 2018,
|
|
"tire_pressure": [ 40.1, 39.9 ] }
|
|
)"_padded;
|
|
ondemand::parser parser;
|
|
ondemand::document doc;
|
|
[[maybe_unused]] auto doc_error = parser.iterate(json).get(doc);
|
|
#if SIMDJSON_EXCEPTIONS
|
|
Car c(doc); // an exception may be thrown
|
|
#else
|
|
Car c;
|
|
if (auto error = doc.get<Car>().get(c)) {
|
|
std::cerr << error << std::endl;
|
|
return EXIT_FAILURE;
|
|
}
|
|
#endif
|
|
Car expected = {"Toyota", "Camry", 2018, {40.1, 39.9}};
|
|
ASSERT_EQUAL(c, expected);
|
|
TEST_SUCCEED();
|
|
}
|
|
|
|
bool car_stream_deserialize() {
|
|
TEST_START();
|
|
padded_string json =
|
|
R"( { "make": "Toyota", "model": "Camry", "year": 2018,
|
|
"tire_pressure": [ 40.1, 39.9 ] }
|
|
{ "make": "Kia", "model": "Soul", "year": 2012,
|
|
"tire_pressure": [ 30.1, 31.0 ] }
|
|
{ "make": "Toyota", "model": "Tercel", "year": 1999,
|
|
"tire_pressure": [ 29.8, 30.0 ] }
|
|
)"_padded;
|
|
ondemand::parser parser;
|
|
ondemand::document_stream stream;
|
|
auto error = parser.iterate_many(json).get(stream);
|
|
if(error) {
|
|
std::cerr << error << std::endl;
|
|
return EXIT_FAILURE;
|
|
}
|
|
std::vector<Car> cars;
|
|
|
|
#if SIMDJSON_EXCEPTIONS
|
|
for(ondemand::document_reference doc : stream) {
|
|
//Car c(doc); // an exception may be thrown
|
|
cars.push_back(Car(doc)); // an exception may be thrown
|
|
}
|
|
#else
|
|
for(auto doc : stream) {
|
|
Car c;
|
|
if ((error = doc.get<Car>().get(c))) {
|
|
std::cerr << error << std::endl;
|
|
return EXIT_FAILURE;
|
|
}
|
|
cars.push_back(c);
|
|
}
|
|
#endif
|
|
std::vector<Car> expected = {{"Toyota", "Camry", 2018, {40.1, 39.9}},
|
|
{"Kia", "Soul", 2012, {30.1, 31.0}},
|
|
{"Toyota", "Tercel", 1999, {29.8, 30.0}}};
|
|
ASSERT_EQUAL(cars.size(), expected.size());
|
|
for (size_t i = 0; i < cars.size(); i++) {
|
|
ASSERT_EQUAL(cars[i], expected[i]);
|
|
}
|
|
TEST_SUCCEED();
|
|
}
|
|
|
|
bool run() { return car_stream_deserialize() && car_doc_deserialize() && car_deserialize(); }
|
|
} // namespace car_error_tests
|
|
|
|
int main(int argc, char *argv[]) {
|
|
return test_main(argc, argv, car_error_tests::run);
|
|
} |