ZeroErr
serialization.h
Go to the documentation of this file.
1 #pragma once
3 
5 
6 #include <cstdint>
7 #include <cstring>
8 #include <string>
9 #include <type_traits>
10 #include <vector>
11 
13 
14 namespace zeroerr {
15 
16 
17 struct IRObject {
18  IRObject() { std::memset(this, 0, sizeof(IRObject)); }
19  ~IRObject() {}
20  IRObject(const IRObject& other) { *this = other; }
21  IRObject(IRObject&& other) { *this = std::move(other); }
22  IRObject& operator=(const IRObject& other) {
23  std::memcpy(this, &other, sizeof(IRObject));
24  return *this;
25  }
27  std::memcpy(this, &other, sizeof(IRObject));
28  std::memset(&other, 0, sizeof(IRObject));
29  return *this;
30  }
31 
33 
34  union {
35  int64_t i;
36  double f;
37  char* s;
38  char ss[8];
39  IRObject* o; // first must be the number of elements
40  };
41  char others[7];
42  unsigned type;
43 
44  template <typename T>
45  typename std::enable_if<std::is_integral<T>::value, T>::type GetScalar() {
46  return static_cast<T>(i);
47  }
48 
49  template <typename T>
50  typename std::enable_if<std::is_floating_point<T>::value, T>::type GetScalar() {
51  return static_cast<T>(f);
52  }
53 
54  template <typename T>
55  typename std::enable_if<std::is_enum<T>::value, T>::type GetScalar() {
56  return GetScalar<typename std::underlying_type<T>::type>();
57  }
58 
59  template <typename T>
60  typename std::enable_if<std::is_same<T, std::string>::value, T>::type GetScalar() {
61  if (type == Type::String)
62  return std::string(s);
63  else if (type == Type::ShortString)
64  return std::string(ss);
65  return "";
66  }
67 
68  template <typename T>
69  typename std::enable_if<std::is_integral<T>::value, void>::type SetScalar(T val) {
70  i = static_cast<int64_t>(val);
71  type = Type::Int;
72  }
73 
74  template <typename T>
75  typename std::enable_if<std::is_floating_point<T>::value, void>::type SetScalar(T val) {
76  f = static_cast<double>(val);
77  type = Type::Float;
78  }
79 
80  template <typename T>
81  typename std::enable_if<std::is_enum<T>::value, void>::type SetScalar(T val) {
82  SetScalar<typename std::underlying_type<T>::type>(val);
83  }
84 
85  template <typename T>
86  typename std::enable_if<std::is_same<T, std::string>::value, void>::type SetScalar(T val) {
87  size_t size = val.size();
88  if (size > 14) {
89  s = alloc_str(size);
90  strcpy(s, val.c_str());
91  type = Type::String;
92  } else {
93  strcpy(ss, val.c_str());
94  ss[size] = 0;
95  type = Type::ShortString;
96  }
97  }
98 
99  void SetScalar(const IRObject& obj) { *this = obj; }
100 
101  struct Childrens {
102  int64_t size;
104  };
105  Childrens GetChildren() { return {o->i, o + 1}; }
106 
107  void SetChildren(IRObject* children) {
108  o = children - 1;
109  type = Type::Object;
110  }
111 
112  // ================================================================
113 
114  template <typename T>
115  static
116  typename std::enable_if<std::is_integral<T>::value || std::is_floating_point<T>::value ||
117  std::is_same<T, std::string>::value || std::is_enum<T>::value,
119  FromCorpus(T val) {
120  IRObject obj;
121  obj.SetScalar(val);
122  return obj;
123  }
124 
125  template <typename T>
126  static typename std::enable_if<
127  detail::is_container<T>::value && !std::is_same<T, std::string>::value, IRObject>::type
128  FromCorpus(const T& val) {
129  IRObject* children = alloc(val.size());
130  IRObject obj;
131  obj.SetChildren(children);
132 
133  for (const auto& elem : val) {
134  *children++ = IRObject::FromCorpus(elem);
135  }
136  return obj;
137  }
138 
139 
140  template <class TupType, unsigned... I>
141  inline static void handle_tuple(const TupType& _tup, IRObject* children, detail::seq<I...>) {
142  int _[] = {((children + I)->SetScalar(FromCorpus(std::get<I>(_tup))), 0)...};
143  (void)_;
144  }
145 
146  template <typename... Args>
147  static IRObject FromCorpus(const std::tuple<Args...>& val) {
148  unsigned size = sizeof...(Args);
149  IRObject obj;
150  IRObject* children = alloc(size);
151  obj.SetChildren(children);
152 
153  handle_tuple(val, children, detail::gen_seq<sizeof...(Args)>{});
154  return obj;
155  }
156 
157  template <typename T1, typename T2>
158  static IRObject FromCorpus(const std::pair<T1, T2>& val) {
159  IRObject obj;
160  IRObject* children = alloc(2);
161  obj.SetChildren(children);
162  children[0] = IRObject::FromCorpus(val.first);
163  children[1] = IRObject::FromCorpus(val.second);
164  return obj;
165  }
166 
167  template <typename T>
168  static typename std::enable_if<std::is_integral<T>::value || std::is_enum<T>::value, T>::type
170  if (obj.type != IRObject::Int) {
171  throw std::runtime_error("Invalid type conversion.");
172  }
173  return obj.GetScalar<T>();
174  }
175 
176  template <typename T>
177  static typename std::enable_if<std::is_floating_point<T>::value, T>::type ToCorpus(
178  IRObject obj) {
179  if (obj.type != IRObject::Float) {
180  throw std::runtime_error("Invalid type conversion.");
181  }
182  return obj.GetScalar<T>();
183  }
184 
185  template <typename T>
186  static typename std::enable_if<std::is_same<T, std::string>::value, T>::type ToCorpus(
187  IRObject obj) {
188  if (obj.type != IRObject::String && obj.type != IRObject::ShortString) {
189  throw std::runtime_error("Invalid type conversion.");
190  }
191  return obj.GetScalar<T>();
192  }
193 
194 
195  template <typename TupType, unsigned... I>
196  static TupType parse_tuple(IRObject* children, detail::seq<I...>) {
197  return std::make_tuple(
198  ToCorpus<typename std::tuple_element<I, TupType>::type>(*(children + I))...);
199  }
200 
201  template <typename T>
202  static typename std::enable_if<
203  detail::is_container<T>::value && !std::is_same<T, std::string>::value, T>::type
205  if (obj.type != IRObject::Object) {
206  throw std::runtime_error("Invalid type conversion.");
207  }
208 
209  auto c = obj.GetChildren();
210 
211  T val;
212  for (int i = 0; i < c.size; i++) {
213  val.insert(val.end(), ToCorpus<typename T::value_type>(c.children[i]));
214  }
215  return val;
216  }
217 
218 
219  template <typename T>
220  static typename std::enable_if<detail::is_specialization<T, std::tuple>::value, T>::type
222  if (obj.type != IRObject::Object || obj.GetChildren().size != std::tuple_size<T>::value) {
223  throw std::runtime_error("Invalid type conversion.");
224  }
225  return parse_tuple<T>(obj.o + 1, detail::gen_seq<std::tuple_size<T>::value>{});
226  }
227 
228  template <typename T>
229  static typename std::enable_if<detail::is_specialization<T, std::pair>::value, T>::type
231  if (obj.type != IRObject::Object || obj.GetChildren().size != 2) {
232  throw std::runtime_error("Invalid type conversion.");
233  }
234  return std::make_pair(ToCorpus<typename T::first_type>(obj.GetChildren().children[0]),
235  ToCorpus<typename T::second_type>(obj.GetChildren().children[1]));
236  }
237 
238 
239  static char* alloc_str(size_t size);
240  static IRObject* alloc(size_t size);
241 
242  // Serialize the object as a string.
243  static std::string ToString(IRObject obj);
244  static IRObject FromString(std::string str);
245 
246  static std::vector<uint8_t> ToBinary(IRObject obj);
247  static IRObject FromBinary(std::vector<uint8_t> bin);
248 };
249 
250 
251 } // namespace zeroerr
252 
#define ZEROERR_SUPPRESS_COMMON_WARNINGS_POP
Definition: config.h:265
#define ZEROERR_SUPPRESS_COMMON_WARNINGS_PUSH
Definition: config.h:218
Definition: benchmark.cpp:17
Definition: serialization.h:101
int64_t size
Definition: serialization.h:102
IRObject * children
Definition: serialization.h:103
Definition: serialization.h:17
static std::enable_if< std::is_integral< T >::value||std::is_enum< T >::value, T >::type ToCorpus(IRObject obj)
Definition: serialization.h:169
static IRObject FromBinary(std::vector< uint8_t > bin)
Definition: serialization.cpp:151
static void handle_tuple(const TupType &_tup, IRObject *children, detail::seq< I... >)
Definition: serialization.h:141
static std::enable_if< std::is_integral< T >::value||std::is_floating_point< T >::value||std::is_same< T, std::string >::value||std::is_enum< T >::value, IRObject >::type FromCorpus(T val)
Definition: serialization.h:119
IRObject()
Definition: serialization.h:18
static std::enable_if< detail::is_container< T >::value &&!std::is_same< T, std::string >::value, T >::type ToCorpus(IRObject obj)
Definition: serialization.h:204
void SetChildren(IRObject *children)
Definition: serialization.h:107
static IRObject FromCorpus(const std::pair< T1, T2 > &val)
Definition: serialization.h:158
std::enable_if< std::is_enum< T >::value, void >::type SetScalar(T val)
Definition: serialization.h:81
std::enable_if< std::is_enum< T >::value, T >::type GetScalar()
Definition: serialization.h:55
std::enable_if< std::is_same< T, std::string >::value, void >::type SetScalar(T val)
Definition: serialization.h:86
static std::enable_if< std::is_floating_point< T >::value, T >::type ToCorpus(IRObject obj)
Definition: serialization.h:177
Childrens GetChildren()
Definition: serialization.h:105
static TupType parse_tuple(IRObject *children, detail::seq< I... >)
Definition: serialization.h:196
void SetScalar(const IRObject &obj)
Definition: serialization.h:99
static std::string ToString(IRObject obj)
Definition: serialization.cpp:133
static std::vector< uint8_t > ToBinary(IRObject obj)
Definition: serialization.cpp:146
IRObject & operator=(const IRObject &other)
Definition: serialization.h:22
static std::enable_if< detail::is_specialization< T, std::pair >::value, T >::type ToCorpus(IRObject obj)
Definition: serialization.h:230
IRObject * o
Definition: serialization.h:39
static IRObject * alloc(size_t size)
Definition: serialization.cpp:7
std::enable_if< std::is_same< T, std::string >::value, T >::type GetScalar()
Definition: serialization.h:60
static IRObject FromString(std::string str)
Definition: serialization.cpp:139
IRObject(IRObject &&other)
Definition: serialization.h:21
char others[7]
Definition: serialization.h:41
std::enable_if< std::is_floating_point< T >::value, void >::type SetScalar(T val)
Definition: serialization.h:75
std::enable_if< std::is_integral< T >::value, void >::type SetScalar(T val)
Definition: serialization.h:69
static char * alloc_str(size_t size)
Definition: serialization.cpp:13
static std::enable_if< std::is_same< T, std::string >::value, T >::type ToCorpus(IRObject obj)
Definition: serialization.h:186
~IRObject()
Definition: serialization.h:19
char * s
Definition: serialization.h:37
double f
Definition: serialization.h:36
IRObject(const IRObject &other)
Definition: serialization.h:20
static std::enable_if< detail::is_specialization< T, std::tuple >::value, T >::type ToCorpus(IRObject obj)
Definition: serialization.h:221
char ss[8]
Definition: serialization.h:38
int64_t i
Definition: serialization.h:35
IRObject & operator=(IRObject &&other)
Definition: serialization.h:26
static IRObject FromCorpus(const std::tuple< Args... > &val)
Definition: serialization.h:147
std::enable_if< std::is_floating_point< T >::value, T >::type GetScalar()
Definition: serialization.h:50
std::enable_if< std::is_integral< T >::value, T >::type GetScalar()
Definition: serialization.h:45
static std::enable_if< detail::is_container< T >::value &&!std::is_same< T, std::string >::value, IRObject >::type FromCorpus(const T &val)
Definition: serialization.h:128
Type
Definition: serialization.h:32
@ Undefined
Definition: serialization.h:32
@ ShortString
Definition: serialization.h:32
@ Int
Definition: serialization.h:32
@ String
Definition: serialization.h:32
@ Float
Definition: serialization.h:32
@ Object
Definition: serialization.h:32
unsigned type
Definition: serialization.h:42
Definition: typetraits.h:58
Definition: typetraits.h:91
Definition: typetraits.h:55