ACF $AcfVersion:0$
CPrimitiveTypesSerializer.h
Go to the documentation of this file.
1// SPDX-License-Identifier: LGPL-2.1-or-later OR GPL-2.0-or-later OR GPL-3.0-or-later OR LicenseRef-ACF-Commercial
2#pragma once
3
4
5// STL includes
6#include <typeinfo>
7#include <memory>
8
9// Qt includes
10#include <QtCore/QDateTime>
11#include <QtCore/QPointF>
12#include <QtCore/QMetaObject>
13#include <QtCore/QMetaEnum>
14
15// ACF includes
16#include <istd/TRange.h>
17#include <istd/TIFactory.h>
18#include <istd/TRanges.h>
19#include <istd/TIndex.h>
20#include <iser/IArchive.h>
21#include <iser/CArchiveTag.h>
22
23
24namespace iser
25{
26
27
32{
33public:
37 static bool SerializeRange(iser::IArchive& archive, istd::CRange& range);
38
42 static bool SerializeIntRange(iser::IArchive& archive, istd::CIntRange& range);
43
47 static bool SerializeRanges(iser::IArchive& archive, istd::CRanges& ranges);
48
52 static bool SerializeIntRanges(iser::IArchive& archive, istd::CIntRanges& ranges);
53
57 static bool SerializeDateTime(iser::IArchive& archive, QDateTime& dateTime);
58
62 static bool SerializeDate(iser::IArchive& archive, QDate& date);
63
67 template <typename ValueType>
68 static bool SerializeRange(iser::IArchive& archive, istd::TRange<ValueType>& range);
69
73 template <int Dimensions>
74 static bool SerializeIndex(iser::IArchive& archive, istd::TIndex<Dimensions>& index);
75
79 static bool SerializeQPointF(iser::IArchive& archive, QPointF& point);
80
84 static bool SerializeQVariant(iser::IArchive& archive, QVariant& variant);
85
90 iser::IArchive& archive,
91 QStringList& stringList,
92 const QByteArray& containerTagName = "Elements",
93 const QByteArray& elementTagName = "Element");
94
95 template <typename ContainterType>
96 static bool SerializeContainer(
97 iser::IArchive& archive,
98 ContainterType& container,
99 const QByteArray& containerTagName = "Elements",
100 const QByteArray& elementTagName = "Element");
101
102 template <typename ContainterType>
104 iser::IArchive& archive,
105 ContainterType& container,
106 const QByteArray& containerTagName = "Elements",
107 const QByteArray& elementTagName = "Element");
108
115 template <typename EnumType, QByteArray (*ToString)(EnumType), bool (*FromString)(const QByteArray&, EnumType&)>
116 static bool SerializeEnum(
117 iser::IArchive& archive,
118 EnumType& enumValue);
119
123 template <typename EnumType>
124 static bool SerializeQEnum(
125 iser::IArchive& archive,
126 EnumType& enumValue);
127
131 template <typename ContainerType, typename KeyType>
133 iser::IArchive& archive,
134 ContainerType& container,
135 bool (*SerializeKeyFunction)(iser::IArchive&, KeyType& key),
136 const QByteArray& containerTagName,
137 const QByteArray& elementTagName = "Element",
138 const QByteArray& keyTagId = "Key",
139 const QByteArray& valueTagId = "Value",
140 const QByteArray& containerComment = "List of elements");
141
142 template <typename ContainerType, typename KeyType>
144 iser::IArchive& archive,
145 ContainerType& container,
146 bool (*SerializeKeyFunction)(iser::IArchive&, KeyType& key),
147 const QByteArray& containerTagName,
148 const QByteArray& elementTagName = "Element",
149 const QByteArray& keyTagId = "Key",
150 const QByteArray& valueTagId = "Value",
151 const QByteArray& containerComment = "List of elements");
152
153 template <typename ObjectType>
155 iser::IArchive& archive,
156 std::unique_ptr<ObjectType>& objectPtrRef,
157 const QByteArray& tagName);
158
159 template <typename ObjectInterface>
161 iser::IArchive& archive,
162 std::unique_ptr<ObjectInterface>& objectPtrRef,
163 istd::TIFactory<ObjectInterface>& objectFactoryPtr,
164 const QByteArray& tagName);
165};
166
167// public template methods
168
169template <typename ValueType>
171{
172 static iser::CArchiveTag minValueTag("MinValue", "Minimal range value", iser::CArchiveTag::TT_LEAF);
173 static iser::CArchiveTag maxValueTag("MaxValue", "Maximal range value", iser::CArchiveTag::TT_LEAF);
174
175 bool retVal = true;
176
177 retVal = retVal && archive.BeginTag(minValueTag);
178 retVal = retVal && archive.Process(range.GetMinValueRef());
179 retVal = retVal && archive.EndTag(minValueTag);
180
181 retVal = retVal && archive.BeginTag(maxValueTag);
182 retVal = retVal && archive.Process(range.GetMaxValueRef());
183 retVal = retVal && archive.EndTag(maxValueTag);
184
185 return retVal;
186}
187
188template <int Dimensions>
190{
191 bool retVal = true;
192
193 for (int i = 0; i < Dimensions; ++i){
194 retVal = retVal && archive.Process(index[i]);
195 }
196
197 return retVal;
198}
199
200
201template <typename ContainerType>
203 iser::IArchive& archive,
204 ContainerType& container,
205 const QByteArray& containerTagName,
206 const QByteArray& elementTagName)
207{
208 iser::CArchiveTag elementsTag(containerTagName, "List of elements", iser::CArchiveTag::TT_MULTIPLE);
209 iser::CArchiveTag elementTag(elementTagName, "Single element", iser::CArchiveTag::TT_LEAF, &elementsTag);
210
211 bool retVal = true;
212
213 bool isStoring = archive.IsStoring();
214 int elementsCount = container.count();
215
216 retVal = retVal && archive.BeginMultiTag(elementsTag, elementTag, elementsCount);
217 if (!retVal){
218 return false;
219 }
220
221 if (isStoring){
222 for (int i = 0; i < elementsCount; ++i){
223 typename ContainerType::value_type element = container[i];
224
225 retVal = retVal && archive.BeginTag(elementTag);
226 retVal = retVal && archive.Process(element);
227 retVal = retVal && archive.EndTag(elementTag);
228 }
229 }
230 else{
231 container.clear();
232
233 for (int i = 0; i < elementsCount; ++i){
234 typename ContainerType::value_type element = typename ContainerType::value_type();
235
236 retVal = retVal && archive.BeginTag(elementTag);
237 retVal = retVal && archive.Process(element);
238 retVal = retVal && archive.EndTag(elementTag);
239
240 if (retVal){
241 container.push_back(element);
242 }
243 }
244 }
245
246 retVal = retVal && archive.EndTag(elementsTag);
247
248 return retVal;
249}
250
251
252template <typename ContainerType>
254 iser::IArchive& archive,
255 ContainerType& container,
256 const QByteArray& containerTagName,
257 const QByteArray& elementTagName)
258{
259 iser::CArchiveTag elementsTag(containerTagName, "List of elements", iser::CArchiveTag::TT_MULTIPLE);
260 iser::CArchiveTag elementTag(elementTagName, "Single element", iser::CArchiveTag::TT_GROUP, &elementsTag);
261
262 bool retVal = true;
263
264 bool isStoring = archive.IsStoring();
265 int elementsCount = container.count();
266
267 retVal = retVal && archive.BeginMultiTag(elementsTag, elementTag, elementsCount);
268 if (!retVal){
269 return false;
270 }
271
272 if (isStoring){
273 for (int i = 0; i < elementsCount; ++i){
274 typename ContainerType::value_type element = container[i];
275
276 retVal = retVal && archive.BeginTag(elementTag);
277 retVal = retVal && element.Serialize(archive);
278 retVal = retVal && archive.EndTag(elementTag);
279 }
280 }
281 else{
282 container.clear();
283
284 for (int i = 0; i < elementsCount; ++i){
285 typename ContainerType::value_type element = typename ContainerType::value_type();
286
287 retVal = retVal && archive.BeginTag(elementTag);
288 retVal = retVal && element.Serialize(archive);
289 retVal = retVal && archive.EndTag(elementTag);
290
291 if (retVal){
292 container.push_back(element);
293 }
294 }
295 }
296
297 retVal = retVal && archive.EndTag(elementsTag);
298
299 return retVal;
300}
301
302
303template <typename EnumType, QByteArray (*ToString)(EnumType), bool (*FromString)(const QByteArray&, EnumType&)>
305 iser::IArchive& archive,
306 EnumType& enumValue)
307{
308 QByteArray enumValueAsText;
309
310 bool retVal = true;
311
312 // Try to get enumeration text generated by I_DECLARE_ENUM macro:
313 if (enumValueAsText.isEmpty() && (ToString != NULL)){
314 enumValueAsText = ToString(enumValue);
315 }
316
317 // Enum value is defined in textual form:
318 if (!enumValueAsText.isEmpty()){
319 retVal = retVal && archive.Process(enumValueAsText);
320
321 if (retVal && !archive.IsStoring()){
322 if (FromString != NULL){
323 retVal = FromString(enumValueAsText, enumValue);
324 }
325 else{
326 retVal = false;
327 }
328 }
329 }
330 else{
331 int value = enumValue;
332
333 retVal = retVal && archive.Process(value);
334
335 if (!archive.IsStoring()){
336 // TODO: check if the readed value is in range of the enum values!
337 enumValue = EnumType(value);
338 }
339 }
340
341 return retVal;
342}
343
344
345template <typename EnumType>
347 iser::IArchive& archive,
348 EnumType& enumValue)
349{
350 QByteArray enumValueAsText;
351 const auto metaEnum = QMetaEnum::fromType<EnumType>();
352 if (!metaEnum.isValid()){
353 return false;
354 }
355 if (archive.IsStoring()){
356 enumValueAsText = metaEnum.valueToKey((int)enumValue);
357 if (enumValueAsText.isEmpty()){
358 return false;
359 }
360 }
361
362 bool retVal = true;
363 retVal = retVal && archive.Process(enumValueAsText);
364 if (retVal && !archive.IsStoring()){
365 enumValue = EnumType(metaEnum.keyToValue(enumValueAsText.constData(), &retVal));
366 }
367 return retVal;
368}
369
370
371template<typename ContainerType, typename KeyType>
373 IArchive& archive,
374 ContainerType& container,
375 bool (*SerializeKeyFunction)(iser::IArchive&, KeyType& key),
376 const QByteArray& containerTagName,
377 const QByteArray& elementTagName,
378 const QByteArray& keyTagId,
379 const QByteArray& valueTagId,
380 const QByteArray& containerComment)
381{
382 bool retVal = true;
383
384 iser::CArchiveTag parametersTag(containerTagName, containerComment, iser::CArchiveTag::TT_MULTIPLE);
385 iser::CArchiveTag parameterTag(elementTagName, "Single element", iser::CArchiveTag::TT_GROUP, &parametersTag, true);
386 iser::CArchiveTag parameterKeyTag(keyTagId, "Key of parameter", iser::CArchiveTag::TT_LEAF, &parameterTag);
387 iser::CArchiveTag parameterValueTag(valueTagId, "Value of parameter", iser::CArchiveTag::TT_LEAF, &parameterTag, true);
388
389 if (archive.IsStoring()){
390 int paramsCount = container.count();
391
392 retVal = retVal && archive.BeginMultiTag(parametersTag, parameterTag, paramsCount);
393
394 for (typename ContainerType::iterator iterator = container.begin(); iterator != container.end(); ++iterator){
395 retVal = retVal && archive.BeginTag(parameterTag);
396
397 typename ContainerType::key_type key = iterator.key();
398 retVal = retVal && archive.BeginTag(parameterKeyTag);
399 retVal = retVal && SerializeKeyFunction(archive, key);
400 retVal = retVal && archive.EndTag(parameterKeyTag);
401
402 typename ContainerType::mapped_type value = iterator.value();
403 retVal = retVal && archive.BeginTag(parameterValueTag);
404 retVal = retVal && archive.Process(value);
405 retVal = retVal && archive.EndTag(parameterValueTag);
406
407 retVal = retVal && archive.EndTag(parameterTag);
408 }
409
410 retVal = retVal && archive.EndTag(parametersTag);
411 }
412 else{
413 int paramsCount = 0;
414 container.clear();
415
416 retVal = retVal && archive.BeginMultiTag(parametersTag, parameterTag, paramsCount);
417
418 if (!retVal){
419 return false;
420 }
421
422 for (int i = 0; i < paramsCount; ++i){
423 retVal = retVal && archive.BeginTag(parameterTag);
424
425 typename ContainerType::key_type key = typename ContainerType::key_type();
426 retVal = retVal && archive.BeginTag(parameterKeyTag);
427 retVal = retVal && SerializeKeyFunction(archive, key);
428 retVal = retVal && archive.EndTag(parameterKeyTag);
429 if (!retVal){
430 return false;
431 }
432
433 typename ContainerType::mapped_type value;
434 retVal = retVal && archive.BeginTag(parameterValueTag);
435 retVal = retVal && archive.Process(value);
436 retVal = retVal && archive.EndTag(parameterValueTag);
437
438 retVal = retVal && archive.EndTag(parameterTag);
439
440 container.insert(key, value);
441 }
442
443 retVal = retVal && archive.EndTag(parametersTag);
444 }
445
446 return retVal;
447}
448
449
450template<typename ContainerType, typename KeyType>
452 IArchive& archive,
453 ContainerType& container,
454 bool (*SerializeKeyFunction)(iser::IArchive&, KeyType& key),
455 const QByteArray& containerTagName,
456 const QByteArray& elementTagName,
457 const QByteArray& keyTagId,
458 const QByteArray& valueTagId,
459 const QByteArray& containerComment)
460{
461 bool retVal = true;
462
463 iser::CArchiveTag parametersTag(containerTagName, containerComment, iser::CArchiveTag::TT_MULTIPLE);
464 iser::CArchiveTag parameterTag(elementTagName, "Single element", iser::CArchiveTag::TT_GROUP, &parametersTag, true);
465 iser::CArchiveTag parameterKeyTag(keyTagId, "Key of parameter", iser::CArchiveTag::TT_LEAF, &parameterTag);
466 iser::CArchiveTag parameterValueTag(valueTagId, "Value of parameter", iser::CArchiveTag::TT_GROUP, &parameterTag, true);
467
468 if (archive.IsStoring()){
469 int paramsCount = container.count();
470
471 retVal = retVal && archive.BeginMultiTag(parametersTag, parameterTag, paramsCount);
472
473 for (typename ContainerType::iterator iterator = container.begin(); iterator != container.end(); ++iterator){
474 retVal = retVal && archive.BeginTag(parameterTag);
475
476 typename ContainerType::key_type key = iterator.key();
477 retVal = retVal && archive.BeginTag(parameterKeyTag);
478 retVal = retVal && SerializeKeyFunction(archive, key);
479 retVal = retVal && archive.EndTag(parameterKeyTag);
480
481 typename ContainerType::mapped_type value = iterator.value();
482 retVal = retVal && archive.BeginTag(parameterValueTag);
483 retVal = retVal && value.Serialize(archive);
484 retVal = retVal && archive.EndTag(parameterValueTag);
485
486 retVal = retVal && archive.EndTag(parameterTag);
487 }
488
489 retVal = retVal && archive.EndTag(parametersTag);
490 }
491 else{
492 int paramsCount = 0;
493 container.clear();
494
495 retVal = retVal && archive.BeginMultiTag(parametersTag, parameterTag, paramsCount);
496
497 if (!retVal){
498 return false;
499 }
500
501 for (int i = 0; i < paramsCount; ++i){
502 retVal = retVal && archive.BeginTag(parameterTag);
503
504 typename ContainerType::key_type key = typename ContainerType::key_type();
505 retVal = retVal && archive.BeginTag(parameterKeyTag);
506 retVal = retVal && SerializeKeyFunction(archive, key);
507 retVal = retVal && archive.EndTag(parameterKeyTag);
508 if (!retVal){
509 return false;
510 }
511
512 typename ContainerType::mapped_type value;
513 retVal = retVal && archive.BeginTag(parameterValueTag);
514 retVal = retVal && value.Serialize(archive);
515 retVal = retVal && archive.EndTag(parameterValueTag);
516
517 retVal = retVal && archive.EndTag(parameterTag);
518
519 container.insert(key, value);
520 }
521
522 retVal = retVal && archive.EndTag(parametersTag);
523 }
524
525 return retVal;
526}
527
528
529#define I_SERIALIZE_FLAG(Enum, archive, flag) iser::CPrimitiveTypesSerializer::SerializeEnum<int, Enum##ToString, Enum##FromString>(archive, flag);
530#define I_SERIALIZE_ENUM(Enum, archive, enumValue) iser::CPrimitiveTypesSerializer::SerializeEnum<Enum, ToString, FromString>(archive, enumValue);
531
532
533} // namespace iser
534
535
Process tag used to group data in archive stream.
Definition CArchiveTag.h:22
@ TT_GROUP
Normal tag used for grouping of tags or processed elements.
Definition CArchiveTag.h:37
@ TT_LEAF
Leaf tag, it can contain only one primitive element.
Definition CArchiveTag.h:48
@ TT_MULTIPLE
Multiple tag containing variable number of child tags.
Definition CArchiveTag.h:42
Implementation of serialize method for some common data types.
static bool SerializeContainer(iser::IArchive &archive, ContainterType &container, const QByteArray &containerTagName="Elements", const QByteArray &elementTagName="Element")
static bool SerializeIndex(iser::IArchive &archive, istd::TIndex< Dimensions > &index)
Serialize a generic index object.
static bool SerializeQStringList(iser::IArchive &archive, QStringList &stringList, const QByteArray &containerTagName="Elements", const QByteArray &elementTagName="Element")
Serialize a QStringList object.
static bool SerializeAssociativeContainer(iser::IArchive &archive, ContainerType &container, bool(*SerializeKeyFunction)(iser::IArchive &, KeyType &key), const QByteArray &containerTagName, const QByteArray &elementTagName="Element", const QByteArray &keyTagId="Key", const QByteArray &valueTagId="Value", const QByteArray &containerComment="List of elements")
This method can be used for serialization associatime containers i.e.: QHash, QMap std::map (since c+...
static bool SerializeQEnum(iser::IArchive &archive, EnumType &enumValue)
Method for serialization of the enumerated value using Qt's meta information system (Q_ENUM or Q_ENUM...
static bool SerializeOptionalObject(iser::IArchive &archive, std::unique_ptr< ObjectType > &objectPtrRef, const QByteArray &tagName)
static bool SerializeObjectContainer(iser::IArchive &archive, ContainterType &container, const QByteArray &containerTagName="Elements", const QByteArray &elementTagName="Element")
static bool SerializeDateTime(iser::IArchive &archive, QDateTime &dateTime)
Serialize QDateTime object.
static bool SerializeEnum(iser::IArchive &archive, EnumType &enumValue)
Method for serialization of the enumerated value using ACF's meta information extensions for the C++ ...
static bool SerializeRanges(iser::IArchive &archive, istd::CRanges &ranges)
Serialize list of range objects.
static bool SerializeIntRanges(iser::IArchive &archive, istd::CIntRanges &ranges)
Serialize list of integer-based ranges.
static bool SerializeQVariant(iser::IArchive &archive, QVariant &variant)
Serialize a QVariant object.
static bool SerializeQPointF(iser::IArchive &archive, QPointF &point)
Serialize a QPointF object.
static bool SerializeIntRange(iser::IArchive &archive, istd::CIntRange &range)
Serialize an integer-based range object.
static bool SerializeOptionalObject(iser::IArchive &archive, std::unique_ptr< ObjectInterface > &objectPtrRef, istd::TIFactory< ObjectInterface > &objectFactoryPtr, const QByteArray &tagName)
static bool SerializeAssociativeObjectContainer(iser::IArchive &archive, ContainerType &container, bool(*SerializeKeyFunction)(iser::IArchive &, KeyType &key), const QByteArray &containerTagName, const QByteArray &elementTagName="Element", const QByteArray &keyTagId="Key", const QByteArray &valueTagId="Value", const QByteArray &containerComment="List of elements")
static bool SerializeDate(iser::IArchive &archive, QDate &date)
Serialize QDate object.
static bool SerializeRange(iser::IArchive &archive, istd::CRange &range)
Serialize a range object.
Represents an input/output persistence archive for object serialization.
Definition IArchive.h:164
virtual bool Process(bool &value)=0
Processes (reads or writes) a boolean value.
virtual bool EndTag(const CArchiveTag &tag)=0
Ends a tagged section in the archive.
virtual bool BeginMultiTag(const CArchiveTag &tag, const CArchiveTag &subTag, int &count)=0
Begins a tagged section containing multiple elements of the same type.
virtual bool IsStoring() const =0
Checks if this archive is in storing (writing) or loading (reading) mode.
virtual bool BeginTag(const CArchiveTag &tag)=0
Begins a tagged section in the archive.
Generic interface for a factory.
Definition TIFactory.h:19
Multidimensional index used to addressing fixed-size array.
Definition TIndex.h:18
ValueType & GetMinValueRef()
Get reference to the bottom value.
Definition TRange.h:348
ValueType & GetMaxValueRef()
Get reference to the top value.
Definition TRange.h:389
#define NULL
Definition istd.h:74
Contains general persistence mechanism with basic archives implementations.
TRanges< double > CRanges
Definition TRanges.h:946
TRanges< int > CIntRanges
Definition TRanges.h:947