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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3153 - (hide annotations) (download)
Sat May 6 13:43:43 2017 UTC (6 years, 10 months ago) by schoenebeck
File size: 34194 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     #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 schoenebeck 3150 //m_data.resize(type.size());
194 schoenebeck 3138 }
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 schoenebeck 3153 Member Object::memberByUID(const UID& uid) const {
240     if (!uid) return Member();
241     for (int i = 0; i < m_members.size(); ++i)
242     if (m_members[i].uid() == uid)
243     return m_members[i];
244     return Member();
245     }
246    
247 schoenebeck 3138 void Object::remove(const Member& member) {
248     for (int i = 0; i < m_members.size(); ++i) {
249     if (m_members[i] == member) {
250     m_members.erase(m_members.begin() + i);
251     return;
252     }
253     }
254     }
255    
256     std::vector<Member> Object::membersOfType(const DataType& type) const {
257     std::vector<Member> v;
258     for (int i = 0; i < m_members.size(); ++i) {
259     const Member& member = m_members[i];
260     if (member.type() == type)
261     v.push_back(member);
262     }
263     return v;
264     }
265    
266     int Object::sequenceIndexOf(const Member& member) const {
267     for (int i = 0; i < m_members.size(); ++i)
268     if (m_members[i] == member)
269     return i;
270     return -1;
271     }
272    
273     // *************** Archive ***************
274     // *
275    
276     Archive::Archive() {
277     m_operation = OPERATION_NONE;
278     m_root = NO_UID;
279 schoenebeck 3150 m_isModified = false;
280 schoenebeck 3138 }
281    
282     Archive::Archive(const RawData& data) {
283     m_operation = OPERATION_NONE;
284     m_root = NO_UID;
285 schoenebeck 3150 m_isModified = false;
286 schoenebeck 3138 decode(m_rawData);
287     }
288    
289     Archive::Archive(const uint8_t* data, size_t size) {
290     m_operation = OPERATION_NONE;
291     m_root = NO_UID;
292 schoenebeck 3150 m_isModified = false;
293 schoenebeck 3138 decode(data, size);
294     }
295    
296     Archive::~Archive() {
297     }
298    
299     Object& Archive::rootObject() {
300     return m_allObjects[m_root];
301     }
302    
303     static String _encodeBlob(String data) {
304     return ToString(data.length()) + ":" + data;
305     }
306    
307     static String _encode(const UID& uid) {
308     String s;
309     s += _encodeBlob(ToString(size_t(uid.id)));
310     s += _encodeBlob(ToString(size_t(uid.size)));
311     return _encodeBlob(s);
312     }
313    
314     static String _encode(const DataType& type) {
315     String s;
316     s += _encodeBlob(type.baseTypeName());
317     s += _encodeBlob(type.customTypeName());
318     s += _encodeBlob(ToString(type.size()));
319     s += _encodeBlob(ToString(type.isPointer()));
320     return _encodeBlob(s);
321     }
322    
323     static String _encode(const UIDChain& chain) {
324     String s;
325     for (int i = 0; i < chain.size(); ++i)
326     s += _encode(chain[i]);
327     return _encodeBlob(s);
328     }
329    
330     static String _encode(const Member& member) {
331     String s;
332     s += _encode(member.uid());
333     s += _encodeBlob(ToString(member.offset()));
334     s += _encodeBlob(member.name());
335     s += _encode(member.type());
336     return _encodeBlob(s);
337     }
338    
339     static String _encode(const std::vector<Member>& members) {
340     String s;
341     for (int i = 0; i < members.size(); ++i)
342     s += _encode(members[i]);
343     return _encodeBlob(s);
344     }
345    
346 schoenebeck 3150 static String _primitiveObjectValueToString(const Object& obj) {
347 schoenebeck 3138 String s;
348     const DataType& type = obj.type();
349     const ID& id = obj.uid().id;
350 schoenebeck 3150 void* ptr = obj.m_data.empty() ? (void*)id : (void*)&obj.m_data[0];
351     if (!obj.m_data.empty())
352     assert(type.size() == obj.m_data.size());
353 schoenebeck 3138 if (type.isPrimitive() && !type.isPointer()) {
354     if (type.isInteger() || type.isEnum()) {
355     if (type.isSigned()) {
356     if (type.size() == 1)
357 schoenebeck 3150 s = ToString((int16_t)*(int8_t*)ptr); // int16_t: prevent ToString() to render an ASCII character
358 schoenebeck 3138 else if (type.size() == 2)
359 schoenebeck 3150 s = ToString(*(int16_t*)ptr);
360 schoenebeck 3138 else if (type.size() == 4)
361 schoenebeck 3150 s = ToString(*(int32_t*)ptr);
362 schoenebeck 3138 else if (type.size() == 8)
363 schoenebeck 3150 s = ToString(*(int64_t*)ptr);
364 schoenebeck 3138 else
365     assert(false /* unknown signed int type size */);
366     } else {
367     if (type.size() == 1)
368 schoenebeck 3150 s = ToString((uint16_t)*(uint8_t*)ptr); // uint16_t: prevent ToString() to render an ASCII character
369 schoenebeck 3138 else if (type.size() == 2)
370 schoenebeck 3150 s = ToString(*(uint16_t*)ptr);
371 schoenebeck 3138 else if (type.size() == 4)
372 schoenebeck 3150 s = ToString(*(uint32_t*)ptr);
373 schoenebeck 3138 else if (type.size() == 8)
374 schoenebeck 3150 s = ToString(*(uint64_t*)ptr);
375 schoenebeck 3138 else
376     assert(false /* unknown unsigned int type size */);
377     }
378     } else if (type.isReal()) {
379     if (type.size() == sizeof(float))
380 schoenebeck 3150 s = ToString(*(float*)ptr);
381 schoenebeck 3138 else if (type.size() == sizeof(double))
382 schoenebeck 3150 s = ToString(*(double*)ptr);
383 schoenebeck 3138 else
384     assert(false /* unknown floating point type */);
385     } else if (type.isBool()) {
386 schoenebeck 3150 s = ToString(*(bool*)ptr);
387 schoenebeck 3138 } else {
388     assert(false /* unknown primitive type */);
389     }
390    
391     }
392 schoenebeck 3150 return s;
393 schoenebeck 3138 }
394    
395 schoenebeck 3150 static String _encodePrimitiveValue(const Object& obj) {
396     return _encodeBlob( _primitiveObjectValueToString(obj) );
397     }
398    
399 schoenebeck 3138 static String _encode(const Object& obj) {
400     String s;
401     s += _encode(obj.type());
402     s += _encodeBlob(ToString(obj.version()));
403     s += _encodeBlob(ToString(obj.minVersion()));
404     s += _encode(obj.uidChain());
405     s += _encode(obj.members());
406     s += _encodePrimitiveValue(obj);
407     return _encodeBlob(s);
408     }
409    
410     String _encode(const Archive::ObjectPool& objects) {
411     String s;
412     for (Archive::ObjectPool::const_iterator itObject = objects.begin();
413     itObject != objects.end(); ++itObject)
414     {
415     const Object& obj = itObject->second;
416     s += _encode(obj);
417     }
418     return _encodeBlob(s);
419     }
420    
421     #define MAGIC_START "Srx1v"
422     #define ENCODING_FORMAT_MINOR_VERSION 0
423    
424     String Archive::_encodeRootBlob() {
425     String s;
426     s += _encodeBlob(ToString(ENCODING_FORMAT_MINOR_VERSION));
427     s += _encode(m_root);
428     s += _encode(m_allObjects);
429     return _encodeBlob(s);
430     }
431    
432     void Archive::encode() {
433     m_rawData.clear();
434     String s = MAGIC_START;
435     s += _encodeRootBlob();
436     m_rawData.resize(s.length() + 1);
437     memcpy(&m_rawData[0], &s[0], s.length() + 1);
438 schoenebeck 3150 m_isModified = false;
439 schoenebeck 3138 }
440    
441     struct _Blob {
442     const char* p;
443     const char* end;
444     };
445    
446     static _Blob _decodeBlob(const char* p, const char* end, bool bThrow = true) {
447     if (!bThrow && p >= end)
448     return (_Blob) { p, end };
449     size_t sz = 0;
450     for (; true; ++p) {
451     if (p >= end)
452     throw Exception("Decode Error: Missing blob");
453     const char& c = *p;
454     if (c == ':') break;
455     if (c < '0' || c > '9')
456     throw Exception("Decode Error: Missing blob size");
457     sz *= 10;
458     sz += size_t(c - '0');
459     }
460     ++p;
461     if (p + sz > end)
462     throw Exception("Decode Error: Premature end of blob");
463     return (_Blob) { p, p + sz };
464     }
465    
466     template<typename T_int>
467     static T_int _popIntBlob(const char*& p, const char* end) {
468     _Blob blob = _decodeBlob(p, end);
469     p = blob.p;
470     end = blob.end;
471    
472     T_int sign = 1;
473     T_int i = 0;
474     if (p >= end)
475     throw Exception("Decode Error: premature end of int blob");
476     if (*p == '-') {
477     sign = -1;
478     ++p;
479     }
480     for (; p < end; ++p) {
481     const char& c = *p;
482     if (c < '0' || c > '9')
483     throw Exception("Decode Error: Invalid int blob format");
484     i *= 10;
485     i += size_t(c - '0');
486     }
487     return i * sign;
488     }
489    
490     template<typename T_int>
491     static void _popIntBlob(const char*& p, const char* end, RawData& rawData) {
492     const T_int i = _popIntBlob<T_int>(p, end);
493     *(T_int*)&rawData[0] = i;
494     }
495    
496     template<typename T_real>
497     static T_real _popRealBlob(const char*& p, const char* end) {
498     _Blob blob = _decodeBlob(p, end);
499     p = blob.p;
500     end = blob.end;
501    
502     if (p >= end || (end - p) < 1)
503     throw Exception("Decode Error: premature end of real blob");
504    
505     String s(p, size_t(end - p));
506    
507     T_real r;
508 schoenebeck 3139 if (sizeof(T_real) <= sizeof(double))
509 schoenebeck 3138 r = atof(s.c_str());
510     else
511     assert(false /* unknown real type */);
512    
513     p += s.length();
514    
515     return r;
516     }
517    
518     template<typename T_real>
519     static void _popRealBlob(const char*& p, const char* end, RawData& rawData) {
520     const T_real r = _popRealBlob<T_real>(p, end);
521     *(T_real*)&rawData[0] = r;
522     }
523    
524     static String _popStringBlob(const char*& p, const char* end) {
525     _Blob blob = _decodeBlob(p, end);
526     p = blob.p;
527     end = blob.end;
528     if (end - p < 0)
529     throw Exception("Decode Error: missing String blob");
530     String s;
531     const size_t sz = end - p;
532     s.resize(sz);
533     memcpy(&s[0], p, sz);
534     p += sz;
535     return s;
536     }
537    
538     DataType _popDataTypeBlob(const char*& p, const char* end) {
539     _Blob blob = _decodeBlob(p, end);
540     p = blob.p;
541     end = blob.end;
542    
543     DataType type;
544     type.m_baseTypeName = _popStringBlob(p, end);
545     type.m_customTypeName = _popStringBlob(p, end);
546     type.m_size = _popIntBlob<int>(p, end);
547     type.m_isPointer = _popIntBlob<bool>(p, end);
548     return type;
549     }
550    
551     static UID _popUIDBlob(const char*& p, const char* end) {
552     _Blob blob = _decodeBlob(p, end);
553     p = blob.p;
554     end = blob.end;
555    
556     if (p >= end)
557     throw Exception("Decode Error: premature end of UID blob");
558    
559     const ID id = (ID) _popIntBlob<size_t>(p, end);
560     const size_t size = _popIntBlob<size_t>(p, end);
561    
562     return (UID) { id, size };
563     }
564    
565     static UIDChain _popUIDChainBlob(const char*& p, const char* end) {
566     _Blob blob = _decodeBlob(p, end);
567     p = blob.p;
568     end = blob.end;
569    
570     UIDChain chain;
571     while (p < end) {
572     const UID uid = _popUIDBlob(p, end);
573     chain.push_back(uid);
574     }
575     assert(!chain.empty());
576     return chain;
577     }
578    
579 schoenebeck 3146 static Member _popMemberBlob(const char*& p, const char* end) {
580 schoenebeck 3138 _Blob blob = _decodeBlob(p, end, false);
581     p = blob.p;
582     end = blob.end;
583    
584     Member m;
585     if (p >= end) return m;
586    
587     m.m_uid = _popUIDBlob(p, end);
588     m.m_offset = _popIntBlob<size_t>(p, end);
589     m.m_name = _popStringBlob(p, end);
590     m.m_type = _popDataTypeBlob(p, end);
591     assert(m.type());
592     assert(!m.name().empty());
593 schoenebeck 3146 assert(m.uid().isValid());
594 schoenebeck 3138 return m;
595     }
596    
597     static std::vector<Member> _popMembersBlob(const char*& p, const char* end) {
598     _Blob blob = _decodeBlob(p, end, false);
599     p = blob.p;
600     end = blob.end;
601    
602     std::vector<Member> members;
603     while (p < end) {
604     const Member member = _popMemberBlob(p, end);
605     if (member)
606     members.push_back(member);
607     else
608     break;
609     }
610     return members;
611     }
612    
613 schoenebeck 3146 static void _popPrimitiveValue(const char*& p, const char* end, Object& obj) {
614 schoenebeck 3138 const DataType& type = obj.type();
615     if (type.isPrimitive() && !type.isPointer()) {
616     obj.m_data.resize(type.size());
617     if (type.isInteger() || type.isEnum()) {
618     if (type.isSigned()) {
619     if (type.size() == 1)
620     _popIntBlob<int8_t>(p, end, obj.m_data);
621     else if (type.size() == 2)
622     _popIntBlob<int16_t>(p, end, obj.m_data);
623     else if (type.size() == 4)
624     _popIntBlob<int32_t>(p, end, obj.m_data);
625     else if (type.size() == 8)
626     _popIntBlob<int64_t>(p, end, obj.m_data);
627     else
628     assert(false /* unknown signed int type size */);
629     } else {
630     if (type.size() == 1)
631     _popIntBlob<uint8_t>(p, end, obj.m_data);
632     else if (type.size() == 2)
633     _popIntBlob<uint16_t>(p, end, obj.m_data);
634     else if (type.size() == 4)
635     _popIntBlob<uint32_t>(p, end, obj.m_data);
636     else if (type.size() == 8)
637     _popIntBlob<uint64_t>(p, end, obj.m_data);
638     else
639     assert(false /* unknown unsigned int type size */);
640     }
641     } else if (type.isReal()) {
642     if (type.size() == sizeof(float))
643     _popRealBlob<float>(p, end, obj.m_data);
644     else if (type.size() == sizeof(double))
645     _popRealBlob<double>(p, end, obj.m_data);
646     else
647     assert(false /* unknown floating point type */);
648     } else if (type.isBool()) {
649     _popIntBlob<uint8_t>(p, end, obj.m_data);
650     } else {
651     assert(false /* unknown primitive type */);
652     }
653    
654     } else {
655     // don't whine if the empty blob was not added on encoder side
656     _Blob blob = _decodeBlob(p, end, false);
657     p = blob.p;
658     end = blob.end;
659     }
660     }
661    
662 schoenebeck 3146 static Object _popObjectBlob(const char*& p, const char* end) {
663 schoenebeck 3138 _Blob blob = _decodeBlob(p, end, false);
664     p = blob.p;
665     end = blob.end;
666    
667     Object obj;
668     if (p >= end) return obj;
669    
670     obj.m_type = _popDataTypeBlob(p, end);
671     obj.m_version = _popIntBlob<Version>(p, end);
672     obj.m_minVersion = _popIntBlob<Version>(p, end);
673     obj.m_uid = _popUIDChainBlob(p, end);
674     obj.m_members = _popMembersBlob(p, end);
675     _popPrimitiveValue(p, end, obj);
676     assert(obj.type());
677     return obj;
678     }
679    
680     void Archive::_popObjectsBlob(const char*& p, const char* end) {
681     _Blob blob = _decodeBlob(p, end, false);
682     p = blob.p;
683     end = blob.end;
684    
685     if (p >= end)
686     throw Exception("Decode Error: Premature end of objects blob");
687    
688     while (true) {
689     const Object obj = _popObjectBlob(p, end);
690     if (!obj) break;
691     m_allObjects[obj.uid()] = obj;
692     }
693     }
694    
695     void Archive::_popRootBlob(const char*& p, const char* end) {
696     _Blob blob = _decodeBlob(p, end, false);
697     p = blob.p;
698     end = blob.end;
699    
700     if (p >= end)
701     throw Exception("Decode Error: Premature end of root blob");
702    
703     // just in case this encoding format will be extended in future
704     // (currently not used)
705     const int formatMinorVersion = _popIntBlob<int>(p, end);
706    
707     m_root = _popUIDBlob(p, end);
708     if (!m_root)
709     throw Exception("Decode Error: No root object");
710    
711     _popObjectsBlob(p, end);
712     if (!m_allObjects[m_root])
713     throw Exception("Decode Error: Missing declared root object");
714     }
715    
716     void Archive::decode(const RawData& data) {
717     m_rawData = data;
718     m_allObjects.clear();
719 schoenebeck 3150 m_isModified = false;
720 schoenebeck 3138 const char* p = (const char*) &data[0];
721     const char* end = p + data.size();
722     if (memcmp(p, MAGIC_START, std::min(strlen(MAGIC_START), data.size())))
723     throw Exception("Decode Error: Magic start missing!");
724     p += strlen(MAGIC_START);
725     _popRootBlob(p, end);
726     }
727    
728     void Archive::decode(const uint8_t* data, size_t size) {
729     RawData rawData;
730     rawData.resize(size);
731     memcpy(&rawData[0], data, size);
732     decode(rawData);
733     }
734    
735 schoenebeck 3150 const RawData& Archive::rawData() {
736     if (m_isModified) encode();
737     return m_rawData;
738     }
739    
740 schoenebeck 3138 String Archive::rawDataFormat() const {
741     return MAGIC_START;
742     }
743    
744 schoenebeck 3150 bool Archive::isModified() const {
745     return m_isModified;
746     }
747    
748 schoenebeck 3138 void Archive::clear() {
749     m_allObjects.clear();
750     m_operation = OPERATION_NONE;
751     m_root = NO_UID;
752     m_rawData.clear();
753 schoenebeck 3150 m_isModified = false;
754 schoenebeck 3138 }
755    
756 schoenebeck 3153 void Archive::removeMember(Object& parent, const Member& member) {
757     parent.remove(member);
758     m_isModified = true;
759     }
760    
761 schoenebeck 3138 void Archive::remove(const Object& obj) {
762 schoenebeck 3153 //FIXME: Should traverse from root object and remove all members associated with this object
763 schoenebeck 3138 if (!obj.uid()) return;
764     m_allObjects.erase(obj.uid());
765 schoenebeck 3150 m_isModified = true;
766 schoenebeck 3138 }
767    
768     Object& Archive::objectByUID(const UID& uid) {
769     return m_allObjects[uid];
770     }
771    
772 schoenebeck 3150 void Archive::setEnumValue(Object& object, uint64_t value) {
773     if (!object) return;
774     if (!object.type().isEnum())
775     throw Exception("Not an enum data type");
776     Object* pObject = &object;
777     if (object.type().isPointer()) {
778     Object& obj = objectByUID(object.uid(1));
779     if (!obj) return;
780     pObject = &obj;
781     }
782     const int nativeEnumSize = sizeof(enum operation_t);
783     DataType& type = const_cast<DataType&>( pObject->type() );
784     // original serializer ("sender") might have had a different word size
785     // than this machine, adjust type object in this case
786     if (type.size() != nativeEnumSize) {
787     type.m_size = nativeEnumSize;
788     }
789     pObject->m_data.resize(type.size());
790     void* ptr = &pObject->m_data[0];
791     if (type.size() == 1)
792     *(uint8_t*)ptr = (uint8_t)value;
793     else if (type.size() == 2)
794     *(uint16_t*)ptr = (uint16_t)value;
795     else if (type.size() == 4)
796     *(uint32_t*)ptr = (uint32_t)value;
797     else if (type.size() == 8)
798     *(uint64_t*)ptr = (uint64_t)value;
799     else
800     assert(false /* unknown enum type size */);
801     m_isModified = true;
802     }
803    
804     void Archive::setIntValue(Object& object, int64_t value) {
805     if (!object) return;
806     if (!object.type().isInteger())
807     throw Exception("Not an integer data type");
808     Object* pObject = &object;
809     if (object.type().isPointer()) {
810     Object& obj = objectByUID(object.uid(1));
811     if (!obj) return;
812     pObject = &obj;
813     }
814     const DataType& type = pObject->type();
815     pObject->m_data.resize(type.size());
816     void* ptr = &pObject->m_data[0];
817     if (type.isSigned()) {
818     if (type.size() == 1)
819     *(int8_t*)ptr = (int8_t)value;
820     else if (type.size() == 2)
821     *(int16_t*)ptr = (int16_t)value;
822     else if (type.size() == 4)
823     *(int32_t*)ptr = (int32_t)value;
824     else if (type.size() == 8)
825     *(int64_t*)ptr = (int64_t)value;
826     else
827     assert(false /* unknown signed int type size */);
828     } else {
829     if (type.size() == 1)
830     *(uint8_t*)ptr = (uint8_t)value;
831     else if (type.size() == 2)
832     *(uint16_t*)ptr = (uint16_t)value;
833     else if (type.size() == 4)
834     *(uint32_t*)ptr = (uint32_t)value;
835     else if (type.size() == 8)
836     *(uint64_t*)ptr = (uint64_t)value;
837     else
838     assert(false /* unknown unsigned int type size */);
839     }
840     m_isModified = true;
841     }
842    
843     void Archive::setRealValue(Object& object, double value) {
844     if (!object) return;
845     if (!object.type().isReal())
846     throw Exception("Not a real data type");
847     Object* pObject = &object;
848     if (object.type().isPointer()) {
849     Object& obj = objectByUID(object.uid(1));
850     if (!obj) return;
851     pObject = &obj;
852     }
853     const DataType& type = pObject->type();
854     pObject->m_data.resize(type.size());
855     void* ptr = &pObject->m_data[0];
856     if (type.size() == sizeof(float))
857     *(float*)ptr = (float)value;
858     else if (type.size() == sizeof(double))
859     *(double*)ptr = (double)value;
860     else
861     assert(false /* unknown real type size */);
862     m_isModified = true;
863     }
864    
865     void Archive::setBoolValue(Object& object, bool value) {
866     if (!object) return;
867     if (!object.type().isBool())
868     throw Exception("Not a bool data type");
869     Object* pObject = &object;
870     if (object.type().isPointer()) {
871     Object& obj = objectByUID(object.uid(1));
872     if (!obj) return;
873     pObject = &obj;
874     }
875     const DataType& type = pObject->type();
876     pObject->m_data.resize(type.size());
877     bool* ptr = (bool*)&pObject->m_data[0];
878     *ptr = value;
879     m_isModified = true;
880     }
881    
882     void Archive::setAutoValue(Object& object, String value) {
883     if (!object) return;
884     const DataType& type = object.type();
885     if (type.isInteger())
886     setIntValue(object, atoll(value.c_str()));
887     else if (type.isReal())
888     setRealValue(object, atof(value.c_str()));
889     else if (type.isBool())
890     setBoolValue(object, atof(value.c_str()));
891     else if (type.isEnum())
892     setEnumValue(object, atoll(value.c_str()));
893     else
894     throw Exception("Not a primitive data type");
895     }
896    
897     String Archive::valueAsString(const Object& object) {
898     if (!object)
899     throw Exception("Invalid object");
900     if (object.type().isClass())
901     throw Exception("Object is class type");
902     const Object* pObject = &object;
903     if (object.type().isPointer()) {
904     const Object& obj = objectByUID(object.uid(1));
905     if (!obj) return "";
906     pObject = &obj;
907     }
908     return _primitiveObjectValueToString(*pObject);
909     }
910    
911 schoenebeck 3138 // *************** Archive::Syncer ***************
912     // *
913    
914     Archive::Syncer::Syncer(Archive& dst, Archive& src)
915     : m_dst(dst), m_src(src)
916     {
917     const Object srcRootObj = src.rootObject();
918     const Object dstRootObj = dst.rootObject();
919     if (!srcRootObj)
920     throw Exception("No source root object!");
921     if (!dstRootObj)
922     throw Exception("Expected destination root object not found!");
923     syncObject(dstRootObj, srcRootObj);
924     }
925    
926     void Archive::Syncer::syncPrimitive(const Object& dstObj, const Object& srcObj) {
927     assert(srcObj.rawData().size() == dstObj.type().size());
928     void* pDst = (void*)dstObj.uid().id;
929     memcpy(pDst, &srcObj.rawData()[0], dstObj.type().size());
930     }
931    
932     void Archive::Syncer::syncPointer(const Object& dstObj, const Object& srcObj) {
933     assert(dstObj.type().isPointer());
934     assert(dstObj.type() == srcObj.type());
935     const Object& pointedDstObject = m_dst.m_allObjects[dstObj.uid(1)];
936     const Object& pointedSrcObject = m_src.m_allObjects[srcObj.uid(1)];
937     syncObject(pointedDstObject, pointedSrcObject);
938     }
939    
940     void Archive::Syncer::syncObject(const Object& dstObj, const Object& srcObj) {
941     if (!dstObj || !srcObj) return; // end of recursion
942     if (!dstObj.isVersionCompatibleTo(srcObj))
943     throw Exception("Version incompatible (destination version " +
944     ToString(dstObj.version()) + " [min. version " +
945     ToString(dstObj.minVersion()) + "], source version " +
946     ToString(srcObj.version()) + " [min. version " +
947     ToString(srcObj.minVersion()) + "])");
948     if (dstObj.type() != srcObj.type())
949     throw Exception("Incompatible data structure type (destination type " +
950     dstObj.type().asLongDescr() + " vs. source type " +
951     srcObj.type().asLongDescr() + ")");
952    
953     // prevent syncing this object again, and thus also prevent endless
954     // loop on data structures with cyclic relations
955     m_dst.m_allObjects.erase(dstObj.uid());
956    
957     if (dstObj.type().isPrimitive() && !dstObj.type().isPointer()) {
958     syncPrimitive(dstObj, srcObj);
959     return; // end of recursion
960     }
961    
962     if (dstObj.type().isPointer()) {
963     syncPointer(dstObj, srcObj);
964     return;
965     }
966    
967     assert(dstObj.type().isClass());
968     for (int iMember = 0; iMember < srcObj.members().size(); ++iMember) {
969     const Member& srcMember = srcObj.members()[iMember];
970     Member dstMember = dstMemberMatching(dstObj, srcObj, srcMember);
971     if (!dstMember)
972     throw Exception("Expected member missing in destination object");
973     syncMember(dstMember, srcMember);
974     }
975     }
976    
977     Member Archive::Syncer::dstMemberMatching(const Object& dstObj, const Object& srcObj, const Member& srcMember) {
978     Member dstMember = dstObj.memberNamed(srcMember.name());
979     if (dstMember)
980     return (dstMember.type() == srcMember.type()) ? dstMember : Member();
981     std::vector<Member> members = dstObj.membersOfType(srcMember.type());
982     if (members.size() <= 0)
983     return Member();
984     if (members.size() == 1)
985     return members[0];
986     for (int i = 0; i < members.size(); ++i)
987     if (members[i].offset() == srcMember.offset())
988     return members[i];
989     const int srcSeqNr = srcObj.sequenceIndexOf(srcMember);
990     assert(srcSeqNr >= 0); // should never happen, otherwise there is a bug
991     for (int i = 0; i < members.size(); ++i) {
992     const int dstSeqNr = dstObj.sequenceIndexOf(members[i]);
993     if (dstSeqNr == srcSeqNr)
994     return members[i];
995     }
996     return Member(); // give up!
997     }
998    
999     void Archive::Syncer::syncMember(const Member& dstMember, const Member& srcMember) {
1000     assert(dstMember && srcMember);
1001     assert(dstMember.type() == srcMember.type());
1002     const Object dstObj = m_dst.m_allObjects[dstMember.uid()];
1003     const Object srcObj = m_src.m_allObjects[srcMember.uid()];
1004     syncObject(dstObj, srcObj);
1005     }
1006    
1007     // *************** Exception ***************
1008     // *
1009    
1010     void Exception::PrintMessage() {
1011     std::cout << "Serialization::Exception: " << Message << std::endl;
1012     }
1013    
1014     } // namespace Serialization

  ViewVC Help
Powered by ViewVC