ZeroErr
Loading...
Searching...
No Matches
serialization.h
Go to the documentation of this file.
1#pragma once
2#include <tuple>
4
6
7#include <cstdint>
8#include <stdexcept>
9#include <cstring>
10#include "zeroerr/string.h"
11#include <type_traits>
12#include <vector>
13
15
16namespace zeroerr {
17
44
45struct IRObject {
46 IRObject() noexcept : i(0), others{}, type(Undefined) {}
47 ~IRObject();
48 IRObject(const IRObject& other);
49 IRObject(IRObject&& other) noexcept;
50 IRObject& operator=(const IRObject& other);
51 IRObject& operator=(IRObject&& other) noexcept;
52 void Reset() noexcept;
53
55
56 union {
57 int64_t i;
58 double f;
59 char* s;
60 char ss[8];
61 IRObject* o; // first must be the number of elements
62 };
63 char others[7];
64 unsigned char type;
65
66 template <typename T>
67 typename std::enable_if<std::is_integral<T>::value, T>::type GetScalar() const {
68 return static_cast<T>(i);
69 }
70
71 template <typename T>
72 typename std::enable_if<std::is_floating_point<T>::value, T>::type GetScalar() const {
73 return static_cast<T>(f);
74 }
75
76 template <typename T>
77 typename std::enable_if<std::is_enum<T>::value, T>::type GetScalar() const {
79 }
80
81 template <typename T>
82 typename std::enable_if<detail::StringLike<T>::owning, T>::type GetScalar() const {
83 if (type == Type::String)
84 return T(s);
85 else if (type == Type::ShortString)
86 return T(ss);
87 return "";
88 }
89
90 template <typename T>
91 typename std::enable_if<std::is_integral<T>::value, void>::type SetScalar(T val) {
92 Reset();
93 i = static_cast<int64_t>(val);
95 }
96
97 template <typename T>
98 typename std::enable_if<std::is_floating_point<T>::value, void>::type SetScalar(T val) {
99 Reset();
100 f = static_cast<double>(val);
102 }
103
104 template <typename T>
105 typename std::enable_if<std::is_enum<T>::value, void>::type SetScalar(T val) {
107 }
108
109 template <typename T>
110 typename std::enable_if<detail::StringLike<T>::owning, void>::type SetScalar(T val) {
111 IRObject next;
112 size_t size = val.size();
113 // Keep the terminator inside ss; adjacent padding is not part of the array.
114 if (size >= sizeof(next.ss)) {
115 next.s = alloc_str(size);
116 std::memcpy(next.s, val.data(), size);
117 next.type = Type::String;
118 } else {
119 std::memcpy(next.ss, val.data(), size);
120 next.ss[size] = 0;
121 next.type = Type::ShortString;
122 }
123 *this = std::move(next);
124 }
125
126 void SetScalar(const IRObject& obj) { *this = obj; }
127
128 struct Childrens {
129 int64_t size;
131 };
133 if (type != Type::Object) return {0, nullptr};
134 return {o->i, o + 1};
135 }
136
137 void SetChildren(IRObject* children) {
138 if (!children) throw std::invalid_argument("IRObject children cannot be null");
139 if (type == Type::Object && o == children - 1) return;
140 Reset();
141 o = children - 1;
143 }
144
145 // ================================================================
146
147 template <typename T>
148 static
149 typename std::enable_if<std::is_integral<T>::value || std::is_floating_point<T>::value ||
150 detail::StringLike<T>::owning || std::is_enum<T>::value,
152 FromCorpus(T val) {
153 IRObject obj;
154 obj.SetScalar(val);
155 return obj;
156 }
157
158 template <typename T>
159 static typename std::enable_if<
161 FromCorpus(const T& val) {
162 IRObject* children = alloc(val.size());
163 IRObject obj;
164 obj.SetChildren(children);
165
166 for (const auto& elem : val) {
167 *children++ = IRObject::FromCorpus(elem);
168 }
169 return obj;
170 }
171
172
173 template <class TupType, unsigned... I>
174 inline static void handle_tuple(const TupType& _tup, IRObject* children, detail::seq<I...>) {
175 int _[] = {((children + I)->SetScalar(FromCorpus(std::get<I>(_tup))), 0)...};
176 (void)_;
177 }
178
179 template <typename... Args>
180 static IRObject FromCorpus(const std::tuple<Args...>& val) {
181 unsigned size = sizeof...(Args);
182 IRObject obj;
183 IRObject* children = alloc(size);
184 obj.SetChildren(children);
185
186 handle_tuple(val, children, detail::gen_seq<sizeof...(Args)>{});
187 return obj;
188 }
189
190 template <typename T1, typename T2>
191 static IRObject FromCorpus(const std::pair<T1, T2>& val) {
192 IRObject obj;
193 IRObject* children = alloc(2);
194 obj.SetChildren(children);
195 children[0] = IRObject::FromCorpus(val.first);
196 children[1] = IRObject::FromCorpus(val.second);
197 return obj;
198 }
199
200 template <typename T>
201 static typename std::enable_if<std::is_integral<T>::value || std::is_enum<T>::value, T>::type
202 ToCorpus(const IRObject& obj) {
203 if (obj.type != IRObject::Int) {
204 throw std::runtime_error("Invalid type conversion.");
205 }
206 return obj.GetScalar<T>();
207 }
208
209 template <typename T>
210 static typename std::enable_if<std::is_floating_point<T>::value, T>::type ToCorpus(
211 const IRObject& obj) {
212 if (obj.type != IRObject::Float) {
213 throw std::runtime_error("Invalid type conversion.");
214 }
215 return obj.GetScalar<T>();
216 }
217
218 template <typename T>
219 static typename std::enable_if<detail::StringLike<T>::owning, T>::type ToCorpus(
220 const IRObject& obj) {
221 if (obj.type != IRObject::String && obj.type != IRObject::ShortString) {
222 throw std::runtime_error("Invalid type conversion.");
223 }
224 return obj.GetScalar<T>();
225 }
226
227
228 template <typename TupType, unsigned... I>
229 static TupType parse_tuple(IRObject* children, detail::seq<I...>) {
230 return std::make_tuple(
231 ToCorpus<typename std::tuple_element<I, TupType>::type>(*(children + I))...);
232 }
233
234 template <typename T>
235 static typename std::enable_if<
237 ToCorpus(const IRObject& obj) {
238 if (obj.type != IRObject::Object) {
239 throw std::runtime_error("Invalid type conversion.");
240 }
241
242 auto c = obj.GetChildren();
243
244 T val;
245 for (int i = 0; i < c.size; i++) {
246 val.insert(val.end(), ToCorpus<typename T::value_type>(c.children[i]));
247 }
248 return val;
249 }
250
251
252 template <typename T>
253 static typename std::enable_if<detail::is_specialization<T, std::tuple>::value, T>::type
254 ToCorpus(const IRObject& obj) {
255 if (obj.type != IRObject::Object || obj.GetChildren().size != std::tuple_size<T>::value) {
256 throw std::runtime_error("Invalid type conversion.");
257 }
258 return parse_tuple<T>(obj.o + 1, detail::gen_seq<std::tuple_size<T>::value>{});
259 }
260
261 template <typename T>
262 static typename std::enable_if<detail::is_specialization<T, std::pair>::value, T>::type
263 ToCorpus(const IRObject& obj) {
264 if (obj.type != IRObject::Object || obj.GetChildren().size != 2) {
265 throw std::runtime_error("Invalid type conversion.");
266 }
267 return std::make_pair(ToCorpus<typename T::first_type>(obj.GetChildren().children[0]),
269 }
270
271
272 static char* alloc_str(size_t size);
273 static IRObject* alloc(size_t size);
274
275 // Serialize the object as a string.
276 static zeroerr::String ToString(const IRObject& obj);
278
279 static std::vector<uint8_t> ToBinary(IRObject obj);
280 static IRObject FromBinary(std::vector<uint8_t> bin);
281
282private:
283 void moveFrom(IRObject& other) noexcept;
284};
285
286
287} // namespace zeroerr
288
Definition string.h:41
#define ZEROERR_SUPPRESS_COMMON_WARNINGS_POP
Definition config.h:283
#define ZEROERR_SUPPRESS_COMMON_WARNINGS_PUSH
Definition config.h:235
Definition assert_text.cpp:5
Definition serialization.h:128
int64_t size
Definition serialization.h:129
IRObject * children
Definition serialization.h:130
Interface for serializable objects.
Definition serialization.h:45
IRObject() noexcept
Definition serialization.h:46
static IRObject FromBinary(std::vector< uint8_t > bin)
Definition serialization.cpp:216
static std::enable_if< detail::StringLike< T >::owning, T >::type ToCorpus(const IRObject &obj)
Definition serialization.h:219
static zeroerr::String ToString(const IRObject &obj)
Definition serialization.cpp:198
static std::enable_if< detail::is_specialization< T, std::tuple >::value, T >::type ToCorpus(const IRObject &obj)
Definition serialization.h:254
static void handle_tuple(const TupType &_tup, IRObject *children, detail::seq< I... >)
Definition serialization.h:174
static std::enable_if< std::is_integral< T >::value||std::is_floating_point< T >::value||detail::StringLike< T >::owning||std::is_enum< T >::value, IRObject >::type FromCorpus(T val)
Definition serialization.h:152
std::enable_if< std::is_enum< T >::value, T >::type GetScalar() const
Definition serialization.h:77
void Reset() noexcept
Definition serialization.cpp:6
unsigned char type
Definition serialization.h:64
void SetChildren(IRObject *children)
Definition serialization.h:137
static IRObject FromCorpus(const std::pair< T1, T2 > &val)
Definition serialization.h:191
std::enable_if< detail::StringLike< T >::owning, T >::type GetScalar() const
Definition serialization.h:82
std::enable_if< std::is_enum< T >::value, void >::type SetScalar(T val)
Definition serialization.h:105
Childrens GetChildren() const
Definition serialization.h:132
static TupType parse_tuple(IRObject *children, detail::seq< I... >)
Definition serialization.h:229
std::enable_if< std::is_floating_point< T >::value, T >::type GetScalar() const
Definition serialization.h:72
void SetScalar(const IRObject &obj)
Definition serialization.h:126
static std::vector< uint8_t > ToBinary(IRObject obj)
Definition serialization.cpp:211
IRObject * o
Definition serialization.h:61
static IRObject * alloc(size_t size)
Definition serialization.cpp:70
std::enable_if< std::is_integral< T >::value, void >::type SetScalar(T val)
Definition serialization.h:91
static std::enable_if< detail::is_container< T >::value &&!detail::StringLike< T >::owning, IRObject >::type FromCorpus(const T &val)
Definition serialization.h:161
char others[7]
Definition serialization.h:63
std::enable_if< std::is_integral< T >::value, T >::type GetScalar() const
Definition serialization.h:67
std::enable_if< std::is_floating_point< T >::value, void >::type SetScalar(T val)
Definition serialization.h:98
static IRObject FromString(zeroerr::String str)
Definition serialization.cpp:204
static char * alloc_str(size_t size)
Definition serialization.cpp:76
~IRObject()
Definition serialization.cpp:13
char * s
Definition serialization.h:59
double f
Definition serialization.h:58
static std::enable_if< std::is_floating_point< T >::value, T >::type ToCorpus(const IRObject &obj)
Definition serialization.h:210
static std::enable_if< std::is_integral< T >::value||std::is_enum< T >::value, T >::type ToCorpus(const IRObject &obj)
Definition serialization.h:202
char ss[8]
Definition serialization.h:60
IRObject & operator=(const IRObject &other)
Definition serialization.cpp:40
int64_t i
Definition serialization.h:57
static std::enable_if< detail::is_specialization< T, std::pair >::value, T >::type ToCorpus(const IRObject &obj)
Definition serialization.h:263
static IRObject FromCorpus(const std::tuple< Args... > &val)
Definition serialization.h:180
static std::enable_if< detail::is_container< T >::value &&!detail::StringLike< T >::owning, T >::type ToCorpus(const IRObject &obj)
Definition serialization.h:237
std::enable_if< detail::StringLike< T >::owning, void >::type SetScalar(T val)
Definition serialization.h:110
Type
Definition serialization.h:54
@ Undefined
Definition serialization.h:54
@ ShortString
Definition serialization.h:54
@ Int
Definition serialization.h:54
@ String
Definition serialization.h:54
@ Float
Definition serialization.h:54
@ Object
Definition serialization.h:54
static constexpr bool owning
Definition string.h:35
Definition typetraits.h:77
Definition typetraits.h:115
Definition typetraits.h:74