Devel Lib
SerializableData.h
1 #pragma once
2 
3 #include <vector>
4 #include <string>
5 #include <functional>
6 
7 #include "Core/Global.h"
8 #include "Core/Global.h"
9 #include "IO/WriteStream/WriteStream.h"
10 #include "IO/ReadStream/ReadStream.h"
11 
12 #include "Serializing/SerializingDefines.h"
13 
16 namespace Devel::Serializing {
19  struct SCompareData {
23  SCompareData(const void *i_pData, const size_t i_nSize)
24  : pData(i_pData), nSize(i_nSize) {}
25 
28  const void *pData;
29 
32  const size_t nSize;
33  };
34 
35 #pragma pack(push, 1)
36 
39  class IStruct {
40  };
41 
45  // Needed for output and input stream operator
46  class IField {
47  };
48 
52  template<typename T>
53  class IValue : public IField {
54  public:
58  template<typename ...TArgs, std::enable_if_t<std::is_constructible_v<T, TArgs...>> * = nullptr>
59  IValue(TArgs... i_tArgs)
60  : m_tValue(std::forward<TArgs>(i_tArgs)...) {}
61 
62  public:
65  const T &value() const {
66  return this->m_tValue;
67  }
68 
71  T &value() {
72  return this->m_tValue;
73  }
74 
75  protected:
79  };
80 
85  template<typename T = int, bool IsHidden = false>
86  class IData : public IValue<T> {
87  public:
88  using IValue<T>::IValue;
89 
91  virtual ~IData() = default;
92 
93  public:
97  bool doSerialize(IO::CWriteStream &i_oStream) const {
98  if (!IsHidden) {
99  return this->serialize(i_oStream);
100  }
101 
102  return true;
103  }
104 
105  private:
109  virtual bool serialize(IO::CWriteStream &i_oStream) const {
110  return true;
111  }
112 
113  public:
117  bool doDeserialize(IO::CReadStream &i_oStream) {
118  if (!IsHidden) {
119  return this->deserialize(i_oStream);
120  }
121 
122  return true;
123  }
124 
128  bool doDeserialize(const char *i_szString) {
129  if (!IsHidden) {
130  return this->deserialize(i_szString);
131  }
132 
133  return true;
134  }
135 
140  bool doDeserialize(std::vector<std::string>::const_iterator &i_oIt,
141  const std::vector<std::string>::const_iterator &i_oItEnd) {
142  if (!IsHidden) {
143  return this->deserialize(i_oIt, i_oItEnd);
144  }
145 
146  return true;
147  }
148 
149  private:
153  virtual bool deserialize(IO::CReadStream &i_oStream) {
154  return true;
155  }
156 
160  virtual bool deserialize(const char *i_szString) {
161  return true;
162  }
163 
168  virtual bool deserialize(std::vector<std::string>::const_iterator &i_oIt,
169  const std::vector<std::string>::const_iterator &i_oItEnd) {
170  ++i_oIt;
171  return true;
172  }
173 
174  public:
177  [[nodiscard]] virtual size_t size() const {
178  return sizeof(*this);
179  }
180 
183  [[nodiscard]] virtual bool isHidden() const {
184  return IsHidden;
185  }
186 
189  [[nodiscard]] virtual SCompareData compareData() const {
190  return {static_cast<const void *>(&this->m_tValue), sizeof(T)};
191  }
192 
193  public:
196  auto begin() const {
197  return this->m_tValue.begin();
198  }
199 
202  auto end() const {
203  return this->m_tValue.end();
204  }
205 
206  public:
210  auto &operator[](const size_t i_nIndex) {
211  return this->m_tValue[i_nIndex];
212  }
213 
217  const auto &operator[](const size_t i_nIndex) const {
218  return this->m_tValue[i_nIndex];
219  }
220 
224  operator--() {
225  --this->m_tValue;
226  return *this;
227  }
228 
232  operator--(int) {
233  --this->m_tValue;
234  return *this;
235  }
236 
237 
241  operator++() {
242  ++this->m_tValue;
243  return *this;
244  }
245 
249  operator++(int) {
250  ++this->m_tValue;
251  return *this;
252  }
253 
257  SerializerEnableIfNotArithmetic(IData<T> &)
258  operator+=(const T &i_tValue) {
259  this->m_tValue += i_tValue;
260  return *this;
261  }
262 
266  SerializerEnableIfNotArithmetic(IData<T> &)
267  operator-=(const T &i_tValue) {
268  this->m_tValue -= i_tValue;
269  return *this;
270  }
271 
275  SerializerEnableIfNotArithmetic(IData<T> &)
276  operator*=(const T &i_tValue) {
277  this->m_tValue *= i_tValue;
278  return *this;
279  }
280 
284  SerializerEnableIfNotArithmetic(IData<T> &)
285  operator/=(const T &i_tValue) {
286  this->m_tValue /= i_tValue;
287  return *this;
288  }
289 
293  SerializerEnableIfNotArithmetic(IData<T> &)
294  operator%=(const T &i_tValue) {
295  this->m_tValue %= i_tValue;
296  return *this;
297  }
298 
302  SerializerEnableIfNotArithmetic(IData<T> &)
303  operator&=(const T &i_tValue) {
304  this->m_tValue &= i_tValue;
305  return *this;
306  }
307 
311  SerializerEnableIfNotArithmetic(IData<T> &)
312  operator|=(const T &i_tValue) {
313  this->m_tValue |= i_tValue;
314  return *this;
315  }
316 
320  SerializerEnableIfNotArithmetic(IData<T> &)
321  operator^=(const T &i_tValue) {
322  this->m_tValue ^= i_tValue;
323  return *this;
324  }
325 
329  SerializerEnableIfNotArithmetic(IData<T> &)
330  operator<<=(const T &i_tValue) {
331  this->m_tValue <<= i_tValue;
332  return *this;
333  }
334 
338  SerializerEnableIfNotArithmetic(IData<T> &)
339  operator>>=(const T &i_tValue) {
340  this->m_tValue >>= i_tValue;
341  return *this;
342  }
343 
347  SerializerEnableIfNotArithmetic(T)
348  operator+(const T &i_tValue) const {
349  return this->m_tValue + i_tValue;
350  }
351 
355  SerializerEnableIfNotArithmetic(T)
356  operator-(const T &i_tValue) const {
357  return this->m_tValue - i_tValue;
358  }
359 
363  SerializerEnableIfNotArithmetic(T)
364  operator*(const T &i_tValue) const {
365  return this->m_tValue * i_tValue;
366  }
367 
371  SerializerEnableIfNotArithmetic(T)
372  operator/(const T &i_tValue) const {
373  return this->m_tValue / i_tValue;
374  }
375 
379  SerializerEnableIfNotArithmetic(T)
380  operator%(const T &i_tValue) const {
381  return this->m_tValue % i_tValue;
382  }
383 
387  SerializerEnableIfNotArithmetic(T)
388  operator&(const T &i_tValue) const {
389  return this->m_tValue & i_tValue;
390  }
391 
395  SerializerEnableIfNotArithmetic(T)
396  operator|(const T &i_tValue) const {
397  return this->m_tValue | i_tValue;
398  }
399 
403  SerializerEnableIfNotArithmetic(T)
404  operator^(const T &i_tValue) const {
405  return this->m_tValue ^ i_tValue;
406  }
407 
411  SerializerEnableIfNotArithmetic(T)
412  operator<<(const T &i_tValue) const {
413  return this->m_tValue << i_tValue;
414  }
415 
419  SerializerEnableIfNotArithmetic(T)
420  operator>>(const T &i_tValue) const {
421  return this->m_tValue >> i_tValue;
422  }
423 
426  SerializerEnableIfNotArithmetic(bool)
427  operator!() const {
428  return !this->m_tValue;
429  }
430 
434  SerializerEnableIfNotArithmetic(bool)
435  operator==(const T &i_tValue) const {
436  return this->m_tValue == i_tValue;
437  }
438 
442  SerializerEnableIfNotArithmetic(bool)
443  operator!=(const T &i_tValue) const {
444  return this->m_tValue != i_tValue;
445  }
446 
450  SerializerEnableIfNotArithmetic(bool)
451  operator>(const T &i_tValue) const {
452  return this->m_tValue > i_tValue;
453  }
454 
458  SerializerEnableIfNotArithmetic(bool)
459  operator>=(const T &i_tValue) const {
460  return this->m_tValue >= i_tValue;
461  }
462 
466  SerializerEnableIfNotArithmetic(bool)
467  operator<(const T &i_tValue) const {
468  return this->m_tValue < i_tValue;
469  }
470 
474  SerializerEnableIfNotArithmetic(bool)
475  operator<=(const T &i_tValue) const {
476  return this->m_tValue <= i_tValue;
477  }
478 
481  template<typename T1 = T>
482  typename std::enable_if<std::is_pointer<T1>::value, T>::type
483  operator->() const {
484  return this->m_tValue;
485  }
486 
489  template<typename T1 = T>
490  typename std::enable_if<!std::is_pointer<T1>::value, T *>::type
491  operator->() {
492  return &this->m_tValue;
493  }
494 
497  T &operator*() {
498  return *this->m_tValue;
499  }
500 
503  const T &operator*() const {
504  return *this->m_tValue;
505  }
506 
509  operator T &() {
510  return this->m_tValue;
511  }
512 
515  operator const T &() const {
516  return this->m_tValue;
517  }
518  };
519 
520 #pragma pack(pop)
521 
527  template<typename T>
528  std::ostream &operator<<(std::ostream &i_oStream, const IValue<T> &i_tData) {
529  i_oStream << i_tData.value();
530  return i_oStream;
531  }
532 
538  template<typename T>
539  std::istream &operator>>(std::istream &i_oStream, const IValue<T> &i_tData) {
540  i_oStream >> i_tData.value();
541  return i_oStream;
542  }
543 
549  template<typename T>
550  std::wostream &operator<<(std::wostream &i_oStream, const IValue<T> &i_tData) {
551  i_oStream << i_tData.value();
552  return i_oStream;
553  }
554 
560  template<typename T>
561  std::wistream &operator>>(std::wistream &i_oStream, const IValue<T> &i_tData) {
562  i_oStream >> i_tData.value();
563  return i_oStream;
564  }
565 
566 
574  // When callback return false then break iteration
575  template<typename TStructFieldType = IData<>, typename TStruct>
576  bool IterateSerializableStruct(const TStruct *i_pStruct, std::function<bool(const TStructFieldType *)> i_pCallback,
577  const size_t i_nStructSize = sizeof(TStruct)) {
578 
579  for (size_t i = ((std::is_base_of_v<IStruct, TStruct> && std::is_polymorphic_v<TStruct>) ? sizeof(void *) : 0);
580  i < i_nStructSize;) {
581  auto pData = reinterpret_cast<const TStructFieldType *>((reinterpret_cast<const char *>(i_pStruct) + i));
582 
583  if (!i_pCallback(pData)) {
584  return false;
585  }
586 
587  i += pData->size();
588  }
589 
590  return true;
591  }
592 
600  template<typename TStructFieldType = IData<>, typename TStruct>
601  bool IterateSerializableStruct(const TStruct &i_oStruct, std::function<bool(const TStructFieldType *)> i_pCallback,
602  const size_t i_nStructSize = sizeof(TStruct)) {
603  return IterateSerializableStruct<TStructFieldType, TStruct>(&i_oStruct, i_pCallback, i_nStructSize);
604  }
605 
613  // When callback return false then break iteration
614  template<typename TStructFieldType = IData<>, typename TStruct>
615  bool IterateDeserializableStruct(TStruct *i_pStruct, std::function<bool(TStructFieldType *)> i_pCallback,
616  const size_t i_nStructSize = sizeof(TStruct)) {
617  for (size_t i = (std::has_virtual_destructor_v<TStruct> ? sizeof(void *) : 0); i < i_nStructSize;) {
618  auto *pData = SerializableGetField(TStructFieldType, i_pStruct, i);
619 
620  if (!i_pCallback(pData)) {
621  return false;
622  }
623 
624  i += pData->size();
625  }
626 
627  return true;
628  }
629 
637  template<typename TStructFieldType = IData<>, typename TStruct>
638  bool IterateDeserializableStruct(TStruct &i_oStruct, std::function<bool(TStructFieldType *)> i_pCallback,
639  const size_t i_nStructSize = sizeof(TStruct)) {
640  return IterateSerializableStruct<TStructFieldType, TStruct>(&i_oStruct, i_pCallback, i_nStructSize);
641  }
642 
643 
651  template<typename TStructFieldType = IData<>, typename TStruct>
652  std::vector<size_t> GetSerializableFieldOffsets(const TStruct *i_pStruct, const bool i_fIncludeHidden = true,
653  const size_t i_nStructSize = sizeof(TStruct)) {
654  std::vector<size_t> anOffsets;
655  anOffsets.reserve(10);
656 
657  for (size_t i = (std::has_virtual_destructor_v<TStruct> ? sizeof(void *) : 0); i < i_nStructSize;) {
658  auto *pData = SerializableGetField(TStructFieldType, i_pStruct, i);
659 
660  if (i_fIncludeHidden || !pData->isHidden()) {
661  anOffsets.push_back(i);
662  }
663 
664  i += pData->size();
665  }
666 
667  return anOffsets;
668  }
669 
677  template<typename TStructFieldType = IData<>, typename TStruct>
678  std::vector<size_t> GetSerializableFieldOffsets(const TStruct &i_oStruct, const bool i_fIncludeHidden = true,
679  const size_t i_nStructSize = sizeof(TStruct)) {
680  return GetSerializableFieldOffsets<TStructFieldType, TStruct>(&i_oStruct, i_fIncludeHidden, i_nStructSize);
681  }
682 
683 
691  template<typename TStructFieldType = IData<>, typename TStruct>
692  TStructFieldType *GetSerializableFieldByIndex(const TStruct *i_pStruct, const size_t i_nIndex) {
693  TStructFieldType *pReturn = nullptr;
694  size_t nCurrentIndex = 0;
695  IterateSerializableStruct<TStructFieldType>(i_pStruct, [&](TStructFieldType *i_pData) {
696  if (nCurrentIndex == i_nIndex) {
697  pReturn = i_pData;
698  return false;
699  }
700 
701  nCurrentIndex++;
702 
703  return true;
704  });
705 
706  return pReturn;
707  }
708 
715  template<typename TStructFieldType = IData<>, typename TStruct>
716  TStructFieldType *GetSerializableFieldByIndex(const TStruct &i_oStruct, const size_t i_nIndex) {
717  return GetSerializableFieldByIndex<TStructFieldType, TStruct>(&i_oStruct, i_nIndex);
718  }
719 
720 
728  template<typename TStructFieldType = IData<>, typename TStruct>
729  bool CompareSerializableStruct(TStruct *i_pStruct, TStruct *i_pCompareStruct, const bool i_fIncludeHidden = false) {
730  std::vector<size_t> anOffsets = GetSerializableFieldOffsets(i_pStruct, i_fIncludeHidden);
731 
732  for (size_t nOffset: anOffsets) {
733  auto *pFirst = SerializableGetField(TStructFieldType, i_pStruct, nOffset);
734  auto *pSecond = SerializableGetField(TStructFieldType, i_pCompareStruct, nOffset);
735 
736  const SCompareData oFirstCompareData = pFirst->compareData();
737  const SCompareData oSecondCompareData = pSecond->compareData();
738 
739  if (oFirstCompareData.nSize != oSecondCompareData.nSize) {
740  return false;
741  }
742 
743  if (memcmp(oFirstCompareData.pData, oSecondCompareData.pData, oFirstCompareData.nSize) != 0) {
744  return false;
745  }
746  }
747 
748  return true;
749  }
750 
758  template<typename TStructFieldType = IData<>, typename TStruct>
759  bool CompareSerializableStruct(TStruct &i_oStruct, TStruct &i_oCompareStruct, const bool i_fIncludeHidden = false) {
760  return CompareSerializableStruct<TStructFieldType, TStruct>(&i_oStruct, &i_oCompareStruct, i_fIncludeHidden);
761  }
762 
766  std::false_type is_data_class_impl(...);
767 
768  template<typename T = int, bool IsHidden = false>
769  std::true_type is_data_class_impl(IData<T, IsHidden> *);
770 
771  template<typename T>
772  using is_data_class = decltype(is_data_class_impl(std::declval<T *>()));
773 }
A class for reading data from a buffer. This class provides functionality to read data from a buffer....
Definition: ReadStream.h:37
A class for writing data to a buffer. This class provides functionality to write data to a buffer....
Definition: WriteStream.h:42
Template class representing a data field.
Definition: SerializableData.h:86
bool doDeserialize(const char *i_szString)
Deserializes the data from a string.
Definition: SerializableData.h:128
virtual SCompareData compareData() const
Returns the compare data for the data field.
Definition: SerializableData.h:189
virtual ~IData()=default
Default destructor.
SerializerEnableIfNotArithmetic(IData< T > &) operator--()
Pre-decrement operator.
Definition: SerializableData.h:223
auto & operator[](const size_t i_nIndex)
Returns a reference to the value at the specified index.
Definition: SerializableData.h:210
SerializerEnableIfNotArithmetic(IData< T > &) operator++()
Pre-increment operator.
Definition: SerializableData.h:240
auto end() const
Returns an iterator pointing to the end of the value.
Definition: SerializableData.h:202
const auto & operator[](const size_t i_nIndex) const
Returns a const reference to the value at the specified index.
Definition: SerializableData.h:217
SerializerEnableIfNotArithmetic(IData< T > &) operator--(int)
Post-decrement operator.
Definition: SerializableData.h:231
auto begin() const
Returns an iterator pointing to the beginning of the value.
Definition: SerializableData.h:196
virtual bool isHidden() const
Returns whether the field is hidden.
Definition: SerializableData.h:183
bool doDeserialize(IO::CReadStream &i_oStream)
Deserializes the data from a read stream.
Definition: SerializableData.h:117
SerializerEnableIfNotArithmetic(IData< T > &) operator++(int)
Post-increment operator.
Definition: SerializableData.h:248
bool doDeserialize(std::vector< std::string >::const_iterator &i_oIt, const std::vector< std::string >::const_iterator &i_oItEnd)
Deserializes the data from a range of strings.
Definition: SerializableData.h:140
bool doSerialize(IO::CWriteStream &i_oStream) const
Serializes the data to a write stream.
Definition: SerializableData.h:97
virtual size_t size() const
Returns the size of the data.
Definition: SerializableData.h:177
Base class for fields.
Definition: SerializableData.h:46
Definition: SerializableData.h:39
Template class representing a value.
Definition: SerializableData.h:53
T m_tValue
The value.
Definition: SerializableData.h:78
const T & value() const
Returns the value.
Definition: SerializableData.h:65
T & value()
Returns a reference to the value.
Definition: SerializableData.h:71
IValue(TArgs... i_tArgs)
Constructs an IValue object with the specified arguments.
Definition: SerializableData.h:59
The namespace encapsulating serializing related functionality in the Devel framework.
std::ostream & operator<<(std::ostream &i_oStream, const IValue< T > &i_tData)
Output stream operator for IValue.
Definition: SerializableData.h:528
bool IterateSerializableStruct(const TStruct *i_pStruct, std::function< bool(const TStructFieldType *)> i_pCallback, const size_t i_nStructSize=sizeof(TStruct))
Iterates over a serializable struct and applies a callback function to each field.
Definition: SerializableData.h:576
std::false_type is_data_class_impl(...)
Check if a type is a data class.
TStructFieldType * GetSerializableFieldByIndex(const TStruct *i_pStruct, const size_t i_nIndex)
Gets the offsets of the serializable fields in a struct.
Definition: SerializableData.h:692
bool CompareSerializableStruct(TStruct *i_pStruct, TStruct *i_pCompareStruct, const bool i_fIncludeHidden=false)
Compares two serializable structs for equality.
Definition: SerializableData.h:729
std::istream & operator>>(std::istream &i_oStream, const IValue< T > &i_tData)
Input stream operator for IValue.
Definition: SerializableData.h:539
std::vector< size_t > GetSerializableFieldOffsets(const TStruct *i_pStruct, const bool i_fIncludeHidden=true, const size_t i_nStructSize=sizeof(TStruct))
Gets the offsets of the serializable fields in a struct.
Definition: SerializableData.h:652
bool IterateDeserializableStruct(TStruct *i_pStruct, std::function< bool(TStructFieldType *)> i_pCallback, const size_t i_nStructSize=sizeof(TStruct))
Iterates over a deserializable struct and applies a callback function to each field.
Definition: SerializableData.h:615
Structure for comparing serialized data.
Definition: SerializableData.h:19
const void * pData
The pointer to the data.
Definition: SerializableData.h:28
SCompareData(const void *i_pData, const size_t i_nSize)
Constructs an SCompareData object with the specified data and size.
Definition: SerializableData.h:23
const size_t nSize
The size of the data.
Definition: SerializableData.h:32