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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3153 - (show annotations) (download)
Sat May 6 13:43:43 2017 UTC (3 years, 5 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 /***************************************************************************
2 * *
3 * Copyright (C) 2017 Christian Schoenebeck *
4 * <cuse@users.sourceforge.net> *
5 * *
6 * This library is part of libgig. *
7 * *
8 * This library is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
12 * *
13 * This library is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU General Public License *
19 * along with this library; if not, write to the Free Software *
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
21 * MA 02111-1307 USA *
22 ***************************************************************************/
23
24 #include "Serialization.h"
25
26 #include <iostream>
27 #include <assert.h>
28 #include <string.h> // for memcpy()
29 #include <stdlib.h> // for atof()
30
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 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 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 m_isModified = false;
280 }
281
282 Archive::Archive(const RawData& data) {
283 m_operation = OPERATION_NONE;
284 m_root = NO_UID;
285 m_isModified = false;
286 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 m_isModified = false;
293 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 static String _primitiveObjectValueToString(const Object& obj) {
347 String s;
348 const DataType& type = obj.type();
349 const ID& id = obj.uid().id;
350 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 if (type.isPrimitive() && !type.isPointer()) {
354 if (type.isInteger() || type.isEnum()) {
355 if (type.isSigned()) {
356 if (type.size() == 1)
357 s = ToString((int16_t)*(int8_t*)ptr); // int16_t: prevent ToString() to render an ASCII character
358 else if (type.size() == 2)
359 s = ToString(*(int16_t*)ptr);
360 else if (type.size() == 4)
361 s = ToString(*(int32_t*)ptr);
362 else if (type.size() == 8)
363 s = ToString(*(int64_t*)ptr);
364 else
365 assert(false /* unknown signed int type size */);
366 } else {
367 if (type.size() == 1)
368 s = ToString((uint16_t)*(uint8_t*)ptr); // uint16_t: prevent ToString() to render an ASCII character
369 else if (type.size() == 2)
370 s = ToString(*(uint16_t*)ptr);
371 else if (type.size() == 4)
372 s = ToString(*(uint32_t*)ptr);
373 else if (type.size() == 8)
374 s = ToString(*(uint64_t*)ptr);
375 else
376 assert(false /* unknown unsigned int type size */);
377 }
378 } else if (type.isReal()) {
379 if (type.size() == sizeof(float))
380 s = ToString(*(float*)ptr);
381 else if (type.size() == sizeof(double))
382 s = ToString(*(double*)ptr);
383 else
384 assert(false /* unknown floating point type */);
385 } else if (type.isBool()) {
386 s = ToString(*(bool*)ptr);
387 } else {
388 assert(false /* unknown primitive type */);
389 }
390
391 }
392 return s;
393 }
394
395 static String _encodePrimitiveValue(const Object& obj) {
396 return _encodeBlob( _primitiveObjectValueToString(obj) );
397 }
398
399 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 m_isModified = false;
439 }
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 if (sizeof(T_real) <= sizeof(double))
509 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 static Member _popMemberBlob(const char*& p, const char* end) {
580 _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 assert(m.uid().isValid());
594 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 static void _popPrimitiveValue(const char*& p, const char* end, Object& obj) {
614 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 static Object _popObjectBlob(const char*& p, const char* end) {
663 _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 m_isModified = false;
720 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 const RawData& Archive::rawData() {
736 if (m_isModified) encode();
737 return m_rawData;
738 }
739
740 String Archive::rawDataFormat() const {
741 return MAGIC_START;
742 }
743
744 bool Archive::isModified() const {
745 return m_isModified;
746 }
747
748 void Archive::clear() {
749 m_allObjects.clear();
750 m_operation = OPERATION_NONE;
751 m_root = NO_UID;
752 m_rawData.clear();
753 m_isModified = false;
754 }
755
756 void Archive::removeMember(Object& parent, const Member& member) {
757 parent.remove(member);
758 m_isModified = true;
759 }
760
761 void Archive::remove(const Object& obj) {
762 //FIXME: Should traverse from root object and remove all members associated with this object
763 if (!obj.uid()) return;
764 m_allObjects.erase(obj.uid());
765 m_isModified = true;
766 }
767
768 Object& Archive::objectByUID(const UID& uid) {
769 return m_allObjects[uid];
770 }
771
772 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 // *************** 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