OLD | NEW |
| (Empty) |
1 // Copyright 2005-2009 Google Inc. | |
2 // | |
3 // Licensed under the Apache License, Version 2.0 (the "License"); | |
4 // you may not use this file except in compliance with the License. | |
5 // You may obtain a copy of the License at | |
6 // | |
7 // http://www.apache.org/licenses/LICENSE-2.0 | |
8 // | |
9 // Unless required by applicable law or agreed to in writing, software | |
10 // distributed under the License is distributed on an "AS IS" BASIS, | |
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
12 // See the License for the specific language governing permissions and | |
13 // limitations under the License. | |
14 // ======================================================================== | |
15 // | |
16 // Declares class SerializableObject | |
17 // | |
18 // Provides the base class framework for those objects to be serialized | |
19 // | |
20 // Currently we support the serialization for the following member type | |
21 // | |
22 // 1) Value-type object | |
23 // 2) CString | |
24 // 3) Nested serializable object | |
25 // 4) Vector of the value-type objects | |
26 // 5) Vector of CString | |
27 // 6) Vector of serializable objects | |
28 // | |
29 // Usage: | |
30 // | |
31 // 1) Declare the object class, which you want to serialize, to be derived | |
32 // from SerializableObject | |
33 // 2) In its constructor, call AddSerializableMember(...) to add those fields | |
34 // to be included in the serialization | |
35 // 3) If you need to serialize a vector of serializable objects, | |
36 // a) The inner object class has to implement copy constructor and | |
37 // operator = | |
38 // b) The outer object class has to override SerializeVectorNestedObject() | |
39 // and DeserializeVectorNestedObject() (see sample) | |
40 // | |
41 // Versioning support: | |
42 // | |
43 // To add new fields in the new version, call | |
44 // AddSerializableMember(version, &member); | |
45 // If "version" is not given, it is 0 by default. | |
46 // | |
47 // To deserialize the data for latest version, call | |
48 // Deserialize(data, size, kLatestSerializableVersion); | |
49 // To deserialize the data for a particular version, call | |
50 // Deserialize(data, size, version); | |
51 // | |
52 // Sample: | |
53 // | |
54 // class FooObject : public SerializableObject { | |
55 // ... | |
56 // }; | |
57 // | |
58 // class BarObject : public SerializableObject { | |
59 // public: | |
60 // BarObject() { | |
61 // AddSerializableMember(&value1_); | |
62 // AddSerializableMember(&value2_); | |
63 // AddSerializableMember(&value3_); | |
64 // AddSerializableMember(&value4_); | |
65 // AddSerializableMember(&value5_); | |
66 // AddSerializableMember(&value6_); | |
67 // AddSerializableMember(1, &value7_); // New version | |
68 // } | |
69 // | |
70 // protected: | |
71 // virtual bool SerializeVectorNestedObject(std::vector<byte>* data, | |
72 // const byte* ptr) const { | |
73 // ASSERT(data, (_T(""))); | |
74 // ASSERT(ptr, (_T(""))); | |
75 // if (ptr == reinterpret_cast<const byte*>(&value6_)) | |
76 // return SerializeVectorNestedObjectHelper(data, &value6_); | |
77 // return false; | |
78 // } | |
79 // | |
80 // virtual bool DeserializeVectorNestedObject(byte** data, | |
81 // int size, | |
82 // byte* ptr, | |
83 // uint32 version) { | |
84 // ASSERT(data, (_T(""))); | |
85 // ASSERT(*data, (_T(""))); | |
86 // ASSERT(ptr, (_T(""))); | |
87 // if (ptr == reinterpret_cast<byte*>(&value6_)) | |
88 // return DeserializeVectorNestedObjectHelper(data, | |
89 // size, | |
90 // &value6_, | |
91 // version); | |
92 // return false; | |
93 // } | |
94 // | |
95 // private: | |
96 // int value1_; | |
97 // CString value2_; | |
98 // FooObject value3_; | |
99 // std::vector<byte> value4_; | |
100 // std::vector<CString> value5_; | |
101 // std::vector<BarObject> value6_; | |
102 // int value7_; | |
103 // }; | |
104 // | |
105 // Binary format: | |
106 // | |
107 // 1) Value type: data | |
108 // e.g. 100 => 64 00 00 00 | |
109 // 2) CString: size count data | |
110 // e.g. "ABC" => 02 00 00 00 03 00 00 00 41 00 42 00 43 00 | |
111 // 3) Vector: size count data | |
112 // e.g. vector<int> = {1, 2} | |
113 // => 04 00 00 00 02 00 00 00 01 00 00 00 02 00 00 00 | |
114 // | |
115 // TODO(omaha): | |
116 // 1) Define struct TypeTrait for all type-related info | |
117 // 2) Initialize TypeTrait on per-type basis instead of per-object basis | |
118 | |
119 #ifndef OMAHA_COMMON_SERIALIZABLE_OBJECT_H_ | |
120 #define OMAHA_COMMON_SERIALIZABLE_OBJECT_H_ | |
121 | |
122 #include <vector> | |
123 #include "base/basictypes.h" | |
124 #include "omaha/base/debug.h" | |
125 #include "omaha/base/type_utils.h" | |
126 | |
127 namespace omaha { | |
128 | |
129 // Constants | |
130 const uint32 kLatestSerializableVersion = 0xFFFFFFFF; | |
131 | |
132 // Serializable object | |
133 class SerializableObject { | |
134 private: | |
135 // Define SerializableMemberType, for internal use | |
136 typedef uint32 SerializableMemberType; | |
137 | |
138 #define SERIALIZABLE_VALUE_TYPE 1 | |
139 #define SERIALIZABLE_CSTRING 2 | |
140 #define SERIALIZABLE_NESTED_OBJECT 3 | |
141 #define SERIALIZABLE_VECTOR 0x8000 | |
142 | |
143 // Serializable member info | |
144 struct SerializableMemberInfo { | |
145 byte* ptr; // Pointers to the serializable member | |
146 SerializableMemberType type; // Type of the serializable member | |
147 int size; // Size of the serializable member | |
148 uint32 version; // Version when the member is added | |
149 | |
150 SerializableMemberInfo() | |
151 : ptr(NULL), type(SERIALIZABLE_VALUE_TYPE), size(0) {} | |
152 }; | |
153 | |
154 public: | |
155 // Constructor | |
156 SerializableObject() {} | |
157 | |
158 // Destructor | |
159 virtual ~SerializableObject() {} | |
160 | |
161 // Serialize | |
162 bool Serialize(std::vector<byte>* data) const; | |
163 | |
164 // Deserialize the data for the latest version | |
165 bool Deserialize(byte* data, int size) { | |
166 return Deserialize(data, size, kLatestSerializableVersion); | |
167 } | |
168 | |
169 // Deserialize the data for a particular version | |
170 bool Deserialize(byte* data, int size, uint32 version); | |
171 | |
172 protected: | |
173 // Clear the serializable member list | |
174 void ClearSerializableMemberList() { | |
175 members_.clear(); | |
176 } | |
177 | |
178 // Add value-typed member to the serializable member list | |
179 template<typename T> | |
180 void AddSerializableMember(T* ptr) { | |
181 return AddSerializableMember(0, ptr); | |
182 } | |
183 | |
184 // Add value-typed member to the serializable member list | |
185 template<typename T> | |
186 void AddSerializableMember(uint32 version, T* ptr) { | |
187 if (SUPERSUBCLASS(SerializableObject, T)) { | |
188 #pragma warning(push) | |
189 // reinterpret_cast used between related classes | |
190 #pragma warning(disable : 4946) | |
191 return AddSerializableMember(version, | |
192 reinterpret_cast<SerializableObject*>(ptr), | |
193 sizeof(T)); | |
194 #pragma warning(pop) | |
195 } | |
196 SerializableMemberInfo member; | |
197 member.ptr = reinterpret_cast<byte*>(ptr); | |
198 member.type = SERIALIZABLE_VALUE_TYPE; | |
199 member.size = sizeof(T); | |
200 member.version = version; | |
201 members_.push_back(member); | |
202 } | |
203 | |
204 // Add CString-typed member to the serializable member list | |
205 void AddSerializableMember(CString* ptr) { | |
206 AddSerializableMember(0, ptr); | |
207 } | |
208 | |
209 // Add CString-typed member to the serializable member list | |
210 void AddSerializableMember(uint32 version, CString* ptr) { | |
211 SerializableMemberInfo member; | |
212 member.ptr = reinterpret_cast<byte*>(ptr); | |
213 member.type = SERIALIZABLE_CSTRING; | |
214 member.size = sizeof(TCHAR); | |
215 member.version = version; | |
216 members_.push_back(member); | |
217 } | |
218 | |
219 // Add nested serializable member to the serializable member list | |
220 void AddSerializableMember(SerializableObject* ptr, int size) { | |
221 AddSerializableMember(0, ptr, size); | |
222 } | |
223 | |
224 // Add nested serializable member to the serializable member list | |
225 void AddSerializableMember(uint32 version, | |
226 SerializableObject* ptr, | |
227 int size) { | |
228 SerializableMemberInfo member; | |
229 member.ptr = reinterpret_cast<byte*>(ptr); | |
230 member.type = SERIALIZABLE_NESTED_OBJECT; | |
231 member.size = size; | |
232 member.version = version; | |
233 members_.push_back(member); | |
234 } | |
235 | |
236 // Add vector-typed member to the serializable member list | |
237 template<typename T> | |
238 void AddSerializableMember(std::vector<T>* ptr) { | |
239 AddSerializableMember(0, ptr); | |
240 } | |
241 | |
242 // Add vector-typed member to the serializable member list | |
243 template<typename T> | |
244 void AddSerializableMember(uint32 version, std::vector<T>* ptr) { | |
245 SerializableMemberInfo member; | |
246 member.ptr = reinterpret_cast<byte*>(ptr); | |
247 member.version = version; | |
248 | |
249 if (SUPERSUBCLASS(CString, T)) { | |
250 member.type = | |
251 static_cast<SerializableMemberType>(SERIALIZABLE_VECTOR | | |
252 SERIALIZABLE_CSTRING); | |
253 member.size = sizeof(TCHAR); | |
254 } else if (SUPERSUBCLASS(SerializableObject, T)) { | |
255 member.type = | |
256 static_cast<SerializableMemberType>(SERIALIZABLE_VECTOR | | |
257 SERIALIZABLE_NESTED_OBJECT); | |
258 member.size = sizeof(T); | |
259 } else { | |
260 member.type = | |
261 static_cast<SerializableMemberType>(SERIALIZABLE_VECTOR | | |
262 SERIALIZABLE_VALUE_TYPE); | |
263 member.size = sizeof(T); | |
264 } | |
265 | |
266 members_.push_back(member); | |
267 } | |
268 | |
269 // If there is a vector of SerializableObject to be serialized, the derived | |
270 // class need to provide the implementation | |
271 virtual bool SerializeVectorNestedObject(std::vector<byte>*, | |
272 const byte*) const { | |
273 ASSERT(false, (_T("Provide the implementation in the derived class."))); | |
274 return false; | |
275 } | |
276 | |
277 // Helper method to serialize a vector of SerializableObject | |
278 template<typename T> | |
279 bool SerializeVectorNestedObjectHelper(std::vector<byte>* data, | |
280 const std::vector<T>* list) const { | |
281 ASSERT(data, (_T(""))); | |
282 ASSERT(list, (_T(""))); | |
283 ASSERT(SUPERSUBCLASS(SerializableObject, T), (_T(""))); | |
284 | |
285 // Size of SerializableObject is unknown | |
286 SerializeSizeAndCount(data, 0, list->size()); | |
287 for (size_t i = 0; i < list->size(); ++i) { | |
288 // To work around compiler complaint while using dynamic_cast | |
289 SerializableObject* so = | |
290 const_cast<SerializableObject*>( | |
291 static_cast<const SerializableObject*>(&(*list)[i])); | |
292 bool res = so->Serialize(data); | |
293 if (!res) | |
294 return false; | |
295 } | |
296 return true; | |
297 } | |
298 | |
299 // If there is a vector of SerializableObject to be serialized, the derived | |
300 // class need to provide the implementation | |
301 virtual bool DeserializeVectorNestedObject(byte**, int, byte*, uint32) { | |
302 ASSERT(false, (_T("provide the implementation in the derived class."))); | |
303 return false; | |
304 } | |
305 | |
306 // Helper method to deserialize a vector of SerializableObject | |
307 template<typename T> | |
308 bool DeserializeVectorNestedObjectHelper(byte** data, | |
309 int size, | |
310 std::vector<T>* list, | |
311 uint32 version) { | |
312 ASSERT(data, (_T(""))); | |
313 ASSERT(*data, (_T(""))); | |
314 ASSERT(size, (_T(""))); | |
315 ASSERT(list, (_T(""))); | |
316 ASSERT(SUPERSUBCLASS(SerializableObject, T), (_T(""))); | |
317 | |
318 byte* tail = *data + size; | |
319 | |
320 // Size of SerializableObject is unknown | |
321 int count = 0; | |
322 bool res = DeserializeSizeAndCount(&count, 0, data, size); | |
323 if (!res) | |
324 return false; | |
325 | |
326 for (int i = 0; i < count; ++i) { | |
327 T obj; | |
328 bool res = obj.DeserializeHelper(data, tail - *data, version); | |
329 if (!res) | |
330 return false; | |
331 list->push_back(obj); | |
332 } | |
333 return true; | |
334 } | |
335 | |
336 private: | |
337 // Serialize the size and count values | |
338 void SerializeSizeAndCount(std::vector<byte>* data, | |
339 int size, | |
340 int count) const; | |
341 | |
342 // Serialize a list of value-typed elements | |
343 void SerializeValueList(std::vector<byte>* ser_data, | |
344 const byte* raw_data, | |
345 int size, | |
346 int count) const; | |
347 | |
348 // Deserialize helper | |
349 bool DeserializeHelper(byte** data, int size, uint32 version); | |
350 | |
351 // Deserialize the size and count values | |
352 bool DeserializeSizeAndCount(int* count, | |
353 int size, | |
354 byte** ser_data, | |
355 int ser_size) const; | |
356 | |
357 // Deserialize a list of value-typed elements | |
358 bool DeserializeValueList(std::vector<byte>* raw_data, | |
359 int size, | |
360 byte** ser_data, | |
361 int ser_size); | |
362 | |
363 // List of serializable members | |
364 std::vector<SerializableMemberInfo> members_; | |
365 | |
366 // We need to initialize TypeTrait on per-type basis instead of per-object | |
367 // basis and remove the following use of macro. | |
368 DISALLOW_EVIL_CONSTRUCTORS(SerializableObject); | |
369 }; | |
370 | |
371 } // namespace omaha | |
372 | |
373 #endif // OMAHA_COMMON_SERIALIZABLE_OBJECT_H_ | |
OLD | NEW |