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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3150 - (hide annotations) (download)
Fri May 5 18:42:06 2017 UTC (6 years, 10 months ago) by schoenebeck
File size: 33702 byte(s)
* Serialization.cpp/.h: Added new methods isModified(),
  setAutoValue(), setIntValue(), setRealValue(),
  setBoolValue(), setEnumValue(), valueAsString() to
  class Archive.
* Serialization.cpp/.h: Archive::rawData(): Automatically
  re-encode new raw data stream if archive had been
  modified (i.e. by remove(), setAutoValue(), etc.).
* Bumped version (4.0.0.svn16).

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

  ViewVC Help
Powered by ViewVC