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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3173 - (show annotations) (download)
Wed May 10 23:07:28 2017 UTC (6 years, 11 months ago) by schoenebeck
File size: 40623 byte(s)
* Print compiler warning if no RTTI available.
* Serialization::DataType class: Implemented demangling C++ type
  names (for methods asLongDescr() and
  customTypeName(bool demangle=false)).
* gig.h: When there is no RTTI, only hide API functions which
  really require RTTI.
* Bumped version (4.0.0.svn21).

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 #include <cxxabi.h>
31
32 #include "helper.h"
33
34 #define LIBGIG_EPOCH_TIME ((time_t)0)
35
36 namespace Serialization {
37
38 // *************** DataType ***************
39 // *
40
41 static UID _createNullUID() {
42 const UID uid = { NULL, 0 };
43 return uid;
44 }
45
46 const UID NO_UID = _createNullUID();
47
48 bool UID::isValid() const {
49 return id != NULL && id != (void*)-1 && size;
50 }
51
52 // *************** DataType ***************
53 // *
54
55 DataType::DataType() {
56 m_size = 0;
57 m_isPointer = false;
58 }
59
60 DataType::DataType(bool isPointer, int size, String baseType, String customType) {
61 m_size = size;
62 m_isPointer = isPointer;
63 m_baseTypeName = baseType;
64 m_customTypeName = customType;
65 }
66
67 bool DataType::isValid() const {
68 return m_size;
69 }
70
71 bool DataType::isPointer() const {
72 return m_isPointer;
73 }
74
75 bool DataType::isClass() const {
76 return m_baseTypeName == "class";
77 }
78
79 bool DataType::isPrimitive() const {
80 return !isClass();
81 }
82
83 bool DataType::isInteger() const {
84 return m_baseTypeName.substr(0, 3) == "int" ||
85 m_baseTypeName.substr(0, 4) == "uint";
86 }
87
88 bool DataType::isReal() const {
89 return m_baseTypeName.substr(0, 4) == "real";
90 }
91
92 bool DataType::isBool() const {
93 return m_baseTypeName == "bool";
94 }
95
96 bool DataType::isEnum() const {
97 return m_baseTypeName == "enum";
98 }
99
100 bool DataType::isSigned() const {
101 return m_baseTypeName.substr(0, 3) == "int" ||
102 isReal();
103 }
104
105 bool DataType::operator==(const DataType& other) const {
106 return m_baseTypeName == other.m_baseTypeName &&
107 m_customTypeName == other.m_customTypeName &&
108 m_size == other.m_size &&
109 m_isPointer == other.m_isPointer;
110 }
111
112 bool DataType::operator!=(const DataType& other) const {
113 return !operator==(other);
114 }
115
116 bool DataType::operator<(const DataType& other) const {
117 return m_baseTypeName < other.m_baseTypeName ||
118 (m_baseTypeName == other.m_baseTypeName &&
119 m_customTypeName < other.m_customTypeName ||
120 (m_customTypeName == other.m_customTypeName &&
121 m_size < other.m_size ||
122 (m_size == other.m_size &&
123 m_isPointer < other.m_isPointer)));
124 }
125
126 bool DataType::operator>(const DataType& other) const {
127 return !(operator==(other) || operator<(other));
128 }
129
130 String DataType::asLongDescr() const {
131 String s = m_baseTypeName;
132 if (!m_customTypeName.empty())
133 s += " " + customTypeName(true);
134 if (isPointer())
135 s += " pointer";
136 return s;
137 }
138
139 String DataType::customTypeName(bool demangle) const {
140 if (!demangle) return m_customTypeName;
141 int status;
142 const char* result =
143 abi::__cxa_demangle(m_customTypeName.c_str(), 0, 0, &status);
144 return (status == 0) ? result : m_customTypeName;
145 }
146
147 // *************** Member ***************
148 // *
149
150 Member::Member() {
151 m_uid = NO_UID;
152 m_offset = 0;
153 }
154
155 Member::Member(String name, UID uid, size_t offset, DataType type) {
156 m_name = name;
157 m_uid = uid;
158 m_offset = offset;
159 m_type = type;
160 }
161
162 bool Member::isValid() const {
163 return m_uid && !m_name.empty() && m_type;
164 }
165
166 bool Member::operator==(const Member& other) const {
167 return m_uid == other.m_uid &&
168 m_offset == other.m_offset &&
169 m_name == other.m_name &&
170 m_type == other.m_type;
171 }
172
173 bool Member::operator!=(const Member& other) const {
174 return !operator==(other);
175 }
176
177 bool Member::operator<(const Member& other) const {
178 return m_uid < other.m_uid ||
179 (m_uid == other.m_uid &&
180 m_offset < other.m_offset ||
181 (m_offset == other.m_offset &&
182 m_name < other.m_name ||
183 (m_name == other.m_name &&
184 m_type < other.m_type)));
185 }
186
187 bool Member::operator>(const Member& other) const {
188 return !(operator==(other) || operator<(other));
189 }
190
191 // *************** Object ***************
192 // *
193
194 Object::Object() {
195 m_version = 0;
196 m_minVersion = 0;
197 }
198
199 Object::Object(UIDChain uidChain, DataType type) {
200 m_type = type;
201 m_uid = uidChain;
202 m_version = 0;
203 m_minVersion = 0;
204 //m_data.resize(type.size());
205 }
206
207 bool Object::isValid() const {
208 return m_type && !m_uid.empty();
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_type == other.m_type;
216 }
217
218 bool Object::operator!=(const Object& other) const {
219 return !operator==(other);
220 }
221
222 bool Object::operator<(const Object& other) const {
223 // ignoring all other member variables here
224 // (since UID stands for "unique" ;-) )
225 return m_uid < other.m_uid ||
226 (m_uid == other.m_uid &&
227 m_type < other.m_type);
228 }
229
230 bool Object::operator>(const Object& other) const {
231 return !(operator==(other) || operator<(other));
232 }
233
234 bool Object::isVersionCompatibleTo(const Object& other) const {
235 if (this->version() == other.version())
236 return true;
237 if (this->version() > other.version())
238 return this->minVersion() <= other.version();
239 else
240 return other.minVersion() <= this->version();
241 }
242
243 Member Object::memberNamed(String name) const {
244 for (int i = 0; i < m_members.size(); ++i)
245 if (m_members[i].name() == name)
246 return m_members[i];
247 return Member();
248 }
249
250 Member Object::memberByUID(const UID& uid) const {
251 if (!uid) return Member();
252 for (int i = 0; i < m_members.size(); ++i)
253 if (m_members[i].uid() == uid)
254 return m_members[i];
255 return Member();
256 }
257
258 void Object::remove(const Member& member) {
259 for (int i = 0; i < m_members.size(); ++i) {
260 if (m_members[i] == member) {
261 m_members.erase(m_members.begin() + i);
262 return;
263 }
264 }
265 }
266
267 std::vector<Member> Object::membersOfType(const DataType& type) const {
268 std::vector<Member> v;
269 for (int i = 0; i < m_members.size(); ++i) {
270 const Member& member = m_members[i];
271 if (member.type() == type)
272 v.push_back(member);
273 }
274 return v;
275 }
276
277 int Object::sequenceIndexOf(const Member& member) const {
278 for (int i = 0; i < m_members.size(); ++i)
279 if (m_members[i] == member)
280 return i;
281 return -1;
282 }
283
284 // *************** Archive ***************
285 // *
286
287 Archive::Archive() {
288 m_operation = OPERATION_NONE;
289 m_root = NO_UID;
290 m_isModified = false;
291 m_timeCreated = m_timeModified = LIBGIG_EPOCH_TIME;
292 }
293
294 Archive::Archive(const RawData& data) {
295 m_operation = OPERATION_NONE;
296 m_root = NO_UID;
297 m_isModified = false;
298 m_timeCreated = m_timeModified = LIBGIG_EPOCH_TIME;
299 decode(m_rawData);
300 }
301
302 Archive::Archive(const uint8_t* data, size_t size) {
303 m_operation = OPERATION_NONE;
304 m_root = NO_UID;
305 m_isModified = false;
306 m_timeCreated = m_timeModified = LIBGIG_EPOCH_TIME;
307 decode(data, size);
308 }
309
310 Archive::~Archive() {
311 }
312
313 Object& Archive::rootObject() {
314 return m_allObjects[m_root];
315 }
316
317 static String _encodeBlob(String data) {
318 return ToString(data.length()) + ":" + data;
319 }
320
321 static String _encode(const UID& uid) {
322 String s;
323 s += _encodeBlob(ToString(size_t(uid.id)));
324 s += _encodeBlob(ToString(size_t(uid.size)));
325 return _encodeBlob(s);
326 }
327
328 static String _encode(const time_t& time) {
329 return _encodeBlob(ToString(time));
330 }
331
332 static String _encode(const DataType& type) {
333 String s;
334 s += _encodeBlob(type.baseTypeName());
335 s += _encodeBlob(type.customTypeName());
336 s += _encodeBlob(ToString(type.size()));
337 s += _encodeBlob(ToString(type.isPointer()));
338 return _encodeBlob(s);
339 }
340
341 static String _encode(const UIDChain& chain) {
342 String s;
343 for (int i = 0; i < chain.size(); ++i)
344 s += _encode(chain[i]);
345 return _encodeBlob(s);
346 }
347
348 static String _encode(const Member& member) {
349 String s;
350 s += _encode(member.uid());
351 s += _encodeBlob(ToString(member.offset()));
352 s += _encodeBlob(member.name());
353 s += _encode(member.type());
354 return _encodeBlob(s);
355 }
356
357 static String _encode(const std::vector<Member>& members) {
358 String s;
359 for (int i = 0; i < members.size(); ++i)
360 s += _encode(members[i]);
361 return _encodeBlob(s);
362 }
363
364 static String _primitiveObjectValueToString(const Object& obj) {
365 String s;
366 const DataType& type = obj.type();
367 const ID& id = obj.uid().id;
368 void* ptr = obj.m_data.empty() ? (void*)id : (void*)&obj.m_data[0];
369 if (!obj.m_data.empty())
370 assert(type.size() == obj.m_data.size());
371 if (type.isPrimitive() && !type.isPointer()) {
372 if (type.isInteger() || type.isEnum()) {
373 if (type.isSigned()) {
374 if (type.size() == 1)
375 s = ToString((int16_t)*(int8_t*)ptr); // int16_t: prevent ToString() to render an ASCII character
376 else if (type.size() == 2)
377 s = ToString(*(int16_t*)ptr);
378 else if (type.size() == 4)
379 s = ToString(*(int32_t*)ptr);
380 else if (type.size() == 8)
381 s = ToString(*(int64_t*)ptr);
382 else
383 assert(false /* unknown signed int type size */);
384 } else {
385 if (type.size() == 1)
386 s = ToString((uint16_t)*(uint8_t*)ptr); // uint16_t: prevent ToString() to render an ASCII character
387 else if (type.size() == 2)
388 s = ToString(*(uint16_t*)ptr);
389 else if (type.size() == 4)
390 s = ToString(*(uint32_t*)ptr);
391 else if (type.size() == 8)
392 s = ToString(*(uint64_t*)ptr);
393 else
394 assert(false /* unknown unsigned int type size */);
395 }
396 } else if (type.isReal()) {
397 if (type.size() == sizeof(float))
398 s = ToString(*(float*)ptr);
399 else if (type.size() == sizeof(double))
400 s = ToString(*(double*)ptr);
401 else
402 assert(false /* unknown floating point type */);
403 } else if (type.isBool()) {
404 s = ToString(*(bool*)ptr);
405 } else {
406 assert(false /* unknown primitive type */);
407 }
408
409 }
410 return s;
411 }
412
413 template<typename T>
414 static T _primitiveObjectValueToNumber(const Object& obj) {
415 T value = 0;
416 const DataType& type = obj.type();
417 const ID& id = obj.uid().id;
418 void* ptr = obj.m_data.empty() ? (void*)id : (void*)&obj.m_data[0];
419 if (!obj.m_data.empty())
420 assert(type.size() == obj.m_data.size());
421 if (type.isPrimitive() && !type.isPointer()) {
422 if (type.isInteger() || type.isEnum()) {
423 if (type.isSigned()) {
424 if (type.size() == 1)
425 value = (T)*(int8_t*)ptr;
426 else if (type.size() == 2)
427 value = (T)*(int16_t*)ptr;
428 else if (type.size() == 4)
429 value = (T)*(int32_t*)ptr;
430 else if (type.size() == 8)
431 value = (T)*(int64_t*)ptr;
432 else
433 assert(false /* unknown signed int type size */);
434 } else {
435 if (type.size() == 1)
436 value = (T)*(uint8_t*)ptr;
437 else if (type.size() == 2)
438 value = (T)*(uint16_t*)ptr;
439 else if (type.size() == 4)
440 value = (T)*(uint32_t*)ptr;
441 else if (type.size() == 8)
442 value = (T)*(uint64_t*)ptr;
443 else
444 assert(false /* unknown unsigned int type size */);
445 }
446 } else if (type.isReal()) {
447 if (type.size() == sizeof(float))
448 value = (T)*(float*)ptr;
449 else if (type.size() == sizeof(double))
450 value = (T)*(double*)ptr;
451 else
452 assert(false /* unknown floating point type */);
453 } else if (type.isBool()) {
454 value = (T)*(bool*)ptr;
455 } else {
456 assert(false /* unknown primitive type */);
457 }
458 }
459 return value;
460 }
461
462 static String _encodePrimitiveValue(const Object& obj) {
463 return _encodeBlob( _primitiveObjectValueToString(obj) );
464 }
465
466 static String _encode(const Object& obj) {
467 String s;
468 s += _encode(obj.type());
469 s += _encodeBlob(ToString(obj.version()));
470 s += _encodeBlob(ToString(obj.minVersion()));
471 s += _encode(obj.uidChain());
472 s += _encode(obj.members());
473 s += _encodePrimitiveValue(obj);
474 return _encodeBlob(s);
475 }
476
477 String _encode(const Archive::ObjectPool& objects) {
478 String s;
479 for (Archive::ObjectPool::const_iterator itObject = objects.begin();
480 itObject != objects.end(); ++itObject)
481 {
482 const Object& obj = itObject->second;
483 s += _encode(obj);
484 }
485 return _encodeBlob(s);
486 }
487
488 #define MAGIC_START "Srx1v"
489 #define ENCODING_FORMAT_MINOR_VERSION 0
490
491 String Archive::_encodeRootBlob() {
492 String s;
493 s += _encodeBlob(ToString(ENCODING_FORMAT_MINOR_VERSION));
494 s += _encode(m_root);
495 s += _encode(m_allObjects);
496 s += _encodeBlob(m_name);
497 s += _encodeBlob(m_comment);
498 s += _encode(m_timeCreated);
499 s += _encode(m_timeModified);
500 return _encodeBlob(s);
501 }
502
503 void Archive::encode() {
504 m_rawData.clear();
505 String s = MAGIC_START;
506 m_timeModified = time(NULL);
507 if (m_timeCreated == LIBGIG_EPOCH_TIME)
508 m_timeCreated = m_timeModified;
509 s += _encodeRootBlob();
510 m_rawData.resize(s.length() + 1);
511 memcpy(&m_rawData[0], &s[0], s.length() + 1);
512 m_isModified = false;
513 }
514
515 struct _Blob {
516 const char* p;
517 const char* end;
518 };
519
520 static _Blob _decodeBlob(const char* p, const char* end, bool bThrow = true) {
521 if (!bThrow && p >= end) {
522 const _Blob blob = { p, end };
523 return blob;
524 }
525 size_t sz = 0;
526 for (; true; ++p) {
527 if (p >= end)
528 throw Exception("Decode Error: Missing blob");
529 const char& c = *p;
530 if (c == ':') break;
531 if (c < '0' || c > '9')
532 throw Exception("Decode Error: Missing blob size");
533 sz *= 10;
534 sz += size_t(c - '0');
535 }
536 ++p;
537 if (p + sz > end)
538 throw Exception("Decode Error: Premature end of blob");
539 const _Blob blob = { p, p + sz };
540 return blob;
541 }
542
543 template<typename T_int>
544 static T_int _popIntBlob(const char*& p, const char* end) {
545 _Blob blob = _decodeBlob(p, end);
546 p = blob.p;
547 end = blob.end;
548
549 T_int sign = 1;
550 T_int i = 0;
551 if (p >= end)
552 throw Exception("Decode Error: premature end of int blob");
553 if (*p == '-') {
554 sign = -1;
555 ++p;
556 }
557 for (; p < end; ++p) {
558 const char& c = *p;
559 if (c < '0' || c > '9')
560 throw Exception("Decode Error: Invalid int blob format");
561 i *= 10;
562 i += size_t(c - '0');
563 }
564 return i * sign;
565 }
566
567 template<typename T_int>
568 static void _popIntBlob(const char*& p, const char* end, RawData& rawData) {
569 const T_int i = _popIntBlob<T_int>(p, end);
570 *(T_int*)&rawData[0] = i;
571 }
572
573 template<typename T_real>
574 static T_real _popRealBlob(const char*& p, const char* end) {
575 _Blob blob = _decodeBlob(p, end);
576 p = blob.p;
577 end = blob.end;
578
579 if (p >= end || (end - p) < 1)
580 throw Exception("Decode Error: premature end of real blob");
581
582 String s(p, size_t(end - p));
583
584 T_real r;
585 if (sizeof(T_real) <= sizeof(double))
586 r = atof(s.c_str());
587 else
588 assert(false /* unknown real type */);
589
590 p += s.length();
591
592 return r;
593 }
594
595 template<typename T_real>
596 static void _popRealBlob(const char*& p, const char* end, RawData& rawData) {
597 const T_real r = _popRealBlob<T_real>(p, end);
598 *(T_real*)&rawData[0] = r;
599 }
600
601 static String _popStringBlob(const char*& p, const char* end) {
602 _Blob blob = _decodeBlob(p, end);
603 p = blob.p;
604 end = blob.end;
605 if (end - p < 0)
606 throw Exception("Decode Error: missing String blob");
607 String s;
608 const size_t sz = end - p;
609 s.resize(sz);
610 memcpy(&s[0], p, sz);
611 p += sz;
612 return s;
613 }
614
615 static time_t _popTimeBlob(const char*& p, const char* end) {
616 const uint64_t i = _popIntBlob<uint64_t>(p, end);
617 return (time_t) i;
618 }
619
620 DataType _popDataTypeBlob(const char*& p, const char* end) {
621 _Blob blob = _decodeBlob(p, end);
622 p = blob.p;
623 end = blob.end;
624
625 DataType type;
626 type.m_baseTypeName = _popStringBlob(p, end);
627 type.m_customTypeName = _popStringBlob(p, end);
628 type.m_size = _popIntBlob<int>(p, end);
629 type.m_isPointer = _popIntBlob<bool>(p, end);
630 return type;
631 }
632
633 static UID _popUIDBlob(const char*& p, const char* end) {
634 _Blob blob = _decodeBlob(p, end);
635 p = blob.p;
636 end = blob.end;
637
638 if (p >= end)
639 throw Exception("Decode Error: premature end of UID blob");
640
641 const ID id = (ID) _popIntBlob<size_t>(p, end);
642 const size_t size = _popIntBlob<size_t>(p, end);
643
644 const UID uid = { id, size };
645 return uid;
646 }
647
648 static UIDChain _popUIDChainBlob(const char*& p, const char* end) {
649 _Blob blob = _decodeBlob(p, end);
650 p = blob.p;
651 end = blob.end;
652
653 UIDChain chain;
654 while (p < end) {
655 const UID uid = _popUIDBlob(p, end);
656 chain.push_back(uid);
657 }
658 assert(!chain.empty());
659 return chain;
660 }
661
662 static Member _popMemberBlob(const char*& p, const char* end) {
663 _Blob blob = _decodeBlob(p, end, false);
664 p = blob.p;
665 end = blob.end;
666
667 Member m;
668 if (p >= end) return m;
669
670 m.m_uid = _popUIDBlob(p, end);
671 m.m_offset = _popIntBlob<size_t>(p, end);
672 m.m_name = _popStringBlob(p, end);
673 m.m_type = _popDataTypeBlob(p, end);
674 assert(m.type());
675 assert(!m.name().empty());
676 assert(m.uid().isValid());
677 return m;
678 }
679
680 static std::vector<Member> _popMembersBlob(const char*& p, const char* end) {
681 _Blob blob = _decodeBlob(p, end, false);
682 p = blob.p;
683 end = blob.end;
684
685 std::vector<Member> members;
686 while (p < end) {
687 const Member member = _popMemberBlob(p, end);
688 if (member)
689 members.push_back(member);
690 else
691 break;
692 }
693 return members;
694 }
695
696 static void _popPrimitiveValue(const char*& p, const char* end, Object& obj) {
697 const DataType& type = obj.type();
698 if (type.isPrimitive() && !type.isPointer()) {
699 obj.m_data.resize(type.size());
700 if (type.isInteger() || type.isEnum()) {
701 if (type.isSigned()) {
702 if (type.size() == 1)
703 _popIntBlob<int8_t>(p, end, obj.m_data);
704 else if (type.size() == 2)
705 _popIntBlob<int16_t>(p, end, obj.m_data);
706 else if (type.size() == 4)
707 _popIntBlob<int32_t>(p, end, obj.m_data);
708 else if (type.size() == 8)
709 _popIntBlob<int64_t>(p, end, obj.m_data);
710 else
711 assert(false /* unknown signed int type size */);
712 } else {
713 if (type.size() == 1)
714 _popIntBlob<uint8_t>(p, end, obj.m_data);
715 else if (type.size() == 2)
716 _popIntBlob<uint16_t>(p, end, obj.m_data);
717 else if (type.size() == 4)
718 _popIntBlob<uint32_t>(p, end, obj.m_data);
719 else if (type.size() == 8)
720 _popIntBlob<uint64_t>(p, end, obj.m_data);
721 else
722 assert(false /* unknown unsigned int type size */);
723 }
724 } else if (type.isReal()) {
725 if (type.size() == sizeof(float))
726 _popRealBlob<float>(p, end, obj.m_data);
727 else if (type.size() == sizeof(double))
728 _popRealBlob<double>(p, end, obj.m_data);
729 else
730 assert(false /* unknown floating point type */);
731 } else if (type.isBool()) {
732 _popIntBlob<uint8_t>(p, end, obj.m_data);
733 } else {
734 assert(false /* unknown primitive type */);
735 }
736
737 } else {
738 // don't whine if the empty blob was not added on encoder side
739 _Blob blob = _decodeBlob(p, end, false);
740 p = blob.p;
741 end = blob.end;
742 }
743 }
744
745 static Object _popObjectBlob(const char*& p, const char* end) {
746 _Blob blob = _decodeBlob(p, end, false);
747 p = blob.p;
748 end = blob.end;
749
750 Object obj;
751 if (p >= end) return obj;
752
753 obj.m_type = _popDataTypeBlob(p, end);
754 obj.m_version = _popIntBlob<Version>(p, end);
755 obj.m_minVersion = _popIntBlob<Version>(p, end);
756 obj.m_uid = _popUIDChainBlob(p, end);
757 obj.m_members = _popMembersBlob(p, end);
758 _popPrimitiveValue(p, end, obj);
759 assert(obj.type());
760 return obj;
761 }
762
763 void Archive::_popObjectsBlob(const char*& p, const char* end) {
764 _Blob blob = _decodeBlob(p, end, false);
765 p = blob.p;
766 end = blob.end;
767
768 if (p >= end)
769 throw Exception("Decode Error: Premature end of objects blob");
770
771 while (true) {
772 const Object obj = _popObjectBlob(p, end);
773 if (!obj) break;
774 m_allObjects[obj.uid()] = obj;
775 }
776 }
777
778 void Archive::_popRootBlob(const char*& p, const char* end) {
779 _Blob blob = _decodeBlob(p, end, false);
780 p = blob.p;
781 end = blob.end;
782
783 if (p >= end)
784 throw Exception("Decode Error: Premature end of root blob");
785
786 // just in case this encoding format will be extended in future
787 // (currently not used)
788 const int formatMinorVersion = _popIntBlob<int>(p, end);
789
790 m_root = _popUIDBlob(p, end);
791 if (!m_root)
792 throw Exception("Decode Error: No root object");
793
794 _popObjectsBlob(p, end);
795 if (!m_allObjects[m_root])
796 throw Exception("Decode Error: Missing declared root object");
797
798 m_name = _popStringBlob(p, end);
799 m_comment = _popStringBlob(p, end);
800 m_timeCreated = _popTimeBlob(p, end);
801 m_timeModified = _popTimeBlob(p, end);
802 }
803
804 void Archive::decode(const RawData& data) {
805 m_rawData = data;
806 m_allObjects.clear();
807 m_isModified = false;
808 m_timeCreated = m_timeModified = LIBGIG_EPOCH_TIME;
809 const char* p = (const char*) &data[0];
810 const char* end = p + data.size();
811 if (memcmp(p, MAGIC_START, std::min(strlen(MAGIC_START), data.size())))
812 throw Exception("Decode Error: Magic start missing!");
813 p += strlen(MAGIC_START);
814 _popRootBlob(p, end);
815 }
816
817 void Archive::decode(const uint8_t* data, size_t size) {
818 RawData rawData;
819 rawData.resize(size);
820 memcpy(&rawData[0], data, size);
821 decode(rawData);
822 }
823
824 const RawData& Archive::rawData() {
825 if (m_isModified) encode();
826 return m_rawData;
827 }
828
829 String Archive::rawDataFormat() const {
830 return MAGIC_START;
831 }
832
833 bool Archive::isModified() const {
834 return m_isModified;
835 }
836
837 void Archive::clear() {
838 m_allObjects.clear();
839 m_operation = OPERATION_NONE;
840 m_root = NO_UID;
841 m_rawData.clear();
842 m_isModified = false;
843 m_timeCreated = m_timeModified = LIBGIG_EPOCH_TIME;
844 }
845
846 String Archive::name() const {
847 return m_name;
848 }
849
850 void Archive::setName(String name) {
851 if (m_name == name) return;
852 m_name = name;
853 m_isModified = true;
854 }
855
856 String Archive::comment() const {
857 return m_comment;
858 }
859
860 void Archive::setComment(String comment) {
861 if (m_comment == comment) return;
862 m_comment = comment;
863 m_isModified = true;
864 }
865
866 static tm _convertTimeStamp(const time_t& time, time_base_t base) {
867 tm* pTm;
868 switch (base) {
869 case LOCAL_TIME:
870 pTm = localtime(&time);
871 break;
872 case UTC_TIME:
873 pTm = gmtime(&time);
874 break;
875 default:
876 throw Exception("Time stamp with unknown time base (" + ToString((int64_t)base) + ") requested");
877 }
878 if (!pTm)
879 throw Exception("Failed assembling time stamp structure");
880 return *pTm;
881 }
882
883 time_t Archive::timeStampCreated() const {
884 return m_timeCreated;
885 }
886
887 time_t Archive::timeStampModified() const {
888 return m_timeModified;
889 }
890
891 tm Archive::dateTimeCreated(time_base_t base) const {
892 return _convertTimeStamp(m_timeCreated, base);
893 }
894
895 tm Archive::dateTimeModified(time_base_t base) const {
896 return _convertTimeStamp(m_timeModified, base);
897 }
898
899 void Archive::removeMember(Object& parent, const Member& member) {
900 parent.remove(member);
901 m_isModified = true;
902 }
903
904 void Archive::remove(const Object& obj) {
905 //FIXME: Should traverse from root object and remove all members associated with this object
906 if (!obj.uid()) return;
907 m_allObjects.erase(obj.uid());
908 m_isModified = true;
909 }
910
911 Object& Archive::objectByUID(const UID& uid) {
912 return m_allObjects[uid];
913 }
914
915 void Archive::setEnumValue(Object& object, uint64_t value) {
916 if (!object) return;
917 if (!object.type().isEnum())
918 throw Exception("Not an enum data type");
919 Object* pObject = &object;
920 if (object.type().isPointer()) {
921 Object& obj = objectByUID(object.uid(1));
922 if (!obj) return;
923 pObject = &obj;
924 }
925 const int nativeEnumSize = sizeof(enum operation_t);
926 DataType& type = const_cast<DataType&>( pObject->type() );
927 // original serializer ("sender") might have had a different word size
928 // than this machine, adjust type object in this case
929 if (type.size() != nativeEnumSize) {
930 type.m_size = nativeEnumSize;
931 }
932 pObject->m_data.resize(type.size());
933 void* ptr = &pObject->m_data[0];
934 if (type.size() == 1)
935 *(uint8_t*)ptr = (uint8_t)value;
936 else if (type.size() == 2)
937 *(uint16_t*)ptr = (uint16_t)value;
938 else if (type.size() == 4)
939 *(uint32_t*)ptr = (uint32_t)value;
940 else if (type.size() == 8)
941 *(uint64_t*)ptr = (uint64_t)value;
942 else
943 assert(false /* unknown enum type size */);
944 m_isModified = true;
945 }
946
947 void Archive::setIntValue(Object& object, int64_t value) {
948 if (!object) return;
949 if (!object.type().isInteger())
950 throw Exception("Not an integer data type");
951 Object* pObject = &object;
952 if (object.type().isPointer()) {
953 Object& obj = objectByUID(object.uid(1));
954 if (!obj) return;
955 pObject = &obj;
956 }
957 const DataType& type = pObject->type();
958 pObject->m_data.resize(type.size());
959 void* ptr = &pObject->m_data[0];
960 if (type.isSigned()) {
961 if (type.size() == 1)
962 *(int8_t*)ptr = (int8_t)value;
963 else if (type.size() == 2)
964 *(int16_t*)ptr = (int16_t)value;
965 else if (type.size() == 4)
966 *(int32_t*)ptr = (int32_t)value;
967 else if (type.size() == 8)
968 *(int64_t*)ptr = (int64_t)value;
969 else
970 assert(false /* unknown signed int type size */);
971 } else {
972 if (type.size() == 1)
973 *(uint8_t*)ptr = (uint8_t)value;
974 else if (type.size() == 2)
975 *(uint16_t*)ptr = (uint16_t)value;
976 else if (type.size() == 4)
977 *(uint32_t*)ptr = (uint32_t)value;
978 else if (type.size() == 8)
979 *(uint64_t*)ptr = (uint64_t)value;
980 else
981 assert(false /* unknown unsigned int type size */);
982 }
983 m_isModified = true;
984 }
985
986 void Archive::setRealValue(Object& object, double value) {
987 if (!object) return;
988 if (!object.type().isReal())
989 throw Exception("Not a real data type");
990 Object* pObject = &object;
991 if (object.type().isPointer()) {
992 Object& obj = objectByUID(object.uid(1));
993 if (!obj) return;
994 pObject = &obj;
995 }
996 const DataType& type = pObject->type();
997 pObject->m_data.resize(type.size());
998 void* ptr = &pObject->m_data[0];
999 if (type.size() == sizeof(float))
1000 *(float*)ptr = (float)value;
1001 else if (type.size() == sizeof(double))
1002 *(double*)ptr = (double)value;
1003 else
1004 assert(false /* unknown real type size */);
1005 m_isModified = true;
1006 }
1007
1008 void Archive::setBoolValue(Object& object, bool value) {
1009 if (!object) return;
1010 if (!object.type().isBool())
1011 throw Exception("Not a bool data type");
1012 Object* pObject = &object;
1013 if (object.type().isPointer()) {
1014 Object& obj = objectByUID(object.uid(1));
1015 if (!obj) return;
1016 pObject = &obj;
1017 }
1018 const DataType& type = pObject->type();
1019 pObject->m_data.resize(type.size());
1020 bool* ptr = (bool*)&pObject->m_data[0];
1021 *ptr = value;
1022 m_isModified = true;
1023 }
1024
1025 void Archive::setAutoValue(Object& object, String value) {
1026 if (!object) return;
1027 const DataType& type = object.type();
1028 if (type.isInteger())
1029 setIntValue(object, atoll(value.c_str()));
1030 else if (type.isReal())
1031 setRealValue(object, atof(value.c_str()));
1032 else if (type.isBool())
1033 setBoolValue(object, atof(value.c_str()));
1034 else if (type.isEnum())
1035 setEnumValue(object, atoll(value.c_str()));
1036 else
1037 throw Exception("Not a primitive data type");
1038 }
1039
1040 String Archive::valueAsString(const Object& object) {
1041 if (!object)
1042 throw Exception("Invalid object");
1043 if (object.type().isClass())
1044 throw Exception("Object is class type");
1045 const Object* pObject = &object;
1046 if (object.type().isPointer()) {
1047 const Object& obj = objectByUID(object.uid(1));
1048 if (!obj) return "";
1049 pObject = &obj;
1050 }
1051 return _primitiveObjectValueToString(*pObject);
1052 }
1053
1054 int64_t Archive::valueAsInt(const Object& object) {
1055 if (!object)
1056 throw Exception("Invalid object");
1057 if (!object.type().isInteger() && !object.type().isEnum())
1058 throw Exception("Object is neither an integer nor an enum");
1059 const Object* pObject = &object;
1060 if (object.type().isPointer()) {
1061 const Object& obj = objectByUID(object.uid(1));
1062 if (!obj) return 0;
1063 pObject = &obj;
1064 }
1065 return _primitiveObjectValueToNumber<int64_t>(*pObject);
1066 }
1067
1068 double Archive::valueAsReal(const Object& object) {
1069 if (!object)
1070 throw Exception("Invalid object");
1071 if (!object.type().isReal())
1072 throw Exception("Object is not an real type");
1073 const Object* pObject = &object;
1074 if (object.type().isPointer()) {
1075 const Object& obj = objectByUID(object.uid(1));
1076 if (!obj) return 0;
1077 pObject = &obj;
1078 }
1079 return _primitiveObjectValueToNumber<double>(*pObject);
1080 }
1081
1082 bool Archive::valueAsBool(const Object& object) {
1083 if (!object)
1084 throw Exception("Invalid object");
1085 if (!object.type().isBool())
1086 throw Exception("Object is not a bool");
1087 const Object* pObject = &object;
1088 if (object.type().isPointer()) {
1089 const Object& obj = objectByUID(object.uid(1));
1090 if (!obj) return 0;
1091 pObject = &obj;
1092 }
1093 return _primitiveObjectValueToNumber<bool>(*pObject);
1094 }
1095
1096 // *************** Archive::Syncer ***************
1097 // *
1098
1099 Archive::Syncer::Syncer(Archive& dst, Archive& src)
1100 : m_dst(dst), m_src(src)
1101 {
1102 const Object srcRootObj = src.rootObject();
1103 const Object dstRootObj = dst.rootObject();
1104 if (!srcRootObj)
1105 throw Exception("No source root object!");
1106 if (!dstRootObj)
1107 throw Exception("Expected destination root object not found!");
1108 syncObject(dstRootObj, srcRootObj);
1109 }
1110
1111 void Archive::Syncer::syncPrimitive(const Object& dstObj, const Object& srcObj) {
1112 assert(srcObj.rawData().size() == dstObj.type().size());
1113 void* pDst = (void*)dstObj.uid().id;
1114 memcpy(pDst, &srcObj.rawData()[0], dstObj.type().size());
1115 }
1116
1117 void Archive::Syncer::syncPointer(const Object& dstObj, const Object& srcObj) {
1118 assert(dstObj.type().isPointer());
1119 assert(dstObj.type() == srcObj.type());
1120 const Object& pointedDstObject = m_dst.m_allObjects[dstObj.uid(1)];
1121 const Object& pointedSrcObject = m_src.m_allObjects[srcObj.uid(1)];
1122 syncObject(pointedDstObject, pointedSrcObject);
1123 }
1124
1125 void Archive::Syncer::syncObject(const Object& dstObj, const Object& srcObj) {
1126 if (!dstObj || !srcObj) return; // end of recursion
1127 if (!dstObj.isVersionCompatibleTo(srcObj))
1128 throw Exception("Version incompatible (destination version " +
1129 ToString(dstObj.version()) + " [min. version " +
1130 ToString(dstObj.minVersion()) + "], source version " +
1131 ToString(srcObj.version()) + " [min. version " +
1132 ToString(srcObj.minVersion()) + "])");
1133 if (dstObj.type() != srcObj.type())
1134 throw Exception("Incompatible data structure type (destination type " +
1135 dstObj.type().asLongDescr() + " vs. source type " +
1136 srcObj.type().asLongDescr() + ")");
1137
1138 // prevent syncing this object again, and thus also prevent endless
1139 // loop on data structures with cyclic relations
1140 m_dst.m_allObjects.erase(dstObj.uid());
1141
1142 if (dstObj.type().isPrimitive() && !dstObj.type().isPointer()) {
1143 syncPrimitive(dstObj, srcObj);
1144 return; // end of recursion
1145 }
1146
1147 if (dstObj.type().isPointer()) {
1148 syncPointer(dstObj, srcObj);
1149 return;
1150 }
1151
1152 assert(dstObj.type().isClass());
1153 for (int iMember = 0; iMember < srcObj.members().size(); ++iMember) {
1154 const Member& srcMember = srcObj.members()[iMember];
1155 Member dstMember = dstMemberMatching(dstObj, srcObj, srcMember);
1156 if (!dstMember)
1157 throw Exception("Expected member missing in destination object");
1158 syncMember(dstMember, srcMember);
1159 }
1160 }
1161
1162 Member Archive::Syncer::dstMemberMatching(const Object& dstObj, const Object& srcObj, const Member& srcMember) {
1163 Member dstMember = dstObj.memberNamed(srcMember.name());
1164 if (dstMember)
1165 return (dstMember.type() == srcMember.type()) ? dstMember : Member();
1166 std::vector<Member> members = dstObj.membersOfType(srcMember.type());
1167 if (members.size() <= 0)
1168 return Member();
1169 if (members.size() == 1)
1170 return members[0];
1171 for (int i = 0; i < members.size(); ++i)
1172 if (members[i].offset() == srcMember.offset())
1173 return members[i];
1174 const int srcSeqNr = srcObj.sequenceIndexOf(srcMember);
1175 assert(srcSeqNr >= 0); // should never happen, otherwise there is a bug
1176 for (int i = 0; i < members.size(); ++i) {
1177 const int dstSeqNr = dstObj.sequenceIndexOf(members[i]);
1178 if (dstSeqNr == srcSeqNr)
1179 return members[i];
1180 }
1181 return Member(); // give up!
1182 }
1183
1184 void Archive::Syncer::syncMember(const Member& dstMember, const Member& srcMember) {
1185 assert(dstMember && srcMember);
1186 assert(dstMember.type() == srcMember.type());
1187 const Object dstObj = m_dst.m_allObjects[dstMember.uid()];
1188 const Object srcObj = m_src.m_allObjects[srcMember.uid()];
1189 syncObject(dstObj, srcObj);
1190 }
1191
1192 // *************** Exception ***************
1193 // *
1194
1195 void Exception::PrintMessage() {
1196 std::cout << "Serialization::Exception: " << Message << std::endl;
1197 }
1198
1199 } // namespace Serialization

  ViewVC Help
Powered by ViewVC