DSL
serialize.cpp
1 #include <drift/dslcore.h>
2 #include <drift/GenLib.h>
3 #include <drift/serialize.h>
4 #include <assert.h>
5 
6 bool DSL_Serializable::_serialize_int(DSL_BUFFER * buf, void * val, uint8_t size, bool deserialize) {
7  assert(size == 1 || size == 2 || size == 4 || size == 8);
8  return deserialize ? dsl_deserialize_int(buf, val, size) : dsl_serialize_int(buf, val, size);
9 }
10 bool DSL_Serializable::serialize_var(DSL_BUFFER * buf, string * val, bool deserialize) {
11  return deserialize ? dsl_deserialize_string(buf, val) : dsl_serialize_string(buf, val);
12 }
13 bool DSL_Serializable::serialize_var(DSL_BUFFER * buf, char * data, size_t bufSize, bool deserialize) {
14  return deserialize ? dsl_deserialize_varchar(buf, (uint8_t *)data, bufSize) : dsl_serialize_varchar(buf, (const uint8_t *)data, strlen(data));
15 }
16 bool DSL_Serializable::serialize_var(DSL_BUFFER * buf, uint8_t * data, size_t lSize, bool deserialize) {
17  return deserialize ? dsl_deserialize_fixed(buf, data, lSize) : dsl_serialize_fixed(buf, data, lSize);
18 }
19 
20 size_t _max_size_of_varint(uint8_t size) {
21  assert(size == 1 || size == 2 || size == 4 || size == 8);
22  unsigned int x = (size * 8) / 7;
23  if ((size * 8) % 7 != 0) {
24  x++;
25  }
26  return x;
27 }
28 
29 bool DSL_Serializable::GetSerialized(DSL_BUFFER * buf) {
30  return Serialize(buf, false);
31 }
32 
33 bool DSL_Serializable::FromSerialized(DSL_BUFFER * buf) {
34  return Serialize(buf, true);
35 }
36 
37 string DSL_Serializable::GetSerialized() {
38  DSL_BUFFER buf;
39  buffer_init(&buf);
40  string ret;
41  if (GetSerialized(&buf)) {
42  ret.assign(buf.data, buf.len);
43  }
44  buffer_free(&buf);
45  return ret;
46 }
47 bool DSL_Serializable::FromSerialized(const string& str) {
48  DSL_BUFFER buf;
49  buffer_init(&buf);
50  buffer_set(&buf, str.data(), str.length());
51  bool ret = FromSerialized(&buf);
52  buffer_free(&buf);
53  return ret;
54 }
55 
56 #ifdef ENABLE_ZLIB
57 
58 bool DSL_Serializable::GetCompressed(DSL_BUFFER * buf, int compression_level) {
59  bool ret = false;
60  if (Serialize(buf, false)) {
61  DSL_BUFFER buf2;
62  buffer_init(&buf2);
63  uLongf dlen = compressBound(buf->len);
64  if ((sizeof(uLongf) == 4 || dlen <= UINT32_MAX)) {
65  buffer_resize(&buf2, dlen);
66  if (compress2(buf2.udata, &dlen, buf->udata, buf->len, compression_level) == Z_OK) {
67  uint32_t serlen = buf->len;
68  buffer_clear(buf);
69  if (dsl_serialize_int(buf, &serlen, sizeof(serlen))) {
70  if (buffer_append(buf, buf2.data, dlen)) {
71  ret = true;
72  }
73  }
74  }
75  }
76  buffer_free(&buf2);
77  }
78  return ret;
79 }
80 
81 bool DSL_Serializable::FromCompressed(DSL_BUFFER * buf) {
82  bool ret = false;
83  DSL_BUFFER buf2;
84  buffer_init(&buf2);
85  uint32_t serlen = 0;
86  if (dsl_deserialize_int(buf, &serlen, sizeof(serlen))) {
87  uLongf dlen = serlen;
88  buffer_resize(&buf2, serlen);
89  int n = 0;
90  if ((n = uncompress(buf2.udata, &dlen, buf->udata, buf->len)) == Z_OK && dlen == serlen) {
91  buffer_clear(buf);
92  if (buffer_append(buf, buf2.data, dlen)) {
93  if (Serialize(buf, true)) {
94  ret = true;
95  }
96  }
97  }
98  }
99  buffer_free(&buf2);
100  return ret;
101 }
102 
103 string DSL_Serializable::GetCompressed(int compression_level) {
104  DSL_BUFFER buf;
105  buffer_init(&buf);
106  string ret;
107  if (GetCompressed(&buf, compression_level)) {
108  ret.assign(buf.data, buf.len);
109  }
110  buffer_free(&buf);
111  return ret;
112 }
113 bool DSL_Serializable::FromCompressed(const string& str) {
114  DSL_BUFFER buf;
115  buffer_init(&buf);
116  buffer_set(&buf, str.data(), str.length());
117  bool ret = FromCompressed(&buf);
118  buffer_free(&buf);
119  return ret;
120 }
121 
122 #endif
123 
124 bool DSL_Serializable_DSD::serializeEntries(DSL_BUFFER * buf) {
125  uint32 len;
126  for (auto& x : dsd_entries) {
127  buffer_append_int<uint8>(buf, x.first);
128 #if SIZE_MAX > UINT32_MAX
129  if (x.second.length() > UINT32_MAX) { return false; }
130 #endif
131  len = x.second.length();
132  if (!serialize_var(buf, &len, false)) { return false; }
133  if (!buffer_append(buf, x.second.c_str(), x.second.length())) { return false; }
134  }
135  return true;
136 }
137 
139  union {
140  uint8_t u8;
141  uint16_t u16;
142  uint32_t u32;
143  uint64_t u64;
144  };
145 };
146 
147 bool DSL_CC dsl_serialize_int(DSL_BUFFER * buf, const void * pVal, size_t lSize) {
148  assert(lSize == 1 || lSize == 2 || lSize == 4 || lSize == 8);
149  uint64_t tmp = 0;
150  const DSL_SERIALIZE_INTINMEM * intinmem = (const DSL_SERIALIZE_INTINMEM *)pVal;
151  switch (lSize) {
152  case 1:
153  tmp = intinmem->u8;
154  break;
155  case 2:
156  tmp = intinmem->u16;
157  break;
158  case 4:
159  tmp = intinmem->u32;
160  break;
161  case 8:
162  tmp = intinmem->u64;
163  break;
164  default:
165  return false;
166  break;
167  }
168  uint8_t data;
169  bool first = true;
170  while (tmp || first) {
171  first = false;
172  data = (tmp & 0x7F);
173  tmp >>= 7;
174  if (tmp) {
175  //more data to follow
176  data |= 0x80;
177  }
178  buffer_append_int<uint8_t>(buf, data);
179  }
180  return true;
181 }
182 
183 bool DSL_CC dsl_deserialize_int(DSL_BUFFER * buf, void * pVal, size_t lSize) {
184  assert(lSize == 1 || lSize == 2 || lSize == 4 || lSize == 8);
185  size_t used = 0;
186  uint8_t * data = buf->udata;
187  size_t maxlen = _max_size_of_varint(lSize);
188  while (1) {
189  if (buf->len < ++used) {
190  return false;
191  }
192  if (used > maxlen) {
193  /* worst case scenario should be 10 bytes */
194  return false;
195  }
196  if (!(*data & 0x80)) {
197  break;
198  }
199  data++;
200  }
201  uint64_t tmp = 0;
202  while (data >= buf->udata) {
203  tmp <<= 7;
204  tmp |= (*data & 0x7F);
205  data--;
206  }
207  buffer_remove_front(buf, used);
208 
209  DSL_SERIALIZE_INTINMEM * intinmem = (DSL_SERIALIZE_INTINMEM *)pVal;
210  switch (lSize) {
211  case 1:
212  if (tmp > UINT8_MAX) {
213  return false;
214  }
215  intinmem->u8 = tmp;
216  break;
217  case 2:
218  if (tmp > UINT16_MAX) {
219  return false;
220  }
221  intinmem->u16 = tmp;
222  break;
223  case 4:
224  if (tmp > UINT32_MAX) {
225  return false;
226  }
227  intinmem->u32 = tmp;
228  break;
229  case 8:
230  intinmem->u64 = tmp;
231  break;
232  default:
233  return false;
234  break;
235  }
236 
237  return true;
238 }
239 
240 bool DSL_CC dsl_serialize_string(DSL_BUFFER * buf, const string * val) {
241  return dsl_serialize_varchar(buf, (const uint8_t *)val->data(), val->length());
242 }
243 bool DSL_CC dsl_deserialize_string(DSL_BUFFER * buf, string * val) {
244  uint32 lSize = 0;
245  if (!dsl_deserialize_int(buf, &lSize, sizeof(lSize))) {
246  return false;
247  }
248  if (buf->len < lSize) {
249  return false;
250  }
251  if (lSize > 0) {
252  val->assign(buf->data, lSize);
253  buffer_remove_front(buf, lSize);
254  } else {
255  val->clear();
256  }
257  return true;
258 }
259 
260 bool DSL_CC dsl_serialize_varchar(DSL_BUFFER * buf, const uint8_t * val, uint32_t lSize) {
261  if (!dsl_serialize_int(buf, &lSize, sizeof(lSize))) {
262  return false;
263  }
264  return buffer_append(buf, (const char *)val, lSize);
265 }
266 bool DSL_CC dsl_deserialize_varchar(DSL_BUFFER * buf, uint8_t * val, uint32_t lSize) {
267  uint32_t len = 0;
268  if (!dsl_deserialize_int(buf, &len, sizeof(len))) {
269  return false;
270  }
271  if (len > lSize || buf->len < len) {
272  return false;
273  }
274  if (len > 0) {
275  memcpy(val, buf->udata, len);
276  buffer_remove_front(buf, len);
277  }
278  return true;
279 }
280 
281 bool DSL_CC dsl_serialize_fixed(DSL_BUFFER * buf, const uint8_t * val, uint32_t lSize) {
282  return buffer_append(buf, (const char *)val, lSize);
283 }
284 bool DSL_CC dsl_deserialize_fixed(DSL_BUFFER * buf, uint8_t * val, uint32_t lSize) {
285  if (buf->len < lSize) {
286  return false;
287  }
288  if (lSize > 0) {
289  memcpy(val, buf->udata, lSize);
290  buffer_remove_front(buf, lSize);
291  }
292  return true;
293 }
DSL_API void DSL_CC buffer_remove_front(DSL_BUFFER *buf, int64 len)
Remove data from the beginning of the buffer.
Definition: Buffer.cpp:167
DSL_API void DSL_CC buffer_init(DSL_BUFFER *buf, bool useMutex=false)
Initialize the buffer, optionally with a mutex protecting it. If you don't use the mutex you need to ...
Definition: Buffer.cpp:123
DSL_API void DSL_CC buffer_set(DSL_BUFFER *buf, const char *ptr, int64 len)
Sets the buffer to the specified data, discarding anything existing.
Definition: Buffer.cpp:152
DSL_API void DSL_CC buffer_free(DSL_BUFFER *buf)
Free the buffer when you are done with it.
Definition: Buffer.cpp:128
DSL_API void DSL_CC buffer_clear(DSL_BUFFER *buf)
Sets the buffer length to 0 and clears the data. It is still ready to be used unlike buffer_free.
Definition: Buffer.cpp:144
DSL_API bool DSL_CC buffer_append(DSL_BUFFER *buf, const char *ptr, int64 len)
Add data to the end of the buffer.
Definition: Buffer.cpp:202
DSL_API void DSL_CC buffer_resize(DSL_BUFFER *buf, int64 len)
Resize the buffer, if the length is longer then the existing data the added byte values are undefined...
Definition: Buffer.cpp:160