-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathSerializeFile.h
340 lines (301 loc) · 10.5 KB
/
SerializeFile.h
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
#pragma once
#include <cassert>
#include <boost/type_traits.hpp>
#include <boost/shared_ptr.hpp>
#include "MemoryAllocation.h"
#include "Types.h"
#include "Preprocessor.h"
#include "SerializeNameValuePair.h"
#include "SerializeSimple.h"
#include "SerializeContainer.h"
#include "SerializeComposite.h"
#include "SerializeSerializeable.h"
namespace Scan
{
namespace Serialize
{
/**
@brief 二进制输入文件
用Factory::createObject创建对象, 后用open来打开一个输入文件
*/
class SerializeBinaryFileIn;
/**
@brief 二进制输出文件
用Factory::createObject创建对象, 后用open来打开一个输出文件
*/
class SerializeBinaryFileOut;
/**
@brief xml输入文件
用Factory::createObject创建对象, 后用open来打开一个输入文件
*/
class SerializeXmlFileIn;
/**
@brief xml输出文件
用Factory::createObject创建对象, 后用open来打开一个输出文件
*/
class SerializeXmlFileOut;
/**
@brief 二进制内存输入
以std::vector<char>作为数据源, 在open时传入vector地址的字符串
*/
class SerializeBinaryDataIn;
/**
@brief 二进制内存输出
以std::vector<char>作为数据目标, 在open时传入vector地址的字符串
*/
class SerializeBinaryDataOut;
/**
@brief xml字符串输入
以xml格式的String作为数据源, 在open时传入String
*/
class SerializeXmlStringIn;
/**
@brief xml字符串输出
将xml格式的字符串输出到指定String对象中, 在open时传入String作为目标
*/
class SerializeXmlStringOut;
typedef boost::shared_ptr<ISerializeFile> SerializeFilePtr;
template<typename T>
inline void serializeContentHook(ISerializeFile &f, T &v, const char *name)
{
f.serializeImpl(v, name);
}
/**
@brief 串行化文件接口
*/
struct ISerializeFile
{
public:
virtual ~ISerializeFile() = 0 {}
/**
@brief 是否是一个输入文件
*/
virtual bool isInputFile() const = 0;
/**
@brief 返回文件标识
如果是文件, 返回的就是文件名
*/
virtual const String& getName() const = 0;
/**
@brief 打开一个文件
*/
virtual bool open(const String& name) = 0;
virtual bool isOpened() const = 0;
virtual void close() = 0;
template<typename T>
ISerializeFile& serialize(T& v, const char *name,
typename boost::disable_if<boost::is_const<T>>::type* = 0)
{
beginObject(name);
serializeContentHook(*this, v, name);
endObject();
return *this;
}
template<typename T>
friend inline void serializeContentHook(ISerializeFile &f, T &v, const char *name);
private:
/**
@brief 串行化一个指针对象
*/
template<typename T>
void serializeImpl(T& v, const char *name,
typename boost::enable_if<boost::is_pointer<T>>::type* = 0)
{
serializePtrCast(v, name);
}
/**
@brief 串行化一个非指针对象
*/
template<typename T>
void serializeImpl(T& v, const char *name,
typename boost::disable_if<boost::is_pointer<T>>::type* = 0)
{
serializeNotPtrCast(v, name);
}
template<typename T>
void serializeNotPtrCast(T& v, const char *name,
typename boost::enable_if<boost::is_base_of<ISerializeable, T>>::type* = 0)
{
// 对于多重继承, 这样可以正确定位偏移
ISerializeable& r = v;
serializeNotPtr(r, name);
}
template<typename T>
void serializeNotPtrCast(T& v, const char *name,
typename boost::disable_if<boost::is_base_of<ISerializeable, T>>::type* = 0)
{
serializeNotPtr(v, name);
}
template<typename T>
void serializePtrCast(T& v, const char *name,
typename boost::enable_if<boost::is_base_of<ISerializeable,
typename boost::remove_pointer<T>::type>>::type* = 0)
{
// 对于多重继承, 这样可以正确定位偏移
ISerializeable* p = v;
serializePtr(p, name);
v = static_cast<T>(p);
}
template<typename T>
void serializePtrCast(T& v, const char *name,
typename boost::disable_if<boost::is_base_of<ISerializeable,
typename boost::remove_pointer<T>::type>>::type* = 0)
{
serializePtr(v, name);
}
private:
/**
@brief 串行化一个简单对象
即非ISerializeable派生类的非容器类
*/
template<typename T>
void serializeNotPtr(T& v, const char *name,
typename boost::disable_if<IsContainer<T>>::type* = 0)
{
ISimpleObject *p = new SimpleObject<T>(v);
handleSimpleObject(p);
delete p;
}
/**
@brief 串行化简单类的指针
*/
template<typename T>
void serializePtr(T*& v, const char *name,
typename boost::disable_if<IsContainer<T>>::type* = 0)
{
// 只有作为输入文件的时候才允许空指针
assert(v != NULL || isInputFile());
// 空指针的话, new一个对象
if (v == NULL)
{
v = ClassAllocator<T>::alloc();
}
serializeNotPtr(*v, name);
}
/**
@brief 串行化一个ISerializeable对象
*/
void serializeNotPtr(ISerializeable& v, const char *name)
{
ISerializeable *p = &v;
serializePtr(p, name);
}
/**
@brief 串行化一个ISerializeable指针
*/
void serializePtr(ISerializeable*& v, const char *name)
{
// 只有输入文件才可以处理空指针
assert(v != NULL || isInputFile());
// 对于空指针, 输入文件会new正确的子类
handleSerializeable(v);
}
/**
@brief 串行化一个容器
*/
template<typename ContainerType>
void serializeNotPtr(ContainerType& v, const char *name,
typename boost::enable_if<IsContainer<ContainerType>>::type* = 0)
{
typedef ContainerAdapter<ContainerType> Adapter;
Adapter* list = new Adapter(v);
uint32 itemCount = list->getSize();
// 先串行化对象的个数
serialize(itemCount, "item_count");
// 然后递归串行化对象
for (uint32 i = 0; i < itemCount; ++i)
{
// 输入文件会创建对象
if (isInputFile())
{
list->createNew();
}
list->moveNext();
String itemName = String(name) + "_item_" + toString(i);
serialize(list->getCurrentItem(), itemName.c_str());
}
delete list;
}
/**
@brief 串行化容器指针
*/
template<typename ContainerType>
void serializePtr(ContainerType*& p, const char *name,
typename boost::enable_if<IsContainer<ContainerType>>::type* = 0,
typename boost::disable_if<boost::is_array<ContainerType>>::type* = 0)
{
assert(p != NULL || isInputFile());
// 遇到空指针, 输入文件会new一个对象
if (p == NULL)
{
p = ClassAllocator<ContainerType>::alloc();
}
serializeNotPtr(*p, name);
}
protected:
/**
@brief 开始串行化一个对象
*/
virtual void beginObject(const char *name) = 0;
/**
@brief 处理简单对象
*/
virtual void handleSimpleObject(ISimpleObject *&p) = 0;
/**
@brief 处理一个复合对象
如果是输入文件, p为空的话会创建一个对象, 这也是为什么p是指针的
引用的原因
*/
virtual void handleSerializeable(ISerializeable *&p) = 0;
/**
@brief 串行化结束
*/
virtual void endObject() = 0;
};
template<typename T>
ISerializeFile& operator << (ISerializeFile& file, const T& v)
{
assert(!file.isInputFile());
file.serialize(const_cast<T&>(v), "");
return file;
}
template<typename T>
ISerializeFile& operator << (ISerializeFile& file, const NVPair<const T>& p)
{
assert(!file.isInputFile());
file.serialize(const_cast<T&>(p.obj), p.name);
return file;
}
template<typename T>
ISerializeFile& operator << (ISerializeFile& file, const NVPair<T>& p)
{
assert(!file.isInputFile());
file.serialize(p.obj, p.name);
return file;
}
template<typename T>
ISerializeFile& operator >> (ISerializeFile& file, T& v)
{
assert(file.isInputFile());
file.serialize(v, "");
return file;
}
template<typename T>
ISerializeFile& operator >> (ISerializeFile& file, const NVPair<T>& p)
{
assert(file.isInputFile());
file.serialize(p.obj, p.name);
return file;
}
template<typename T>
ISerializeFile& operator & (ISerializeFile& file, T& v)
{
return file.isInputFile() ? file >> v : file << v;
}
template<typename T>
ISerializeFile& operator & (ISerializeFile& file, const NVPair<T>& p)
{
return file.isInputFile() ? file >> p : file << p;
}
}
}