Skip to content

Commit 5347a93

Browse files
Adding example of how to use tag_invoke for specializing value::get() for pushable containers.
Yet to use reflection in the same style in this branch.
1 parent 5d7ab55 commit 5347a93

4 files changed

Lines changed: 168 additions & 72 deletions

File tree

CMakeLists.txt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ project(experimental_json_builder
88
LANGUAGES CXX
99
)
1010

11-
12-
1311
option(SIMDJSON_SERIALIZER_SANITIZE_MEMORY "Sanitize memory" OFF)
1412

1513
if(SIMDJSON_SERIALIZER_SANITIZE_MEMORY)
@@ -52,9 +50,11 @@ target_include_directories(
5250
)
5351

5452
include(cmake/CPM.cmake)
55-
# include simdjson
56-
CPMAddPackage("gh:simdjson/simdjson@3.9.4")
57-
53+
CPMAddPackage(
54+
NAME simdjson
55+
GITHUB_REPOSITORY the-moisrex/simdjson-custom-types
56+
GIT_TAG master
57+
) # include simdjson
5858

5959
add_subdirectory(examples)
6060
add_subdirectory(benchmarks)

examples/CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,8 @@ target_link_libraries(example PRIVATE simdjson::serialization simdjson::simdjson
66

77
add_executable(example2 example2.cpp)
88
target_link_libraries(example2 PRIVATE simdjson::serialization simdjson::simdjson)
9+
10+
add_executable(example3 example3.cpp)
11+
target_link_libraries(example3 PRIVATE simdjson::serialization simdjson::simdjson)
12+
13+

examples/example2.cpp

Lines changed: 82 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,10 @@
55
#include <iostream>
66
#include <print>
77
#include <string>
8-
#include <vector>
98
#include <type_traits>
9+
#include <vector>
1010
using namespace simdjson;
1111

12-
1312
struct MyStruct {
1413
int id;
1514
std::string name;
@@ -32,59 +31,13 @@ struct X {
3231
Y y;
3332
};
3433

35-
/*
36-
// todo: use reflection to generate
37-
template <>
38-
simdjson_inline simdjson_result<std::vector<int>>
39-
simdjson::ondemand::value::get() noexcept {
40-
ondemand::array array;
41-
auto error = get_array().get(array);
42-
if (error) {
43-
return error;
44-
}
45-
std::vector<int> vec;
46-
for (auto v : array) {
47-
int64_t val;
48-
error = v.get_int64().get(val);
49-
if (error) {
50-
return error;
51-
}
52-
vec.push_back(int(val));
53-
}
54-
return vec;
55-
}
56-
57-
// todo: use reflection to generate
58-
template <>
59-
simdjson_inline simdjson_result<std::vector<std::string>>
60-
simdjson::ondemand::value::get() noexcept {
61-
ondemand::array array;
62-
auto error = get_array().get(array);
63-
if (error) {
64-
return error;
65-
}
66-
std::vector<std::string> vec;
67-
for (auto v : array) {
68-
std::string t;
69-
error = v.get_string(t);
70-
if (error) {
71-
return error;
72-
}
73-
vec.push_back(t);
74-
}
75-
return vec;
76-
}*/
77-
7834
template <typename T>
7935
concept PushableContainer =
80-
requires(T a, typename T::value_type val) {
81-
a.push_back(val);
82-
} && !std::is_same_v<T, std::string> &&
83-
!std::is_same_v<T, std::string_view> &&
84-
!std::is_same_v<T, const char*>;
36+
requires(T a, typename T::value_type val) { a.push_back(val); } &&
37+
!std::is_same_v<T, std::string> && !std::is_same_v<T, std::string_view> &&
38+
!std::is_same_v<T, const char *>;
8539

86-
template <typename T>
87-
requires PushableContainer<T>
40+
template <class T>
8841
simdjson_inline simdjson_result<T> simdjson::ondemand::value::get() noexcept {
8942
ondemand::array array;
9043
auto error = get_array().get(array);
@@ -114,13 +67,15 @@ simdjson_inline simdjson_result<T> simdjson::ondemand::value::get() noexcept {
11467
if (!error) {
11568
val = std::move(str_val);
11669
}
117-
} else if constexpr (std::is_same_v<typename T::value_type, std::string_view>) {
70+
} else if constexpr (std::is_same_v<typename T::value_type,
71+
std::string_view>) {
11872
std::string_view str_view_val;
11973
error = v.get_string(str_view_val, false);
12074
if (!error) {
12175
val = str_view_val;
12276
}
123-
} else if constexpr (std::is_same_v<typename T::value_type, simdjson::ondemand::raw_json_string>) {
77+
} else if constexpr (std::is_same_v<typename T::value_type,
78+
simdjson::ondemand::raw_json_string>) {
12479
simdjson::ondemand::raw_json_string raw_val;
12580
error = v.get_raw_json_string().get(raw_val);
12681
if (!error) {
@@ -138,16 +93,65 @@ simdjson_inline simdjson_result<T> simdjson::ondemand::value::get() noexcept {
13893
return container;
13994
}
14095

141-
// Specialization for std::vector<int>
142-
template <>
143-
simdjson_inline simdjson_result<std::vector<int> > simdjson::ondemand::value::get() noexcept {
144-
return get<std::vector<int>>();
145-
}
96+
template <typename T>
97+
simdjson_inline simdjson_result<T>
98+
simdjson::ondemand::document::get() & noexcept {
99+
if constexpr (PushableContainer<T>) {
100+
ondemand::array array;
101+
auto error = get_array().get(array);
102+
if (error) {
103+
return error;
104+
}
105+
T container;
106+
for (auto v : array) {
107+
typename T::value_type val;
108+
if constexpr (std::is_same_v<typename T::value_type, double>) {
109+
error = v.get_double().get(val);
110+
} else if constexpr (std::is_same_v<typename T::value_type, bool>) {
111+
error = v.get_bool().get(val);
112+
} else if constexpr (std::is_same_v<typename T::value_type, uint64_t>) {
113+
error = v.get_uint64().get(val);
114+
} else if constexpr (std::is_same_v<typename T::value_type, int64_t>) {
115+
error = v.get_int64().get(val);
116+
} else if constexpr (std::is_same_v<typename T::value_type, int>) {
117+
int64_t temp_val;
118+
error = v.get_int64().get(temp_val);
119+
if (!error) {
120+
val = static_cast<int>(temp_val);
121+
}
122+
} else if constexpr (std::is_same_v<typename T::value_type, std::string>) {
123+
std::string str_val;
124+
error = v.get_string(str_val);
125+
if (!error) {
126+
val = std::move(str_val);
127+
}
128+
} else if constexpr (std::is_same_v<typename T::value_type,
129+
std::string_view>) {
130+
std::string_view str_view_val;
131+
error = v.get_string(str_view_val, false);
132+
if (!error) {
133+
val = str_view_val;
134+
}
135+
} else if constexpr (std::is_same_v<typename T::value_type,
136+
simdjson::ondemand::raw_json_string>) {
137+
simdjson::ondemand::raw_json_string raw_val;
138+
error = v.get_raw_json_string().get(raw_val);
139+
if (!error) {
140+
val = raw_val;
141+
}
142+
} else {
143+
static_assert(!sizeof(T), "Unsupported value type in the container.");
144+
}
146145

147-
// Specialization for std::vector<std::string>
148-
template <>
149-
simdjson_inline simdjson_result<std::vector<std::string> > simdjson::ondemand::value::get() noexcept {
150-
return get<std::vector<std::string>>();
146+
if (error) {
147+
return error;
148+
}
149+
container.push_back(std::move(val));
150+
}
151+
return container;
152+
} else {
153+
static_assert(!sizeof(T), "Unsupported container type.");
154+
}
151155
}
152156

153157
template <>
@@ -216,7 +220,7 @@ simdjson::ondemand::document::get() & noexcept {
216220
return error;
217221
}
218222
} else if (key == "values") {
219-
error = field.value().get<std::vector<int>>().get(s.values);
223+
error = field.value().get<std::vector<int>>().get(s.values);
220224
if (error) {
221225
return error;
222226
}
@@ -376,8 +380,20 @@ simdjson::ondemand::document::get() & noexcept {
376380
return x;
377381
}
378382

383+
void demo() {
384+
std::vector<std::string> vec;
385+
std::string json_str = R"(["a", "b", "c"])";
386+
ondemand::parser parser;
387+
ondemand::document doc = parser.iterate(json_str);
388+
std::vector<std::string> result = doc.get<std::vector<std::string>>();
389+
for (auto x : result) {
390+
std::cout << x << std::endl;
391+
}
392+
}
379393

380394
int main() {
395+
demo();
396+
381397
std::string json_str = R"({"id": 1, "name": "example", "values": [1, 2, 3]})";
382398
ondemand::parser parser;
383399
ondemand::document doc = parser.iterate(json_str);
@@ -387,15 +403,14 @@ int main() {
387403
simdjson::json_builder::fast_to_json_string(sb, my_struct);
388404
std::cout << sb.c_str() << std::endl;
389405

390-
/*
391406
std::string json_str_nested =
392407
R"({"a":1,"b":10,"c":0,"d":"test string\n\r\"","e":[1,2,3],"f":["ab","cd","fg"],"y":{"g":100,"h":"test string\n\r\"","i":[1,2,3]}})";
393408
doc = parser.iterate(json_str_nested);
394409

395410
X s1 = X(doc);
396411
simdjson::json_builder::StringBuilder sb2;
397412
simdjson::json_builder::fast_to_json_string(sb2, s1);
398-
std::cout << sb2.c_str() << std::endl;*/
413+
std::cout << sb2.c_str() << std::endl;
399414

400415
return 0;
401-
}
416+
}

examples/example3.cpp

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
#include "simdjson.h"
2+
#include <string>
3+
#include <vector>
4+
#include <iostream>
5+
#include <type_traits>
6+
7+
using namespace simdjson;
8+
9+
namespace simdjson {
10+
11+
template <typename T>
12+
concept PushableContainer =
13+
requires(T a, typename T::value_type val) {
14+
a.push_back(val);
15+
} && !std::is_same_v<T, std::string> &&
16+
!std::is_same_v<T, std::string_view> &&
17+
!std::is_same_v<T, const char*>;
18+
19+
// Specialize tag_invoke for std::vector<int>
20+
template <typename T>
21+
requires PushableContainer<T>
22+
simdjson_result<T>
23+
tag_invoke(deserialize_tag, std::type_identity<T>, ondemand::value &val) {
24+
T vec;
25+
auto array_result = val.get_array();
26+
if (array_result.error()) return array_result.error();
27+
ondemand::array array = array_result.value();
28+
29+
for (auto v : array) {
30+
typename T::value_type element;
31+
if constexpr (std::is_same_v<typename T::value_type, int>) {
32+
auto int_result = v.get_int64();
33+
if (int_result.error()) return int_result.error();
34+
element = static_cast<int>(int_result.value());
35+
} else if constexpr (std::is_same_v<typename T::value_type, double>) {
36+
auto double_result = v.get_double();
37+
if (double_result.error()) return double_result.error();
38+
element = double_result.value();
39+
} else if constexpr (std::is_same_v<typename T::value_type, std::string>) {
40+
auto string_result = v.get_string();
41+
if (string_result.error()) return string_result.error();
42+
element = std::string(string_result.value());
43+
} else if constexpr (std::is_same_v<typename T::value_type, bool>) {
44+
auto bool_result = v.get_bool();
45+
if (bool_result.error()) return bool_result.error();
46+
element = bool_result.value();
47+
} else {
48+
// Unsupported type
49+
static_assert(!std::is_same_v<T, T>, "Unsupported type in JSON array");
50+
}
51+
vec.push_back(std::move(element));
52+
}
53+
54+
return vec;
55+
}
56+
57+
} // namespace simdjson
58+
59+
int main() {
60+
std::string json_str = R"({"values": [1, 2, 3]})";
61+
ondemand::parser parser;
62+
auto doc = parser.iterate(json_str);
63+
64+
auto result = doc["values"].get<std::vector<int>>();
65+
if (result.error()) {
66+
std::cerr << "Error parsing JSON: " << result.error() << std::endl;
67+
return 1;
68+
}
69+
70+
std::vector<int> my_struct = result.value();
71+
for (const int &x : my_struct) {
72+
std::cout << x << std::endl;
73+
}
74+
75+
return 0;
76+
}

0 commit comments

Comments
 (0)