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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3138 - (hide annotations) (download)
Wed May 3 14:41:58 2017 UTC (6 years, 10 months ago) by schoenebeck
File size: 27977 byte(s)
* Added new "Serialization" framework (and equally named namespace)
  which allows to serialize and deserialize native C++ objects
  in a portable, easy and flexible way.
* gig.cpp/gig.h: Added support for serializing & deserializing
  DimensionRegion objects (and crossfade_t and leverage_ctrl_t
  objects).
* Bumped version (4.0.0.svn15).

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     #include "Serialization.h"
25    
26     #include <iostream>
27     #include <assert.h>
28     #include <string.h> // for memcpy()
29     #include <stdlib.h> // for atof() and atof_l()
30     #include <xlocale.h> // for locale passed to atof_l()
31    
32     #include "helper.h"
33    
34     namespace Serialization {
35    
36     // *************** DataType ***************
37     // *
38    
39     static UID _createNullUID() {
40     return (UID) { NULL, 0 };
41     }
42    
43     const UID NO_UID = _createNullUID();
44    
45     bool UID::isValid() const {
46     return id != NULL && id != (void*)-1 && size;
47     }
48    
49     // *************** DataType ***************
50     // *
51    
52     DataType::DataType() {
53     m_size = 0;
54     m_isPointer = false;
55     }
56    
57     DataType::DataType(bool isPointer, int size, String baseType, String customType) {
58     m_size = size;
59     m_isPointer = isPointer;
60     m_baseTypeName = baseType;
61     m_customTypeName = customType;
62     }
63    
64     bool DataType::isValid() const {
65     return m_size;
66     }
67    
68     bool DataType::isPointer() const {
69     return m_isPointer;
70     }
71    
72     bool DataType::isClass() const {
73     return m_baseTypeName == "class";
74     }
75    
76     bool DataType::isPrimitive() const {
77     return !isClass();
78     }
79    
80     bool DataType::isInteger() const {
81     return m_baseTypeName.substr(0, 3) == "int" ||
82     m_baseTypeName.substr(0, 4) == "uint";
83     }
84    
85     bool DataType::isReal() const {
86     return m_baseTypeName.substr(0, 4) == "real";
87     }
88    
89     bool DataType::isBool() const {
90     return m_baseTypeName == "bool";
91     }
92    
93     bool DataType::isEnum() const {
94     return m_baseTypeName == "enum";
95     }
96    
97     bool DataType::isSigned() const {
98     return m_baseTypeName.substr(0, 3) == "int" ||
99     isReal();
100     }
101    
102     bool DataType::operator==(const DataType& other) const {
103     return m_baseTypeName == other.m_baseTypeName &&
104     m_customTypeName == other.m_customTypeName &&
105     m_size == other.m_size &&
106     m_isPointer == other.m_isPointer;
107     }
108    
109     bool DataType::operator!=(const DataType& other) const {
110     return !operator==(other);
111     }
112    
113     bool DataType::operator<(const DataType& other) const {
114     return m_baseTypeName < other.m_baseTypeName ||
115     (m_baseTypeName == other.m_baseTypeName &&
116     m_customTypeName < other.m_customTypeName ||
117     (m_customTypeName == other.m_customTypeName &&
118     m_size < other.m_size ||
119     (m_size == other.m_size &&
120     m_isPointer < other.m_isPointer)));
121     }
122    
123     bool DataType::operator>(const DataType& other) const {
124     return !(operator==(other) || operator<(other));
125     }
126    
127     String DataType::asLongDescr() const {
128     //TODO: Demangling of C++ raw type names
129     String s = m_baseTypeName;
130     if (!m_customTypeName.empty())
131     s += " " + m_customTypeName;
132     if (isPointer())
133     s += " pointer";
134     return s;
135     }
136    
137     // *************** Member ***************
138     // *
139    
140     Member::Member() {
141     m_uid = NO_UID;
142     m_offset = 0;
143     }
144    
145     Member::Member(String name, UID uid, size_t offset, DataType type) {
146     m_name = name;
147     m_uid = uid;
148     m_offset = offset;
149     m_type = type;
150     }
151    
152     bool Member::isValid() const {
153     return m_uid && !m_name.empty() && m_type;
154     }
155    
156     bool Member::operator==(const Member& other) const {
157     return m_uid == other.m_uid &&
158     m_offset == other.m_offset &&
159     m_name == other.m_name &&
160     m_type == other.m_type;
161     }
162    
163     bool Member::operator!=(const Member& other) const {
164     return !operator==(other);
165     }
166    
167     bool Member::operator<(const Member& other) const {
168     return m_uid < other.m_uid ||
169     (m_uid == other.m_uid &&
170     m_offset < other.m_offset ||
171     (m_offset == other.m_offset &&
172     m_name < other.m_name ||
173     (m_name == other.m_name &&
174     m_type < other.m_type)));
175     }
176    
177     bool Member::operator>(const Member& other) const {
178     return !(operator==(other) || operator<(other));
179     }
180    
181     // *************** Object ***************
182     // *
183    
184     Object::Object() {
185     m_version = 0;
186     m_minVersion = 0;
187     }
188    
189     Object::Object(UIDChain uidChain, DataType type) {
190     m_type = type;
191     m_uid = uidChain;
192     m_version = 0;
193     m_minVersion = 0;
194     m_data.resize(type.size());
195     }
196    
197     bool Object::isValid() const {
198     return m_type && !m_uid.empty();
199     }
200    
201     bool Object::operator==(const Object& other) const {
202     // ignoring all other member variables here
203     // (since UID stands for "unique" ;-) )
204     return m_uid == other.m_uid &&
205     m_type == other.m_type;
206     }
207    
208     bool Object::operator!=(const Object& other) const {
209     return !operator==(other);
210     }
211    
212     bool Object::operator<(const Object& other) const {
213     // ignoring all other member variables here
214     // (since UID stands for "unique" ;-) )
215     return m_uid < other.m_uid ||
216     (m_uid == other.m_uid &&
217     m_type < other.m_type);
218     }
219    
220     bool Object::operator>(const Object& other) const {
221     return !(operator==(other) || operator<(other));
222     }
223    
224     bool Object::isVersionCompatibleTo(const Object& other) const {
225     if (this->version() == other.version())
226     return true;
227     if (this->version() > other.version())
228     return this->minVersion() <= other.version();
229     else
230     return other.minVersion() <= this->version();
231     }
232    
233     Member Object::memberNamed(String name) const {
234     for (int i = 0; i < m_members.size(); ++i)
235     if (m_members[i].name() == name)
236     return m_members[i];
237     return Member();
238     }
239    
240     void Object::remove(const Member& member) {
241     for (int i = 0; i < m_members.size(); ++i) {
242     if (m_members[i] == member) {
243     m_members.erase(m_members.begin() + i);
244     return;
245     }
246     }
247     }
248    
249     std::vector<Member> Object::membersOfType(const DataType& type) const {
250     std::vector<Member> v;
251     for (int i = 0; i < m_members.size(); ++i) {
252     const Member& member = m_members[i];
253     if (member.type() == type)
254     v.push_back(member);
255     }
256     return v;
257     }
258    
259     int Object::sequenceIndexOf(const Member& member) const {
260     for (int i = 0; i < m_members.size(); ++i)
261     if (m_members[i] == member)
262     return i;
263     return -1;
264     }
265    
266     // *************** Archive ***************
267     // *
268    
269     Archive::Archive() {
270     m_operation = OPERATION_NONE;
271     m_root = NO_UID;
272     }
273    
274     Archive::Archive(const RawData& data) {
275     m_operation = OPERATION_NONE;
276     m_root = NO_UID;
277     decode(m_rawData);
278     }
279    
280     Archive::Archive(const uint8_t* data, size_t size) {
281     m_operation = OPERATION_NONE;
282     m_root = NO_UID;
283     decode(data, size);
284     }
285    
286     Archive::~Archive() {
287     }
288    
289     Object& Archive::rootObject() {
290     return m_allObjects[m_root];
291     }
292    
293     static String _encodeBlob(String data) {
294     return ToString(data.length()) + ":" + data;
295     }
296    
297     static String _encode(const UID& uid) {
298     String s;
299     s += _encodeBlob(ToString(size_t(uid.id)));
300     s += _encodeBlob(ToString(size_t(uid.size)));
301     return _encodeBlob(s);
302     }
303    
304     static String _encode(const DataType& type) {
305     String s;
306     s += _encodeBlob(type.baseTypeName());
307     s += _encodeBlob(type.customTypeName());
308     s += _encodeBlob(ToString(type.size()));
309     s += _encodeBlob(ToString(type.isPointer()));
310     return _encodeBlob(s);
311     }
312    
313     static String _encode(const UIDChain& chain) {
314     String s;
315     for (int i = 0; i < chain.size(); ++i)
316     s += _encode(chain[i]);
317     return _encodeBlob(s);
318     }
319    
320     static String _encode(const Member& member) {
321     String s;
322     s += _encode(member.uid());
323     s += _encodeBlob(ToString(member.offset()));
324     s += _encodeBlob(member.name());
325     s += _encode(member.type());
326     return _encodeBlob(s);
327     }
328    
329     static String _encode(const std::vector<Member>& members) {
330     String s;
331     for (int i = 0; i < members.size(); ++i)
332     s += _encode(members[i]);
333     return _encodeBlob(s);
334     }
335    
336     static String _encodePrimitiveValue(const Object& obj) {
337     String s;
338     const DataType& type = obj.type();
339     const ID& id = obj.uid().id;
340     if (type.isPrimitive() && !type.isPointer()) {
341     if (type.isInteger() || type.isEnum()) {
342     if (type.isSigned()) {
343     if (type.size() == 1)
344     s = ToString((int16_t)*(int8_t*)id); // int16_t: prevent ToString() to render an ASCII character
345     else if (type.size() == 2)
346     s = ToString(*(int16_t*)id);
347     else if (type.size() == 4)
348     s = ToString(*(int32_t*)id);
349     else if (type.size() == 8)
350     s = ToString(*(int64_t*)id);
351     else
352     assert(false /* unknown signed int type size */);
353     } else {
354     if (type.size() == 1)
355     s = ToString((uint16_t)*(uint8_t*)id); // uint16_t: prevent ToString() to render an ASCII character
356     else if (type.size() == 2)
357     s = ToString(*(uint16_t*)id);
358     else if (type.size() == 4)
359     s = ToString(*(uint32_t*)id);
360     else if (type.size() == 8)
361     s = ToString(*(uint64_t*)id);
362     else
363     assert(false /* unknown unsigned int type size */);
364     }
365     } else if (type.isReal()) {
366     if (type.size() == sizeof(float))
367     s = ToString(*(float*)id);
368     else if (type.size() == sizeof(double))
369     s = ToString(*(double*)id);
370     else
371     assert(false /* unknown floating point type */);
372     } else if (type.isBool()) {
373     s = ToString(*(bool*)id);
374     } else {
375     assert(false /* unknown primitive type */);
376     }
377    
378     }
379     return _encodeBlob(s);
380     }
381    
382     static String _encode(const Object& obj) {
383     String s;
384     s += _encode(obj.type());
385     s += _encodeBlob(ToString(obj.version()));
386     s += _encodeBlob(ToString(obj.minVersion()));
387     s += _encode(obj.uidChain());
388     s += _encode(obj.members());
389     s += _encodePrimitiveValue(obj);
390     return _encodeBlob(s);
391     }
392    
393     String _encode(const Archive::ObjectPool& objects) {
394     String s;
395     for (Archive::ObjectPool::const_iterator itObject = objects.begin();
396     itObject != objects.end(); ++itObject)
397     {
398     const Object& obj = itObject->second;
399     s += _encode(obj);
400     }
401     return _encodeBlob(s);
402     }
403    
404     #define MAGIC_START "Srx1v"
405     #define ENCODING_FORMAT_MINOR_VERSION 0
406    
407     String Archive::_encodeRootBlob() {
408     String s;
409     s += _encodeBlob(ToString(ENCODING_FORMAT_MINOR_VERSION));
410     s += _encode(m_root);
411     s += _encode(m_allObjects);
412     return _encodeBlob(s);
413     }
414    
415     void Archive::encode() {
416     m_rawData.clear();
417     String s = MAGIC_START;
418     s += _encodeRootBlob();
419     m_rawData.resize(s.length() + 1);
420     memcpy(&m_rawData[0], &s[0], s.length() + 1);
421     }
422    
423     struct _Blob {
424     const char* p;
425     const char* end;
426     };
427    
428     static _Blob _decodeBlob(const char* p, const char* end, bool bThrow = true) {
429     if (!bThrow && p >= end)
430     return (_Blob) { p, end };
431     size_t sz = 0;
432     for (; true; ++p) {
433     if (p >= end)
434     throw Exception("Decode Error: Missing blob");
435     const char& c = *p;
436     if (c == ':') break;
437     if (c < '0' || c > '9')
438     throw Exception("Decode Error: Missing blob size");
439     sz *= 10;
440     sz += size_t(c - '0');
441     }
442     ++p;
443     if (p + sz > end)
444     throw Exception("Decode Error: Premature end of blob");
445     return (_Blob) { p, p + sz };
446     }
447    
448     template<typename T_int>
449     static T_int _popIntBlob(const char*& p, const char* end) {
450     _Blob blob = _decodeBlob(p, end);
451     p = blob.p;
452     end = blob.end;
453    
454     T_int sign = 1;
455     T_int i = 0;
456     if (p >= end)
457     throw Exception("Decode Error: premature end of int blob");
458     if (*p == '-') {
459     sign = -1;
460     ++p;
461     }
462     for (; p < end; ++p) {
463     const char& c = *p;
464     if (c < '0' || c > '9')
465     throw Exception("Decode Error: Invalid int blob format");
466     i *= 10;
467     i += size_t(c - '0');
468     }
469     return i * sign;
470     }
471    
472     template<typename T_int>
473     static void _popIntBlob(const char*& p, const char* end, RawData& rawData) {
474     const T_int i = _popIntBlob<T_int>(p, end);
475     *(T_int*)&rawData[0] = i;
476     }
477    
478     template<typename T_real>
479     static T_real _popRealBlob(const char*& p, const char* end) {
480     _Blob blob = _decodeBlob(p, end);
481     p = blob.p;
482     end = blob.end;
483    
484     if (p >= end || (end - p) < 1)
485     throw Exception("Decode Error: premature end of real blob");
486    
487     String s(p, size_t(end - p));
488    
489     T_real r;
490     if (sizeof(T_real) == sizeof(float))
491     r = atof(s.c_str());
492     else if (sizeof(T_real) == sizeof(double))
493     r = atof_l(s.c_str(), _c_locale);
494     else
495     assert(false /* unknown real type */);
496    
497     p += s.length();
498    
499     return r;
500     }
501    
502     template<typename T_real>
503     static void _popRealBlob(const char*& p, const char* end, RawData& rawData) {
504     const T_real r = _popRealBlob<T_real>(p, end);
505     *(T_real*)&rawData[0] = r;
506     }
507    
508     static String _popStringBlob(const char*& p, const char* end) {
509     _Blob blob = _decodeBlob(p, end);
510     p = blob.p;
511     end = blob.end;
512     if (end - p < 0)
513     throw Exception("Decode Error: missing String blob");
514     String s;
515     const size_t sz = end - p;
516     s.resize(sz);
517     memcpy(&s[0], p, sz);
518     p += sz;
519     return s;
520     }
521    
522     DataType _popDataTypeBlob(const char*& p, const char* end) {
523     _Blob blob = _decodeBlob(p, end);
524     p = blob.p;
525     end = blob.end;
526    
527     DataType type;
528     type.m_baseTypeName = _popStringBlob(p, end);
529     type.m_customTypeName = _popStringBlob(p, end);
530     type.m_size = _popIntBlob<int>(p, end);
531     type.m_isPointer = _popIntBlob<bool>(p, end);
532     return type;
533     }
534    
535     static UID _popUIDBlob(const char*& p, const char* end) {
536     _Blob blob = _decodeBlob(p, end);
537     p = blob.p;
538     end = blob.end;
539    
540     if (p >= end)
541     throw Exception("Decode Error: premature end of UID blob");
542    
543     const ID id = (ID) _popIntBlob<size_t>(p, end);
544     const size_t size = _popIntBlob<size_t>(p, end);
545    
546     return (UID) { id, size };
547     }
548    
549     static UIDChain _popUIDChainBlob(const char*& p, const char* end) {
550     _Blob blob = _decodeBlob(p, end);
551     p = blob.p;
552     end = blob.end;
553    
554     UIDChain chain;
555     while (p < end) {
556     const UID uid = _popUIDBlob(p, end);
557     chain.push_back(uid);
558     }
559     assert(!chain.empty());
560     return chain;
561     }
562    
563     Member _popMemberBlob(const char*& p, const char* end) {
564     _Blob blob = _decodeBlob(p, end, false);
565     p = blob.p;
566     end = blob.end;
567    
568     Member m;
569     if (p >= end) return m;
570    
571     m.m_uid = _popUIDBlob(p, end);
572     m.m_offset = _popIntBlob<size_t>(p, end);
573     m.m_name = _popStringBlob(p, end);
574     m.m_type = _popDataTypeBlob(p, end);
575     assert(m.type());
576     assert(!m.name().empty());
577     assert(m.uid() != NULL);
578     return m;
579     }
580    
581     static std::vector<Member> _popMembersBlob(const char*& p, const char* end) {
582     _Blob blob = _decodeBlob(p, end, false);
583     p = blob.p;
584     end = blob.end;
585    
586     std::vector<Member> members;
587     while (p < end) {
588     const Member member = _popMemberBlob(p, end);
589     if (member)
590     members.push_back(member);
591     else
592     break;
593     }
594     return members;
595     }
596    
597     void _popPrimitiveValue(const char*& p, const char* end, Object& obj) {
598     const DataType& type = obj.type();
599     if (type.isPrimitive() && !type.isPointer()) {
600     obj.m_data.resize(type.size());
601     if (type.isInteger() || type.isEnum()) {
602     if (type.isSigned()) {
603     if (type.size() == 1)
604     _popIntBlob<int8_t>(p, end, obj.m_data);
605     else if (type.size() == 2)
606     _popIntBlob<int16_t>(p, end, obj.m_data);
607     else if (type.size() == 4)
608     _popIntBlob<int32_t>(p, end, obj.m_data);
609     else if (type.size() == 8)
610     _popIntBlob<int64_t>(p, end, obj.m_data);
611     else
612     assert(false /* unknown signed int type size */);
613     } else {
614     if (type.size() == 1)
615     _popIntBlob<uint8_t>(p, end, obj.m_data);
616     else if (type.size() == 2)
617     _popIntBlob<uint16_t>(p, end, obj.m_data);
618     else if (type.size() == 4)
619     _popIntBlob<uint32_t>(p, end, obj.m_data);
620     else if (type.size() == 8)
621     _popIntBlob<uint64_t>(p, end, obj.m_data);
622     else
623     assert(false /* unknown unsigned int type size */);
624     }
625     } else if (type.isReal()) {
626     if (type.size() == sizeof(float))
627     _popRealBlob<float>(p, end, obj.m_data);
628     else if (type.size() == sizeof(double))
629     _popRealBlob<double>(p, end, obj.m_data);
630     else
631     assert(false /* unknown floating point type */);
632     } else if (type.isBool()) {
633     _popIntBlob<uint8_t>(p, end, obj.m_data);
634     } else {
635     assert(false /* unknown primitive type */);
636     }
637    
638     } else {
639     // don't whine if the empty blob was not added on encoder side
640     _Blob blob = _decodeBlob(p, end, false);
641     p = blob.p;
642     end = blob.end;
643     }
644     }
645    
646     Object _popObjectBlob(const char*& p, const char* end) {
647     _Blob blob = _decodeBlob(p, end, false);
648     p = blob.p;
649     end = blob.end;
650    
651     Object obj;
652     if (p >= end) return obj;
653    
654     obj.m_type = _popDataTypeBlob(p, end);
655     obj.m_version = _popIntBlob<Version>(p, end);
656     obj.m_minVersion = _popIntBlob<Version>(p, end);
657     obj.m_uid = _popUIDChainBlob(p, end);
658     obj.m_members = _popMembersBlob(p, end);
659     _popPrimitiveValue(p, end, obj);
660     assert(obj.type());
661     return obj;
662     }
663    
664     void Archive::_popObjectsBlob(const char*& p, const char* end) {
665     _Blob blob = _decodeBlob(p, end, false);
666     p = blob.p;
667     end = blob.end;
668    
669     if (p >= end)
670     throw Exception("Decode Error: Premature end of objects blob");
671    
672     while (true) {
673     const Object obj = _popObjectBlob(p, end);
674     if (!obj) break;
675     m_allObjects[obj.uid()] = obj;
676     }
677     }
678    
679     void Archive::_popRootBlob(const char*& p, const char* end) {
680     _Blob blob = _decodeBlob(p, end, false);
681     p = blob.p;
682     end = blob.end;
683    
684     if (p >= end)
685     throw Exception("Decode Error: Premature end of root blob");
686    
687     // just in case this encoding format will be extended in future
688     // (currently not used)
689     const int formatMinorVersion = _popIntBlob<int>(p, end);
690    
691     m_root = _popUIDBlob(p, end);
692     if (!m_root)
693     throw Exception("Decode Error: No root object");
694    
695     _popObjectsBlob(p, end);
696     if (!m_allObjects[m_root])
697     throw Exception("Decode Error: Missing declared root object");
698     }
699    
700     void Archive::decode(const RawData& data) {
701     m_rawData = data;
702     m_allObjects.clear();
703     const char* p = (const char*) &data[0];
704     const char* end = p + data.size();
705     if (memcmp(p, MAGIC_START, std::min(strlen(MAGIC_START), data.size())))
706     throw Exception("Decode Error: Magic start missing!");
707     p += strlen(MAGIC_START);
708     _popRootBlob(p, end);
709     }
710    
711     void Archive::decode(const uint8_t* data, size_t size) {
712     RawData rawData;
713     rawData.resize(size);
714     memcpy(&rawData[0], data, size);
715     decode(rawData);
716     }
717    
718     String Archive::rawDataFormat() const {
719     return MAGIC_START;
720     }
721    
722     void Archive::clear() {
723     m_allObjects.clear();
724     m_operation = OPERATION_NONE;
725     m_root = NO_UID;
726     m_rawData.clear();
727     }
728    
729     void Archive::remove(const Object& obj) {
730     if (!obj.uid()) return;
731     m_allObjects.erase(obj.uid());
732     }
733    
734     Object& Archive::objectByUID(const UID& uid) {
735     return m_allObjects[uid];
736     }
737    
738     // *************** Archive::Syncer ***************
739     // *
740    
741     Archive::Syncer::Syncer(Archive& dst, Archive& src)
742     : m_dst(dst), m_src(src)
743     {
744     const Object srcRootObj = src.rootObject();
745     const Object dstRootObj = dst.rootObject();
746     if (!srcRootObj)
747     throw Exception("No source root object!");
748     if (!dstRootObj)
749     throw Exception("Expected destination root object not found!");
750     syncObject(dstRootObj, srcRootObj);
751     }
752    
753     void Archive::Syncer::syncPrimitive(const Object& dstObj, const Object& srcObj) {
754     assert(srcObj.rawData().size() == dstObj.type().size());
755     void* pDst = (void*)dstObj.uid().id;
756     memcpy(pDst, &srcObj.rawData()[0], dstObj.type().size());
757     }
758    
759     void Archive::Syncer::syncPointer(const Object& dstObj, const Object& srcObj) {
760     assert(dstObj.type().isPointer());
761     assert(dstObj.type() == srcObj.type());
762     const Object& pointedDstObject = m_dst.m_allObjects[dstObj.uid(1)];
763     const Object& pointedSrcObject = m_src.m_allObjects[srcObj.uid(1)];
764     syncObject(pointedDstObject, pointedSrcObject);
765     }
766    
767     void Archive::Syncer::syncObject(const Object& dstObj, const Object& srcObj) {
768     if (!dstObj || !srcObj) return; // end of recursion
769     if (!dstObj.isVersionCompatibleTo(srcObj))
770     throw Exception("Version incompatible (destination version " +
771     ToString(dstObj.version()) + " [min. version " +
772     ToString(dstObj.minVersion()) + "], source version " +
773     ToString(srcObj.version()) + " [min. version " +
774     ToString(srcObj.minVersion()) + "])");
775     if (dstObj.type() != srcObj.type())
776     throw Exception("Incompatible data structure type (destination type " +
777     dstObj.type().asLongDescr() + " vs. source type " +
778     srcObj.type().asLongDescr() + ")");
779    
780     // prevent syncing this object again, and thus also prevent endless
781     // loop on data structures with cyclic relations
782     m_dst.m_allObjects.erase(dstObj.uid());
783    
784     if (dstObj.type().isPrimitive() && !dstObj.type().isPointer()) {
785     syncPrimitive(dstObj, srcObj);
786     return; // end of recursion
787     }
788    
789     if (dstObj.type().isPointer()) {
790     syncPointer(dstObj, srcObj);
791     return;
792     }
793    
794     assert(dstObj.type().isClass());
795     for (int iMember = 0; iMember < srcObj.members().size(); ++iMember) {
796     const Member& srcMember = srcObj.members()[iMember];
797     Member dstMember = dstMemberMatching(dstObj, srcObj, srcMember);
798     if (!dstMember)
799     throw Exception("Expected member missing in destination object");
800     syncMember(dstMember, srcMember);
801     }
802     }
803    
804     Member Archive::Syncer::dstMemberMatching(const Object& dstObj, const Object& srcObj, const Member& srcMember) {
805     Member dstMember = dstObj.memberNamed(srcMember.name());
806     if (dstMember)
807     return (dstMember.type() == srcMember.type()) ? dstMember : Member();
808     std::vector<Member> members = dstObj.membersOfType(srcMember.type());
809     if (members.size() <= 0)
810     return Member();
811     if (members.size() == 1)
812     return members[0];
813     for (int i = 0; i < members.size(); ++i)
814     if (members[i].offset() == srcMember.offset())
815     return members[i];
816     const int srcSeqNr = srcObj.sequenceIndexOf(srcMember);
817     assert(srcSeqNr >= 0); // should never happen, otherwise there is a bug
818     for (int i = 0; i < members.size(); ++i) {
819     const int dstSeqNr = dstObj.sequenceIndexOf(members[i]);
820     if (dstSeqNr == srcSeqNr)
821     return members[i];
822     }
823     return Member(); // give up!
824     }
825    
826     void Archive::Syncer::syncMember(const Member& dstMember, const Member& srcMember) {
827     assert(dstMember && srcMember);
828     assert(dstMember.type() == srcMember.type());
829     const Object dstObj = m_dst.m_allObjects[dstMember.uid()];
830     const Object srcObj = m_src.m_allObjects[srcMember.uid()];
831     syncObject(dstObj, srcObj);
832     }
833    
834     // *************** Exception ***************
835     // *
836    
837     void Exception::PrintMessage() {
838     std::cout << "Serialization::Exception: " << Message << std::endl;
839     }
840    
841     } // namespace Serialization

  ViewVC Help
Powered by ViewVC