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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

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

  ViewVC Help
Powered by ViewVC