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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3153 - (hide annotations) (download) (as text)
Sat May 6 13:43:43 2017 UTC (6 years, 11 months ago) by schoenebeck
File MIME type: text/x-c++hdr
File size: 27923 byte(s)
* Serialization.cpp/.h: class Object: Added method
  memberByUID(), and method remove() is now protected,
  class Archive: Added method removeMember().
* Bumped version (4.0.0.svn17).

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

  ViewVC Help
Powered by ViewVC