CmRTTIPrerequisites.h 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. #pragma once
  2. namespace CamelotFramework
  3. {
  4. /**
  5. * @brief Helper method when serializing known data types that have valid
  6. * RTTIPlainType specializations.
  7. *
  8. * Returns the size of the element. If elements serializable type is
  9. * specialized with hasDynamicSize == true, the dynamic size is calculated,
  10. * otherwise sizeof() is used.
  11. */
  12. template<class ElemType>
  13. UINT32 rttiGetElemSize(const ElemType& data)
  14. {
  15. if(RTTIPlainType<ElemType>::hasDynamicSize == 1)
  16. return RTTIPlainType<ElemType>::getDynamicSize(data);
  17. else
  18. return sizeof(ElemType);
  19. }
  20. /**
  21. * @brief Helper method when serializing known data types that have valid
  22. * RTTIPlainType specializations.
  23. *
  24. * Writes the specified data into memory, advances the memory pointer by the
  25. * bytes written and returns pointer to new memory.
  26. */
  27. template<class ElemType>
  28. char* rttiWriteElem(const ElemType& data, char* memory)
  29. {
  30. RTTIPlainType<ElemType>::toMemory(data, memory);
  31. return memory + rttiGetElemSize(data);
  32. }
  33. /**
  34. * @brief Helper method when serializing known data types that have valid
  35. * RTTIPlainType specializations.
  36. *
  37. * Reads the specified data into memory, advances the memory pointer by the
  38. * bytes read and returns pointer to new memory.
  39. */
  40. template<class ElemType>
  41. char* rttiReadElem(ElemType& data, char* memory)
  42. {
  43. RTTIPlainType<ElemType>::fromMemory(data, memory);
  44. return memory + rttiGetElemSize(data);
  45. }
  46. template<class T>
  47. struct RTTIPlainType
  48. {
  49. static_assert(std::is_pod<T>::value,
  50. "Provided type isn't plain-old-data. You need to specialize RTTIPlainType template in order to serialize this type. "\
  51. " (Or call CM_ALLOW_MEMCPY_SERIALIZATION(type) macro if you are sure the type can be properly serialized using just memcpy.)");
  52. enum { id = 0 };
  53. enum { hasDynamicSize = 0 };
  54. static void toMemory(const T& data, char* memory)
  55. {
  56. memcpy(memory, &data, sizeof(T));
  57. }
  58. static UINT32 fromMemory(T& data, char* memory)
  59. {
  60. memcpy(&data, memory, sizeof(T));
  61. return sizeof(T);
  62. }
  63. static UINT32 getDynamicSize(const T& data)
  64. {
  65. assert(false);
  66. return sizeof(T);
  67. }
  68. };
  69. #define CM_ALLOW_MEMCPY_SERIALIZATION(type) \
  70. template<> struct RTTIPlainType<##type##> \
  71. { enum { id=0 }; enum { hasDynamicSize = 0 }; \
  72. static void toMemory(const type& data, char* memory) \
  73. { memcpy(memory, &data, sizeof(##type##)); } \
  74. static UINT32 fromMemory(##type##& data, char* memory) \
  75. { memcpy(&data, memory, sizeof(##type##)); return sizeof(##type##); } \
  76. static UINT32 getDynamicSize(const type& data) \
  77. { assert(false); return sizeof(##type##); } \
  78. };
  79. // RTTI types for some standard classes
  80. template<class T> struct RTTIPlainType<std::vector<T, StdAlloc<T>>>
  81. {
  82. enum { id = TID_STDVECTOR }; enum { hasDynamicSize = 1 };
  83. static void toMemory(const std::vector<T, StdAlloc<T>>& data, char* memory)
  84. {
  85. UINT32 size = (UINT32)data.size();
  86. memcpy(memory, &size, sizeof(UINT32));
  87. memory += sizeof(UINT32);
  88. for(auto iter = data.begin(); iter != data.end(); ++iter)
  89. {
  90. UINT32 elementSize = RTTIPlainType<T>::getDynamicSize(*iter);
  91. RTTIPlainType<T>::toMemory(*iter, memory);
  92. memory += elementSize;
  93. }
  94. }
  95. static UINT32 fromMemory(std::vector<T, StdAlloc<T>>& data, char* memory)
  96. {
  97. UINT32 size;
  98. memcpy(&size, memory, sizeof(UINT32));
  99. memory += sizeof(UINT32);
  100. for(UINT32 i = 0; i < size; i++)
  101. {
  102. T element;
  103. UINT32 elementSize = RTTIPlainType<T>::fromMemory(element, memory);
  104. data.push_back(element);
  105. memory += elementSize;
  106. }
  107. return size;
  108. }
  109. static UINT32 getDynamicSize(const std::vector<T, StdAlloc<T>>& data)
  110. {
  111. UINT64 dataSize = sizeof(UINT32);
  112. for(auto iter = data.begin(); iter != data.end(); ++iter)
  113. dataSize += RTTIPlainType<T>::getDynamicSize(*iter);
  114. assert(dataSize <= std::numeric_limits<UINT32>::max());
  115. return (UINT32)dataSize;
  116. }
  117. };
  118. template<class Key, class Value> struct RTTIPlainType<std::map<Key, Value, std::less<Key>, StdAlloc<std::pair<const Key, Value>>>>
  119. {
  120. enum { id = TID_STDMAP }; enum { hasDynamicSize = 1 };
  121. static void toMemory(const std::map<Key, Value, std::less<Key>, StdAlloc<std::pair<const Key, Value>>>& data, char* memory)
  122. {
  123. UINT32 size = (UINT32)data.size();
  124. memcpy(memory, &size, sizeof(UINT32));
  125. memory += sizeof(UINT32);
  126. for(auto iter = data.begin(); iter != data.end(); ++iter)
  127. {
  128. UINT32 keySize = RTTIPlainType<Key>::getDynamicSize(iter->first);
  129. RTTIPlainType<Key>::toMemory(iter->first, memory);
  130. memory += keySize;
  131. UINT32 valueSize = RTTIPlainType<Value>::getDynamicSize(iter->second);
  132. RTTIPlainType<Value>::toMemory(iter->second, memory);
  133. memory += valueSize;
  134. }
  135. }
  136. static UINT32 fromMemory(std::map<Key, Value, std::less<Key>, StdAlloc<std::pair<const Key, Value>>>& data, char* memory)
  137. {
  138. UINT32 size;
  139. memcpy(&size, memory, sizeof(UINT32));
  140. memory += sizeof(UINT32);
  141. for(UINT32 i = 0; i < size; i++)
  142. {
  143. Key key;
  144. UINT32 keySize = RTTIPlainType<Key>::fromMemory(key, memory);
  145. memory += keySize;
  146. Value value;
  147. UINT32 valueSize = RTTIPlainType<Value>::fromMemory(value, memory);
  148. memory += valueSize;
  149. data[key] = value;
  150. }
  151. return size;
  152. }
  153. static UINT32 getDynamicSize(const std::map<Key, Value, std::less<Key>, StdAlloc<std::pair<const Key, Value>>>& data)
  154. {
  155. UINT64 dataSize = sizeof(UINT32);
  156. for(auto iter = data.begin(); iter != data.end(); ++iter)
  157. {
  158. dataSize += RTTIPlainType<Key>::getDynamicSize(iter->first);
  159. dataSize += RTTIPlainType<Value>::getDynamicSize(iter->second);
  160. }
  161. assert(dataSize <= std::numeric_limits<UINT32>::max());
  162. return (UINT32)dataSize;
  163. }
  164. };
  165. }