/[svn]/libgig/trunk/src/Serialization.h
ViewVC logotype

Contents of /libgig/trunk/src/Serialization.h

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3163 - (show annotations) (download) (as text)
Tue May 9 14:52:02 2017 UTC (6 years, 11 months ago) by schoenebeck
File MIME type: text/x-c++hdr
File size: 28531 byte(s)
* Attempt to fix type traits issue with older compilers.

1 /***************************************************************************
2 * *
3 * Copyright (C) 2017 Christian Schoenebeck *
4 * <cuse@users.sourceforge.net> *
5 * *
6 * This library is part of libgig. *
7 * *
8 * This library is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
12 * *
13 * This library is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU General Public License *
19 * along with this library; if not, write to the Free Software *
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
21 * MA 02111-1307 USA *
22 ***************************************************************************/
23
24 #ifndef LIBGIG_SERIALIZATION_H
25 #define LIBGIG_SERIALIZATION_H
26
27 #ifdef HAVE_CONFIG_H
28 # include <config.h>
29 #endif
30
31 #include <stdint.h>
32 #include <stdio.h>
33 #include <typeinfo>
34 #include <string>
35 #include <vector>
36 #include <map>
37 #include <time.h>
38 #if __cplusplus < 201103L
39 # include <tr1/type_traits>
40 #endif
41
42 /** @brief Serialization / deserialization framework.
43 *
44 * See class Archive as starting point for how to implement serialization and
45 * deserialization with your application.
46 *
47 * The classes in this namespace allow to serialize and deserialize native
48 * C++ objects in a portable, easy and flexible way. Serialization is a
49 * technique that allows to transform the current state and data of native
50 * (in this case C++) objects into a data stream (including all other objects
51 * the "serialized" objects relate to); the data stream may then be sent over
52 * "wire" (for example via network connection to another computer, which might
53 * also have a different OS, CPU architecture, native memory word size and
54 * endian type); and finally the data stream would be "deserialized" on that
55 * receiver side, that is transformed again to modify all objects and data
56 * structures on receiver side to resemble the objects' state and data as it
57 * was originally on sender side.
58 *
59 * In contrast to many other already existing serialization frameworks, this
60 * implementation has a strong focus on robustness regarding long-term changes
61 * to the serialized C++ classes of the serialized objects. So even if sender
62 * and receiver are using different versions of their serialized/deserialized
63 * C++ classes, structures and data types (thus having different data structure
64 * layout to a certain extent), this framework aims trying to automatically
65 * adapt its serialization and deserialization process in that case so that
66 * the deserialized objects on receiver side would still reflect the overall
67 * expected states and overall data as intended by the sender. For being able to
68 * do so, this framework stores all kind of additional information about each
69 * serialized object and each data structure member (for example name of each
70 * data structure member, but also the offset of each member within its
71 * containing data structure, precise data types, and more).
72 *
73 * Like most other serialization frameworks, this frameworks does not require a
74 * tree-structured layout of the serialized data structures. So it automatically
75 * handles also cyclic dependencies between serialized data structures
76 * correctly, without i.e. causing endless recursion or redundancy.
77 *
78 * Additionally this framework also allows partial deserialization. Which means
79 * the receiver side may for example decide that it wants to restrict
80 * deserialization so that it would only modify certain objects or certain
81 * members by the deserialization process, leaving all other ones untouched.
82 * So this partial deserialization technique for example allows to implement
83 * flexible preset features for applications in a powerful and easy way.
84 */
85 namespace Serialization {
86
87 // just symbol prototyping
88 class DataType;
89 class Object;
90 class Member;
91 class Archive;
92 class ObjectPool;
93 class Exception;
94
95 typedef std::string String;
96
97 typedef std::vector<uint8_t> RawData;
98
99 typedef void* ID;
100
101 typedef uint32_t Version;
102
103 enum operation_t {
104 OPERATION_NONE,
105 OPERATION_SERIALIZE,
106 OPERATION_DESERIALIZE
107 };
108
109 enum time_base_t {
110 LOCAL_TIME,
111 UTC_TIME
112 };
113
114 template<typename T>
115 bool IsEnum(const T& data) {
116 return __is_enum(T);
117 }
118
119 template<typename T>
120 bool IsUnion(const T& data) {
121 return __is_union(T);
122 }
123
124 template<typename T>
125 bool IsClass(const T& data) {
126 return __is_class(T);
127 }
128
129 /*template<typename T>
130 bool IsTrivial(T data) {
131 return __is_trivial(T);
132 }*/
133
134 /*template<typename T>
135 bool IsPOD(T data) {
136 return __is_pod(T);
137 }*/
138
139 /** @brief Unique identifier for one specific C++ object, member or fundamental variable.
140 *
141 * Reflects a unique identifier for one specific serialized C++ class
142 * instance, struct instance, member, primitive pointer, or fundamental
143 * variables.
144 */
145 class UID {
146 public:
147 ID id;
148 size_t size;
149
150 bool isValid() const;
151 operator bool() const { return isValid(); }
152 //bool operator()() const { return isValid(); }
153 bool operator==(const UID& other) const { return id == other.id && size == other.size; }
154 bool operator!=(const UID& other) const { return id != other.id || size != other.size; }
155 bool operator<(const UID& other) const { return id < other.id || (id == other.id && size < other.size); }
156 bool operator>(const UID& other) const { return id > other.id || (id == other.id && size > other.size); }
157
158 template<typename T>
159 static UID from(const T& obj) {
160 return Resolver<T>::resolve(obj);
161 }
162
163 protected:
164 // UID resolver for non-pointer types
165 template<typename T>
166 struct Resolver {
167 static UID resolve(const T& obj) {
168 return (UID) { (ID) &obj, sizeof(obj) };
169 }
170 };
171
172 // UID resolver for pointer types (of 1st degree)
173 template<typename T>
174 struct Resolver<T*> {
175 static UID resolve(const T* const & obj) {
176 return (UID) { (ID) obj, sizeof(*obj) };
177 }
178 };
179 };
180
181 /**
182 * Reflects an invalid UID and behaves similar to NULL as invalid value for
183 * pointer types.
184 */
185 extern const UID NO_UID;
186
187 typedef std::vector<UID> UIDChain;
188
189 // prototyping of private internal friend functions
190 static String _encodePrimitiveValue(const Object& obj);
191 static DataType _popDataTypeBlob(const char*& p, const char* end);
192 static Member _popMemberBlob(const char*& p, const char* end);
193 static Object _popObjectBlob(const char*& p, const char* end);
194 static void _popPrimitiveValue(const char*& p, const char* end, Object& obj);
195 static String _primitiveObjectValueToString(const Object& obj);
196
197 /** @brief Abstract reflection of a native C++ data type.
198 *
199 * Provides detailed information about a C++ data type, whether it is a
200 * fundamental C/C++ data type (like int, float, char, etc.) or custom
201 * defined data type like a C++ class, struct, enum, as well as other
202 * features of the data type like its native memory size and more.
203 */
204 class DataType {
205 public:
206 DataType();
207 size_t size() const { return m_size; }
208 bool isValid() const;
209 bool isPointer() const;
210 bool isClass() const;
211 bool isPrimitive() const;
212 bool isInteger() const;
213 bool isReal() const;
214 bool isBool() const;
215 bool isEnum() const;
216 bool isSigned() const;
217 operator bool() const { return isValid(); }
218 //bool operator()() const { return isValid(); }
219 bool operator==(const DataType& other) const;
220 bool operator!=(const DataType& other) const;
221 bool operator<(const DataType& other) const;
222 bool operator>(const DataType& other) const;
223 String asLongDescr() const;
224 String baseTypeName() const { return m_baseTypeName; }
225 String customTypeName() const { return m_customTypeName; }
226
227 template<typename T>
228 static DataType dataTypeOf(const T& data) {
229 return Resolver<T>::resolve(data);
230 }
231
232 protected:
233 DataType(bool isPointer, int size, String baseType, String customType = "");
234
235 template<typename T, bool T_isPointer>
236 struct ResolverBase {
237 static DataType resolve(const T& data) {
238 const std::type_info& type = typeid(data);
239 const int sz = sizeof(data);
240
241 // for primitive types we are using our own type names instead of
242 // using std:::type_info::name(), because the precise output of the
243 // latter may vary between compilers
244 if (type == typeid(int8_t)) return DataType(T_isPointer, sz, "int8");
245 if (type == typeid(uint8_t)) return DataType(T_isPointer, sz, "uint8");
246 if (type == typeid(int16_t)) return DataType(T_isPointer, sz, "int16");
247 if (type == typeid(uint16_t)) return DataType(T_isPointer, sz, "uint16");
248 if (type == typeid(int32_t)) return DataType(T_isPointer, sz, "int32");
249 if (type == typeid(uint32_t)) return DataType(T_isPointer, sz, "uint32");
250 if (type == typeid(int64_t)) return DataType(T_isPointer, sz, "int64");
251 if (type == typeid(uint64_t)) return DataType(T_isPointer, sz, "uint64");
252 if (type == typeid(bool)) return DataType(T_isPointer, sz, "bool");
253 if (type == typeid(float)) return DataType(T_isPointer, sz, "real32");
254 if (type == typeid(double)) return DataType(T_isPointer, sz, "real64");
255
256 if (IsEnum(data)) return DataType(T_isPointer, sz, "enum", rawCppTypeNameOf(data));
257 if (IsUnion(data)) return DataType(T_isPointer, sz, "union", rawCppTypeNameOf(data));
258 if (IsClass(data)) return DataType(T_isPointer, sz, "class", rawCppTypeNameOf(data));
259
260 return DataType();
261 }
262 };
263
264 // DataType resolver for non-pointer types
265 template<typename T>
266 struct Resolver : ResolverBase<T,false> {
267 static DataType resolve(const T& data) {
268 return ResolverBase<T,false>::resolve(data);
269 }
270 };
271
272 // DataType resolver for pointer types (of 1st degree)
273 template<typename T>
274 struct Resolver<T*> : ResolverBase<T,true> {
275 static DataType resolve(const T*& data) {
276 return ResolverBase<T,true>::resolve(*data);
277 }
278 };
279
280 template<typename T>
281 static String rawCppTypeNameOf(const T& data) {
282 #if defined _MSC_VER // Microsoft compiler ...
283 # warning type_info::raw_name() demangling has not been tested yet with Microsoft compiler! Feedback appreciated!
284 String name = typeid(data).raw_name(); //NOTE: I haven't checked yet what MSC actually outputs here exactly
285 #else // i.e. especially GCC and clang ...
286 String name = typeid(data).name();
287 #endif
288 //while (!name.empty() && name[0] >= 0 && name[0] <= 9)
289 // name = name.substr(1);
290 return name;
291 }
292
293 private:
294 String m_baseTypeName;
295 String m_customTypeName;
296 int m_size;
297 bool m_isPointer;
298
299 friend DataType _popDataTypeBlob(const char*& p, const char* end);
300 friend class Archive;
301 };
302
303 /** @brief Abstract reflection of a native C++ class/struct's member variable.
304 *
305 * Provides detailed information about a specific C++ member variable of
306 * serialized C++ object, like its C++ data type, offset of this member
307 * within its containing data structure/class, its C++ member variable name
308 * and more.
309 */
310 class Member {
311 public:
312 Member();
313 UID uid() const { return m_uid; }
314 String name() const { return m_name; }
315 size_t offset() const { return m_offset; }
316 const DataType& type() const { return m_type; }
317 bool isValid() const;
318 operator bool() const { return isValid(); }
319 //bool operator()() const { return isValid(); }
320 bool operator==(const Member& other) const;
321 bool operator!=(const Member& other) const;
322 bool operator<(const Member& other) const;
323 bool operator>(const Member& other) const;
324
325 protected:
326 Member(String name, UID uid, size_t offset, DataType type);
327 friend class Archive;
328
329 private:
330 UID m_uid;
331 size_t m_offset;
332 String m_name;
333 DataType m_type;
334
335 friend Member _popMemberBlob(const char*& p, const char* end);
336 };
337
338 /** @brief Abstract reflection of a native C++ class/struct instance.
339 *
340 * Provides detailed information about a specific serialized C++ object,
341 * like its C++ member variables, its C++ class/struct name, its native
342 * memory size and more.
343 */
344 class Object {
345 public:
346 Object();
347 Object(UIDChain uidChain, DataType type);
348
349 UID uid(int index = 0) const {
350 return (index < m_uid.size()) ? m_uid[index] : NO_UID;
351 }
352
353 const UIDChain& uidChain() const { return m_uid; }
354 const DataType& type() const { return m_type; }
355 const RawData& rawData() const { return m_data; }
356
357 Version version() const { return m_version; }
358
359 void setVersion(Version v) {
360 m_version = v;
361 }
362
363 Version minVersion() const { return m_minVersion; }
364
365 void setMinVersion(Version v) {
366 m_minVersion = v;
367 }
368
369 bool isVersionCompatibleTo(const Object& other) const;
370
371 std::vector<Member>& members() { return m_members; }
372 const std::vector<Member>& members() const { return m_members; }
373 Member memberNamed(String name) const;
374 Member memberByUID(const UID& uid) const;
375 std::vector<Member> membersOfType(const DataType& type) const;
376 int sequenceIndexOf(const Member& member) const;
377 bool isValid() const;
378 operator bool() const { return isValid(); }
379 //bool operator()() const { return isValid(); }
380 bool operator==(const Object& other) const;
381 bool operator!=(const Object& other) const;
382 bool operator<(const Object& other) const;
383 bool operator>(const Object& other) const;
384
385 protected:
386 void remove(const Member& member);
387
388 private:
389 DataType m_type;
390 UIDChain m_uid;
391 Version m_version;
392 Version m_minVersion;
393 RawData m_data;
394 std::vector<Member> m_members;
395
396 friend String _encodePrimitiveValue(const Object& obj);
397 friend Object _popObjectBlob(const char*& p, const char* end);
398 friend void _popPrimitiveValue(const char*& p, const char* end, Object& obj);
399 friend String _primitiveObjectValueToString(const Object& obj);
400 friend class Archive;
401 };
402
403 /** @brief Destination container for serialization, and source container for deserialization.
404 *
405 * This is the main class for implementing serialization and deserialization
406 * with your C++ application. This framework does not require a a tree
407 * structured layout of your C++ objects being serialized/deserialized, it
408 * uses a concept of a "root" object though. So to start serialization
409 * construct an empty Archive object and then instruct it to serialize your
410 * C++ objects by pointing it to your "root" object:
411 * @code
412 * Archive a;
413 * a.serialize(&myRootObject);
414 * @endcode
415 * Or if you prefer the look of operator based code:
416 * @code
417 * Archive a;
418 * a << myRootObject;
419 * @endcode
420 * The Archive object will then serialize all members of the passed C++
421 * object, and will recursively serialize all other C++ objects which it
422 * contains or points to. So the root object is the starting point for the
423 * overall serialization. After the serialize() method returned, you can
424 * then access the serialized data stream by calling rawData() and send that
425 * data stream over "wire", or store it on disk or whatever you may intend
426 * to do with it.
427 *
428 * Then on receiver side likewise, you create a new Archive object, pass the
429 * received data stream i.e. via constructor to the Archive object and call
430 * deserialize() by pointing it to the root object on receiver side:
431 * @code
432 * Archive a(rawDataStream);
433 * a.deserialize(&myRootObject);
434 * @endcode
435 * Or with operator instead:
436 * @code
437 * Archive a(rawDataStream);
438 * a >> myRootObject;
439 * @endcode
440 * Now this framework automatically handles serialization and
441 * deserialization of fundamental data types automatically for you (like
442 * i.e. char, int, long int, float, double, etc.). However for your own
443 * custom C++ classes and structs you must implement one method which
444 * defines which members of your class should actually be serialized and
445 * deserialized. That method to be added must have the following signature:
446 * @code
447 * void serialize(Serialization::Archive* archive);
448 * @endcode
449 * So let's say you have the following simple data structures:
450 * @code
451 * struct Foo {
452 * int a;
453 * bool b;
454 * double c;
455 * };
456 *
457 * struct Bar {
458 * char one;
459 * float two;
460 * Foo foo1;
461 * Foo* pFoo2;
462 * Foo* pFoo3DontTouchMe; // shall not be serialized/deserialized
463 * };
464 * @endcode
465 * So in order to be able to serialize and deserialize objects of those two
466 * structures you would first add the mentioned method to each struct
467 * definition (i.e. in your header file):
468 * @code
469 * struct Foo {
470 * int a;
471 * bool b;
472 * double c;
473 *
474 * void serialize(Serialization::Archive* archive);
475 * };
476 *
477 * struct Bar {
478 * char one;
479 * float two;
480 * Foo foo1;
481 * Foo* pFoo2;
482 * Foo* pFoo3DontTouchMe; // shall not be serialized/deserialized
483 *
484 * void serialize(Serialization::Archive* archive);
485 * };
486 * @endcode
487 * And then you would implement those two new methods like this (i.e. in
488 * your .cpp file):
489 * @code
490 * #define SRLZ(member) \
491 * archive->serializeMember(*this, member, #member);
492 *
493 * void Foo::serialize(Serialization::Archive* archive) {
494 * SRLZ(a);
495 * SRLZ(b);
496 * SRLZ(c);
497 * }
498 *
499 * void Bar::serialize(Serialization::Archive* archive) {
500 * SRLZ(one);
501 * SRLZ(two);
502 * SRLZ(foo1);
503 * SRLZ(pFoo2);
504 * // leaving out pFoo3DontTouchMe here
505 * }
506 * @endcode
507 * Now when you serialize such a Bar object, this framework will also
508 * automatically serialize the respective Foo object(s) accordingly, also
509 * for the pFoo2 pointer for instance (as long as it is not a NULL pointer
510 * that is).
511 *
512 * Note that there is only one method that you need to implement. So the
513 * respective serialize() method implementation of your classes/structs are
514 * both called for serialization, as well as for deserialization!
515 */
516 class Archive {
517 public:
518 Archive();
519 Archive(const RawData& data);
520 Archive(const uint8_t* data, size_t size);
521 virtual ~Archive();
522
523 template<typename T>
524 void serialize(const T* obj) {
525 m_operation = OPERATION_SERIALIZE;
526 m_allObjects.clear();
527 m_rawData.clear();
528 m_root = UID::from(obj);
529 const_cast<T*>(obj)->serialize(this);
530 encode();
531 m_operation = OPERATION_NONE;
532 }
533
534 template<typename T>
535 void deserialize(T* obj) {
536 Archive a;
537 m_operation = OPERATION_DESERIALIZE;
538 obj->serialize(&a);
539 a.m_root = UID::from(obj);
540 Syncer s(a, *this);
541 m_operation = OPERATION_NONE;
542 }
543
544 template<typename T>
545 void operator<<(const T& obj) {
546 serialize(&obj);
547 }
548
549 template<typename T>
550 void operator>>(T& obj) {
551 deserialize(&obj);
552 }
553
554 const RawData& rawData();
555 virtual String rawDataFormat() const;
556
557 template<typename T_classType, typename T_memberType>
558 void serializeMember(const T_classType& nativeObject, const T_memberType& nativeMember, const char* memberName) {
559 const size_t offset =
560 ((const uint8_t*)(const void*)&nativeMember) -
561 ((const uint8_t*)(const void*)&nativeObject);
562 const UIDChain uids = UIDChainResolver<T_memberType>(nativeMember);
563 const DataType type = DataType::dataTypeOf(nativeMember);
564 const Member member(memberName, uids[0], offset, type);
565 const UID parentUID = UID::from(nativeObject);
566 Object& parent = m_allObjects[parentUID];
567 if (!parent) {
568 const UIDChain uids = UIDChainResolver<T_classType>(nativeObject);
569 const DataType type = DataType::dataTypeOf(nativeObject);
570 parent = Object(uids, type);
571 }
572 parent.members().push_back(member);
573 const Object obj(uids, type);
574 const bool bExistsAlready = m_allObjects.count(uids[0]);
575 const bool isValidObject = obj;
576 const bool bExistingObjectIsInvalid = !m_allObjects[uids[0]];
577 if (!bExistsAlready || (bExistingObjectIsInvalid && isValidObject)) {
578 m_allObjects[uids[0]] = obj;
579 // recurse serialization for all members of this member
580 // (only for struct/class types, noop for primitive types)
581 SerializationRecursion<T_memberType>::serializeObject(this, nativeMember);
582 }
583 }
584
585 virtual void decode(const RawData& data);
586 virtual void decode(const uint8_t* data, size_t size);
587 void clear();
588 bool isModified() const;
589 void removeMember(Object& parent, const Member& member);
590 void remove(const Object& obj);
591 Object& rootObject();
592 Object& objectByUID(const UID& uid);
593 void setAutoValue(Object& object, String value);
594 void setIntValue(Object& object, int64_t value);
595 void setRealValue(Object& object, double value);
596 void setBoolValue(Object& object, bool value);
597 void setEnumValue(Object& object, uint64_t value);
598 String valueAsString(const Object& object);
599 String name() const;
600 void setName(String name);
601 String comment() const;
602 void setComment(String comment);
603 time_t timeStampCreated() const;
604 time_t timeStampModified() const;
605 tm dateTimeCreated(time_base_t base = LOCAL_TIME) const;
606 tm dateTimeModified(time_base_t base = LOCAL_TIME) const;
607
608 protected:
609 // UID resolver for non-pointer types
610 template<typename T>
611 class UIDChainResolver {
612 public:
613 UIDChainResolver(const T& data) {
614 m_uid.push_back(UID::from(data));
615 }
616
617 operator UIDChain() const { return m_uid; }
618 UIDChain operator()() const { return m_uid; }
619 private:
620 UIDChain m_uid;
621 };
622
623 // UID resolver for pointer types (of 1st degree)
624 template<typename T>
625 class UIDChainResolver<T*> {
626 public:
627 UIDChainResolver(const T*& data) {
628 m_uid.push_back((UID) { &data, sizeof(data) });
629 m_uid.push_back((UID) { data, sizeof(*data) });
630 }
631
632 operator UIDChain() const { return m_uid; }
633 UIDChain operator()() const { return m_uid; }
634 private:
635 UIDChain m_uid;
636 };
637
638 // SerializationRecursion for non-pointer class/struct types.
639 template<typename T, bool T_isRecursive>
640 struct SerializationRecursionImpl {
641 static void serializeObject(Archive* archive, const T& obj) {
642 const_cast<T&>(obj).serialize(archive);
643 }
644 };
645
646 // SerializationRecursion for pointers (of 1st degree) to class/structs.
647 template<typename T, bool T_isRecursive>
648 struct SerializationRecursionImpl<T*,T_isRecursive> {
649 static void serializeObject(Archive* archive, const T*& obj) {
650 if (!obj) return;
651 const_cast<T*&>(obj)->serialize(archive);
652 }
653 };
654
655 // NOOP SerializationRecursion for primitive types.
656 template<typename T>
657 struct SerializationRecursionImpl<T,false> {
658 static void serializeObject(Archive* archive, const T& obj) {}
659 };
660
661 // NOOP SerializationRecursion for pointers (of 1st degree) to primitive types.
662 template<typename T>
663 struct SerializationRecursionImpl<T*,false> {
664 static void serializeObject(Archive* archive, const T*& obj) {}
665 };
666
667 // Automatically handles recursion for class/struct types, while ignoring all primitive types.
668 template<typename T>
669 struct SerializationRecursion : SerializationRecursionImpl<T, __is_class(T)> {
670 };
671
672 class ObjectPool : public std::map<UID,Object> {
673 public:
674 // prevent passing obvious invalid UID values from creating a new pair entry
675 Object& operator[](const UID& k) {
676 static Object invalid;
677 if (!k.isValid()) {
678 invalid = Object();
679 return invalid;
680 }
681 return std::map<UID,Object>::operator[](k);
682 }
683 };
684
685 friend String _encode(const ObjectPool& objects);
686
687 private:
688 String _encodeRootBlob();
689 void _popRootBlob(const char*& p, const char* end);
690 void _popObjectsBlob(const char*& p, const char* end);
691
692 protected:
693 class Syncer {
694 public:
695 Syncer(Archive& dst, Archive& src);
696 protected:
697 void syncObject(const Object& dst, const Object& src);
698 void syncPrimitive(const Object& dst, const Object& src);
699 void syncPointer(const Object& dst, const Object& src);
700 void syncMember(const Member& dstMember, const Member& srcMember);
701 static Member dstMemberMatching(const Object& dstObj, const Object& srcObj, const Member& srcMember);
702 private:
703 Archive& m_dst;
704 Archive& m_src;
705 };
706
707 virtual void encode();
708
709 ObjectPool m_allObjects;
710 operation_t m_operation;
711 UID m_root;
712 RawData m_rawData;
713 bool m_isModified;
714 String m_name;
715 String m_comment;
716 time_t m_timeCreated;
717 time_t m_timeModified;
718 };
719
720 /**
721 * Will be thrown whenever an error occurs during an serialization or
722 * deserialization process.
723 */
724 class Exception {
725 public:
726 String Message;
727
728 Exception(String Message) { Exception::Message = Message; }
729 void PrintMessage();
730 virtual ~Exception() {}
731 };
732
733 } // namespace Serialization
734
735 #endif // LIBGIG_SERIALIZATION_H

  ViewVC Help
Powered by ViewVC