forked from skyfireitdiy/sflib
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsf_serialize_binary.hpp
353 lines (299 loc) · 13.9 KB
/
sf_serialize_binary.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
/**
* @version 1.0.0
* @author skyfire
* @mail skyfireitdiy@hotmail.com
* @see http://github.com/skyfireitdiy/sflib
* @file sf_serialize_binary.hpp
* sflib第一版本发布
* 版本号1.0.0
* 发布日期:2018-10-22
*/
/*
* 提供序列化支持(二进制)
*/
#pragma once
#include "sf_serialize_binary.h"
namespace skyfire {
inline sf_serialize_binary_size_mismatch_exception::
sf_serialize_binary_size_mismatch_exception(const std::string &exception_message) : _message(exception_message) {
}
inline const char *sf_serialize_binary_size_mismatch_exception::what() const noexcept {
return _message.c_str();
}
inline byte_array sf_serialize_binary() {
return byte_array();
}
template<typename _Pod_Type>
typename std::enable_if<std::is_pod<_Pod_Type>::value, byte_array>::type
sf_serialize_binary(const _Pod_Type &value) {
byte_array ret(sizeof(_Pod_Type));
auto p = reinterpret_cast<const char *>(&value);
memcpy(ret.data(), &value, sizeof(_Pod_Type));
return ret;
}
template<typename _Pod_Type>
typename std::enable_if<std::is_pod<_Pod_Type>::value, size_t>::type
sf_deserialize_binary(const byte_array &data, _Pod_Type &obj, size_t begin_pos) {
if (sizeof(_Pod_Type) > data.size() - begin_pos) {
throw sf_serialize_binary_size_mismatch_exception("Data size is to small");
}
memcpy(&obj, data.data() + begin_pos, sizeof(_Pod_Type));
return begin_pos + sizeof(_Pod_Type);
}
template<typename _Type>
byte_array sf_serialize_binary(const std::vector<_Type> &value) {
byte_array ret;
size_t len = value.size();
auto tmp_ret = sf_serialize_binary(len);
ret.insert(ret.end(), tmp_ret.begin(), tmp_ret.end());
for (auto const &p : value) {
tmp_ret = sf_serialize_binary(p);
ret.insert(ret.end(), tmp_ret.begin(), tmp_ret.end());
}
return ret;
}
template<typename _Type>
size_t sf_deserialize_binary(const byte_array &data, std::vector<_Type> &obj,
size_t begin_pos) {
obj.clear();
size_t len;
auto offset = sf_deserialize_binary(data, len, begin_pos);
obj.resize(len);
for (auto i = 0; i < len; ++i) {
offset = sf_deserialize_binary(data, obj[i], offset);
}
return offset;
}
template<typename _Type>
byte_array sf_serialize_binary(const std::list<_Type> &value) {
std::vector<_Type> tmp_obj(value.begin(), value.end());
return sf_serialize_binary(tmp_obj);
}
template<typename _Type>
size_t sf_deserialize_binary(const byte_array &data, std::list<_Type> &obj,
size_t begin_pos) {
std::vector<_Type> tmp_obj;
auto ret = sf_deserialize_binary(data, tmp_obj, begin_pos);
obj = std::list<_Type>(tmp_obj.begin(), tmp_obj.end());
return ret;
}
template<typename _Type>
byte_array sf_serialize_binary(const std::deque<_Type> &value) {
std::vector<_Type> tmp_obj(value.begin(), value.end());
return sf_serialize_binary(tmp_obj);
}
template<typename _Type>
size_t sf_deserialize_binary(const byte_array &data, std::deque<_Type> &obj,
size_t begin_pos) {
std::vector<_Type> tmp_obj;
auto ret = sf_deserialize_binary(data, tmp_obj, begin_pos);
obj = std::deque<_Type>(tmp_obj.begin(), tmp_obj.end());
return ret;
}
template<typename _Type>
byte_array sf_serialize_binary(const std::set<_Type> &value) {
std::vector<_Type> tmp_obj(value.begin(), value.end());
return sf_serialize_binary(tmp_obj);
}
template<typename _Type>
size_t sf_deserialize_binary(const byte_array &data, std::set<_Type> &obj,
size_t begin_pos) {
std::vector<_Type> tmp_obj;
auto ret = sf_deserialize_binary(data, tmp_obj, begin_pos);
obj = std::set<_Type>(tmp_obj.begin(), tmp_obj.end());
return ret;
}
template<typename _Type>
byte_array sf_serialize_binary(const std::unordered_set<_Type> &value) {
std::vector<_Type> tmp_obj(value.begin(), value.end());
return sf_serialize_binary(tmp_obj);
}
template<typename _Type>
size_t sf_deserialize_binary(const byte_array &data, std::unordered_set<_Type> &obj,
size_t begin_pos) {
std::vector<_Type> tmp_obj;
auto ret = sf_deserialize_binary(data, tmp_obj, begin_pos);
obj = std::unordered_set<_Type>(tmp_obj.begin(), tmp_obj.end());
return ret;
}
template<typename _Type>
byte_array sf_serialize_binary(const std::multiset<_Type> &value) {
std::vector<_Type> tmp_obj(value.begin(), value.end());
return sf_serialize_binary(tmp_obj);
}
template<typename _Type>
size_t sf_deserialize_binary(const byte_array &data, std::multiset<_Type> &obj,
size_t begin_pos) {
std::vector<_Type> tmp_obj;
auto ret = sf_deserialize_binary(data, tmp_obj, begin_pos);
obj = std::multiset<_Type>(tmp_obj.begin(), tmp_obj.end());
return ret;
}
template<typename _Type>
byte_array sf_serialize_binary(const std::basic_string<_Type> &value) {
std::vector<char> tmp_obj(value.begin(), value.end());
return sf_serialize_binary(tmp_obj);
}
template<typename _Type>
size_t sf_deserialize_binary(const byte_array &data, std::basic_string<_Type> &obj,
size_t begin_pos) {
std::vector<char> tmp_obj;
auto ret = sf_deserialize_binary(data, tmp_obj, begin_pos);
obj = std::basic_string<_Type>(tmp_obj.begin(), tmp_obj.end());
return ret;
}
template<typename _Type>
byte_array sf_serialize_binary(const std::unordered_multiset<_Type> &value) {
std::vector<_Type> tmp_obj(value.begin(), value.end());
return sf_serialize_binary(tmp_obj);
}
template<typename _Type>
size_t sf_deserialize_binary(const byte_array &data, std::unordered_multiset<_Type> &obj,
size_t begin_pos) {
std::vector<_Type> tmp_obj;
auto ret = sf_deserialize_binary(data, tmp_obj, begin_pos);
obj = std::unordered_multiset<_Type>(tmp_obj.begin(), tmp_obj.end());
return ret;
}
template<typename _TypeKey, typename _TypeValue>
byte_array sf_serialize_binary(const std::unordered_multimap<_TypeKey, _TypeValue> &obj) {
byte_array ret;
size_t len = obj.size();
auto tmp_ret = sf_serialize_binary(len);
ret.insert(ret.end(), tmp_ret.begin(), tmp_ret.end());
for (auto const &p : obj) {
tmp_ret = sf_serialize_binary(p.first);
ret.insert(ret.end(), tmp_ret.begin(), tmp_ret.end());
tmp_ret = sf_serialize_binary(p.second);
ret.insert(ret.end(), tmp_ret.begin(), tmp_ret.end());
}
return ret;
}
template<typename _TypeKey, typename _TypeValue>
size_t
sf_deserialize_binary(const byte_array &data, std::unordered_multimap<_TypeKey, _TypeValue> &obj,
size_t begin_pos) {
obj.clear();
size_t len;
auto offset = sf_deserialize_binary(data, len, begin_pos);
_TypeKey key;
_TypeValue value;
for (auto i = 0; i < len; ++i) {
offset = sf_deserialize_binary(data, key, offset);
offset = sf_deserialize_binary(data, value, offset);
obj.insert({key, value});
}
return offset;
}
template<typename _TypeKey, typename _TypeValue>
byte_array sf_serialize_binary(const std::unordered_map<_TypeKey, _TypeValue> &obj) {
std::unordered_multimap<_TypeKey, _TypeValue> tmp_obj(obj.begin(), obj.end());
return sf_serialize_binary(tmp_obj);
}
template<typename _TypeKey, typename _TypeValue>
size_t
sf_deserialize_binary(const byte_array &data, std::unordered_map<_TypeKey, _TypeValue> &obj,
size_t begin_pos) {
std::unordered_multimap<_TypeKey, _TypeValue> tmp_obj;
auto ret = sf_deserialize_binary(data, tmp_obj, begin_pos);
obj = std::unordered_map<_TypeKey, _TypeValue>(tmp_obj.begin(), tmp_obj.end());
return ret;
}
template<typename _TypeKey, typename _TypeValue>
byte_array sf_serialize_binary(const std::multimap<_TypeKey, _TypeValue> &obj) {
std::unordered_multimap<_TypeKey, _TypeValue> tmp_obj(obj.begin(), obj.end());
return sf_serialize_binary(tmp_obj);
}
template<typename _TypeKey, typename _TypeValue>
size_t
sf_deserialize_binary(const byte_array &data, std::multimap<_TypeKey, _TypeValue> &obj,
size_t begin_pos) {
std::unordered_multimap<_TypeKey, _TypeValue> tmp_obj;
auto ret = sf_deserialize_binary(data, tmp_obj, begin_pos);
obj = std::multimap<_TypeKey, _TypeValue>(tmp_obj.begin(), tmp_obj.end());
return ret;
}
template<typename _TypeKey, typename _TypeValue>
byte_array sf_serialize_binary(const std::map<_TypeKey, _TypeValue> &obj) {
std::unordered_multimap<_TypeKey, _TypeValue> tmp_obj(obj.begin(), obj.end());
return sf_serialize_binary(tmp_obj);
}
template<typename _TypeKey, typename _TypeValue>
size_t
sf_deserialize_binary(const byte_array &data, std::map<_TypeKey, _TypeValue> &obj,
size_t begin_pos) {
std::unordered_multimap<_TypeKey, _TypeValue> tmp_obj;
auto ret = sf_deserialize_binary(data, tmp_obj, begin_pos);
obj = std::map<_TypeKey, _TypeValue>(tmp_obj.begin(), tmp_obj.end());
return ret;
}
template<typename _First_Type, typename... _Types>
byte_array sf_serialize_binary(const _First_Type &first, const _Types &... value) {
return sf_serialize_binary(first) + sf_serialize_binary(value...);
}
template<int N, typename... _Types>
typename std::enable_if<N == sizeof...(_Types), byte_array>::type
sf_serialize_binary_tuple(const std::tuple<_Types...> &obj) {
return byte_array();
}
template<int N, typename... _Types>
typename std::enable_if<N != sizeof...(_Types), byte_array>::type
sf_serialize_binary_tuple(const std::tuple<_Types...> &obj) {
return sf_serialize_binary(std::get<N>(obj)) + sf_serialize_binary_tuple<N + 1, _Types...>(obj);
}
template<typename... _Types>
byte_array sf_serialize_binary(const std::tuple<_Types...> &obj) {
return sf_serialize_binary_tuple<0, _Types...>(obj);
}
template<int N, typename _Tuple_Type, typename... _Types>
typename std::enable_if<N == std::tuple_size<_Tuple_Type>::value, size_t>::type
sf_deserialize_binary_tuple(size_t pos, const byte_array &data, _Tuple_Type &obj, _Types... arg) {
obj = std::tuple<_Types...>(arg...);
return pos;
}
template<int N, typename _Tuple_Type, typename... _Types>
typename std::enable_if<N != std::tuple_size<_Tuple_Type>::value, size_t>::type
sf_deserialize_binary_tuple(size_t pos, const byte_array &data, _Tuple_Type &obj, _Types... arg) {
using next_type = typename std::remove_reference<decltype(std::get<N>(std::declval<_Tuple_Type>()))>::type;
next_type _t;
pos = sf_deserialize_binary(data, _t, pos);
return sf_deserialize_binary_tuple<N + 1, _Tuple_Type, _Types..., next_type>(pos, data, obj, arg..., _t);
}
template<typename _Tuple_Type>
size_t sf_deserialize_binary_tuple(size_t pos, const byte_array &data, _Tuple_Type &obj) {
using next_type = typename std::remove_reference<decltype(std::get<0>(std::declval<_Tuple_Type>()))>::type;
next_type _t;
pos = sf_deserialize_binary(data, _t, pos);
return sf_deserialize_binary_tuple<1, _Tuple_Type, next_type>(pos, data, obj, _t);
}
template<typename... _Types>
size_t sf_deserialize_binary(const byte_array &data, std::tuple<_Types...> &obj, size_t begin_pos) {
if constexpr (sizeof...(_Types) == 0) {
return begin_pos;
} else {
return sf_deserialize_binary_tuple(begin_pos, data, obj);
}
}
template<typename ... _Type>
byte_array sf_serialize_binary_obj_helper(const _Type &... obj) {
return (sf_serialize_binary(obj) + ...);
}
template<typename T>
size_t sf_deserialize_binary_obj_helper(const byte_array &data, size_t begin_pos, T &obj) {
return sf_deserialize_binary(data, obj, begin_pos);
}
template<typename T, typename ... _Type>
size_t sf_deserialize_binary_obj_helper(const byte_array &data, size_t begin_pos, T &obj, _Type &... other) {
auto pos = sf_deserialize_binary(data, obj, begin_pos);
return sf_deserialize_binary_obj_helper(data, pos, other...);
}
//使一个结构变成可序列化的结构(需保证内部的每个成员都可以序列化,使用时需要注入到skyfire命名空间内部)
#define SF_MAKE_SERIALIZABLE_BINARY(className, ...) \
inline byte_array sf_serialize_binary(const className& obj){ \
return sf_serialize_binary_obj_helper(SF_EXPAND_OBJ_MEM(obj, __VA_ARGS__)); \
} \
inline size_t \
sf_deserialize_binary(const byte_array &data, className &obj, size_t begin_pos){ \
return sf_deserialize_binary_obj_helper(data, begin_pos, SF_EXPAND_OBJ_MEM(obj, __VA_ARGS__)); \
} \
}