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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3169 - (show annotations) (download)
Wed May 10 21:17:10 2017 UTC (6 years, 11 months ago) by schoenebeck
File size: 40353 byte(s)
* src/gig.h: Added enum reflection API functions for
  retrieving enum declaration type information at
  runtime (countEnum(), enumKey(), enumKeys(),
  enumValue()).
* Archive: Added methods valueAsInt(), valueAsReal()
  and valueAsBool().
* Bumped version (4.0.0.svn20).

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

  ViewVC Help
Powered by ViewVC