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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3146 - (hide annotations) (download)
Wed May 3 19:54:08 2017 UTC (6 years, 10 months ago) by schoenebeck
File size: 27837 byte(s)
- Serialization.h/.cpp: trivial corrections.

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

  ViewVC Help
Powered by ViewVC