BsRTTIPrerequisites.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487
  1. #pragma once
  2. namespace BansheeEngine
  3. {
  4. /**
  5. * @brief Helper method when serializing known data types that have valid
  6. * RTTIPlainType specialization.
  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 specialization.
  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 specialization.
  36. *
  37. * Writes the specified data into memory, advances the memory pointer by the
  38. * bytes written and returns pointer to new memory. Also increases the size
  39. * value by the size of the written element.
  40. */
  41. template<class ElemType>
  42. char* rttiWriteElem(const ElemType& data, char* memory, UINT32& size)
  43. {
  44. RTTIPlainType<ElemType>::toMemory(data, memory);
  45. UINT32 elemSize = rttiGetElemSize(data);
  46. size += elemSize;
  47. return memory + elemSize;
  48. }
  49. /**
  50. * @brief Helper method when serializing known data types that have valid
  51. * RTTIPlainType specialization.
  52. *
  53. * Reads the specified data into memory, advances the memory pointer by the
  54. * bytes read and returns pointer to new memory.
  55. */
  56. template<class ElemType>
  57. char* rttiReadElem(ElemType& data, char* memory)
  58. {
  59. RTTIPlainType<ElemType>::fromMemory(data, memory);
  60. return memory + rttiGetElemSize(data);
  61. }
  62. /**
  63. * @brief Helper method when serializing known data types that have valid
  64. * RTTIPlainType specialization.
  65. *
  66. * Reads the specified data into memory, advances the memory pointer by the
  67. * bytes read and returns pointer to new memory. Also increases the size
  68. * value by the size of the read element.
  69. */
  70. template<class ElemType>
  71. char* rttiReadElem(ElemType& data, char* memory, UINT32& size)
  72. {
  73. RTTIPlainType<ElemType>::fromMemory(data, memory);
  74. UINT32 elemSize = rttiGetElemSize(data);
  75. size += elemSize;
  76. return memory + elemSize;
  77. }
  78. /**
  79. * @brief Template that you may specialize with a class if you want to provide
  80. * simple serialization for it.
  81. *
  82. * Any type that uses the "plain" field in the RTTI system must specialize this class.
  83. *
  84. * @note Normally you will want to implement IReflectable interface if you want to provide serialization
  85. * as that interface properly handles versioning, nested objects, pointer handling and more.
  86. *
  87. * This class is useful for types you can easily serialize using a memcpy (built-in types like int/float/etc), or
  88. * types you cannot modify so they implement IReflectable interface (like std::string or std::vector).
  89. *
  90. * @see RTTIType
  91. * @see RTTIField
  92. */
  93. template<class T>
  94. struct RTTIPlainType
  95. {
  96. static_assert(std::is_pod<T>::value,
  97. "Provided type isn't plain-old-data. You need to specialize RTTIPlainType template in order to serialize this type. "\
  98. " (Or call BS_ALLOW_MEMCPY_SERIALIZATION(type) macro if you are sure the type can be properly serialized using just memcpy.)");
  99. enum { id = 0 /**< Unique id for the serializable type. */ };
  100. enum { hasDynamicSize = 0 /**< 0 (Object has static size less than 255 bytes, e.g. int) or 1 (Dynamic size with no size restriction, e.g. string) */ };
  101. /**
  102. * @brief Serializes the provided object into the provided pre-allocated
  103. * memory buffer.
  104. */
  105. static void toMemory(const T& data, char* memory)
  106. {
  107. memcpy(memory, &data, sizeof(T));
  108. }
  109. /**
  110. * @brief Deserializes a previously allocated object from the provided
  111. * memory buffer. Return the number of bytes read from the memory buffer.
  112. */
  113. static UINT32 fromMemory(T& data, char* memory)
  114. {
  115. memcpy(&data, memory, sizeof(T));
  116. return sizeof(T);
  117. }
  118. /**
  119. * @brief Returns the size of the provided object. (Works for both
  120. * static and dynamic size types)
  121. */
  122. static UINT32 getDynamicSize(const T& data)
  123. {
  124. assert(false);
  125. return sizeof(T);
  126. }
  127. };
  128. /**
  129. * @brief Tell the RTTI system that the specified type may be serialized just by
  130. * using a memcpy.
  131. *
  132. * @note Internally this creates a basic RTTIPlainType specialization for the type.
  133. *
  134. * @see RTTIPlainType
  135. */
  136. #define BS_ALLOW_MEMCPY_SERIALIZATION(type) \
  137. template<> struct RTTIPlainType<##type##> \
  138. { enum { id=0 }; enum { hasDynamicSize = 0 }; \
  139. static void toMemory(const type& data, char* memory) \
  140. { memcpy(memory, &data, sizeof(##type##)); } \
  141. static UINT32 fromMemory(##type##& data, char* memory) \
  142. { memcpy(&data, memory, sizeof(##type##)); return sizeof(##type##); } \
  143. static UINT32 getDynamicSize(const type& data) \
  144. { assert(false); return sizeof(##type##); } \
  145. };
  146. /**
  147. * @brief RTTIPlainType for std::vector.
  148. *
  149. * @see RTTIPlainType
  150. */
  151. template<class T> struct RTTIPlainType<std::vector<T, StdAlloc<T>>>
  152. {
  153. enum { id = TID_Vector }; enum { hasDynamicSize = 1 };
  154. /**
  155. * @copydoc RTTIPlainType::toMemory
  156. */
  157. static void toMemory(const std::vector<T, StdAlloc<T>>& data, char* memory)
  158. {
  159. UINT32 size = sizeof(UINT32);
  160. char* memoryStart = memory;
  161. memory += sizeof(UINT32);
  162. UINT32 numElements = (UINT32)data.size();
  163. memcpy(memory, &numElements, sizeof(UINT32));
  164. memory += sizeof(UINT32);
  165. size += sizeof(UINT32);
  166. for(auto iter = data.begin(); iter != data.end(); ++iter)
  167. {
  168. UINT32 elementSize = RTTIPlainType<T>::getDynamicSize(*iter);
  169. RTTIPlainType<T>::toMemory(*iter, memory);
  170. memory += elementSize;
  171. size += elementSize;
  172. }
  173. memcpy(memoryStart, &size, sizeof(UINT32));
  174. }
  175. /**
  176. * @copydoc RTTIPlainType::toMemory
  177. */
  178. static UINT32 fromMemory(std::vector<T, StdAlloc<T>>& data, char* memory)
  179. {
  180. UINT32 size = 0;
  181. memcpy(&size, memory, sizeof(UINT32));
  182. memory += sizeof(UINT32);
  183. UINT32 numElements;
  184. memcpy(&numElements, memory, sizeof(UINT32));
  185. memory += sizeof(UINT32);
  186. for(UINT32 i = 0; i < numElements; i++)
  187. {
  188. T element;
  189. UINT32 elementSize = RTTIPlainType<T>::fromMemory(element, memory);
  190. data.push_back(element);
  191. memory += elementSize;
  192. }
  193. return size;
  194. }
  195. /**
  196. * @copydoc RTTIPlainType::toMemory
  197. */
  198. static UINT32 getDynamicSize(const std::vector<T, StdAlloc<T>>& data)
  199. {
  200. UINT64 dataSize = sizeof(UINT32) * 2;
  201. for(auto iter = data.begin(); iter != data.end(); ++iter)
  202. dataSize += RTTIPlainType<T>::getDynamicSize(*iter);
  203. assert(dataSize <= std::numeric_limits<UINT32>::max());
  204. return (UINT32)dataSize;
  205. }
  206. };
  207. /**
  208. * @brief RTTIPlainType for std::map.
  209. *
  210. * @see RTTIPlainType
  211. */
  212. template<class Key, class Value> struct RTTIPlainType<std::map<Key, Value, std::less<Key>, StdAlloc<std::pair<const Key, Value>>>>
  213. {
  214. enum { id = TID_Map }; enum { hasDynamicSize = 1 };
  215. /**
  216. * @copydoc RTTIPlainType::toMemory
  217. */
  218. static void toMemory(const std::map<Key, Value, std::less<Key>, StdAlloc<std::pair<const Key, Value>>>& data, char* memory)
  219. {
  220. UINT32 size = sizeof(UINT32);
  221. char* memoryStart = memory;
  222. memory += sizeof(UINT32);
  223. UINT32 numElements = (UINT32)data.size();
  224. memcpy(memory, &numElements, sizeof(UINT32));
  225. memory += sizeof(UINT32);
  226. size += sizeof(UINT32);
  227. for(auto iter = data.begin(); iter != data.end(); ++iter)
  228. {
  229. UINT32 keySize = RTTIPlainType<Key>::getDynamicSize(iter->first);
  230. RTTIPlainType<Key>::toMemory(iter->first, memory);
  231. memory += keySize;
  232. size += keySize;
  233. UINT32 valueSize = RTTIPlainType<Value>::getDynamicSize(iter->second);
  234. RTTIPlainType<Value>::toMemory(iter->second, memory);
  235. memory += valueSize;
  236. size += valueSize;
  237. }
  238. memcpy(memoryStart, &size, sizeof(UINT32));
  239. }
  240. /**
  241. * @copydoc RTTIPlainType::fromMemory
  242. */
  243. static UINT32 fromMemory(std::map<Key, Value, std::less<Key>, StdAlloc<std::pair<const Key, Value>>>& data, char* memory)
  244. {
  245. UINT32 size = 0;
  246. memcpy(&size, memory, sizeof(UINT32));
  247. memory += sizeof(UINT32);
  248. UINT32 numElements;
  249. memcpy(&numElements, memory, sizeof(UINT32));
  250. memory += sizeof(UINT32);
  251. for(UINT32 i = 0; i < numElements; i++)
  252. {
  253. Key key;
  254. UINT32 keySize = RTTIPlainType<Key>::fromMemory(key, memory);
  255. memory += keySize;
  256. Value value;
  257. UINT32 valueSize = RTTIPlainType<Value>::fromMemory(value, memory);
  258. memory += valueSize;
  259. data[key] = value;
  260. }
  261. return size;
  262. }
  263. /**
  264. * @copydoc RTTIPlainType::getDynamicSize
  265. */
  266. static UINT32 getDynamicSize(const std::map<Key, Value, std::less<Key>, StdAlloc<std::pair<const Key, Value>>>& data)
  267. {
  268. UINT64 dataSize = sizeof(UINT32) * 2;
  269. for(auto iter = data.begin(); iter != data.end(); ++iter)
  270. {
  271. dataSize += RTTIPlainType<Key>::getDynamicSize(iter->first);
  272. dataSize += RTTIPlainType<Value>::getDynamicSize(iter->second);
  273. }
  274. assert(dataSize <= std::numeric_limits<UINT32>::max());
  275. return (UINT32)dataSize;
  276. }
  277. };
  278. /**
  279. * @brief RTTIPlainType for std::unordered_map.
  280. *
  281. * @see RTTIPlainType
  282. */
  283. template<class Key, class Value>
  284. struct RTTIPlainType<std::unordered_map<Key, Value, std::hash<Key>, std::equal_to<Key>, StdAlloc<std::pair<const Key, Value>>>>
  285. {
  286. enum { id = TID_UnorderedMap }; enum { hasDynamicSize = 1 };
  287. typedef std::unordered_map<Key, Value, std::hash<Key>, std::equal_to<Key>, StdAlloc<std::pair<const Key, Value>>> MapType;
  288. /**
  289. * @copydoc RTTIPlainType::toMemory
  290. */
  291. static void toMemory(MapType& data, char* memory)
  292. {
  293. UINT32 size = sizeof(UINT32);
  294. char* memoryStart = memory;
  295. memory += sizeof(UINT32);
  296. UINT32 numElements = (UINT32)data.size();
  297. memcpy(memory, &numElements, sizeof(UINT32));
  298. memory += sizeof(UINT32);
  299. size += sizeof(UINT32);
  300. for (auto iter = data.begin(); iter != data.end(); ++iter)
  301. {
  302. UINT32 keySize = RTTIPlainType<Key>::getDynamicSize(iter->first);
  303. RTTIPlainType<Key>::toMemory(iter->first, memory);
  304. memory += keySize;
  305. size += keySize;
  306. UINT32 valueSize = RTTIPlainType<Value>::getDynamicSize(iter->second);
  307. RTTIPlainType<Value>::toMemory(iter->second, memory);
  308. memory += valueSize;
  309. size += valueSize;
  310. }
  311. memcpy(memoryStart, &size, sizeof(UINT32));
  312. }
  313. /**
  314. * @copydoc RTTIPlainType::fromMemory
  315. */
  316. static UINT32 fromMemory(MapType& data, char* memory)
  317. {
  318. UINT32 size = 0;
  319. memcpy(&size, memory, sizeof(UINT32));
  320. memory += sizeof(UINT32);
  321. UINT32 numElements;
  322. memcpy(&numElements, memory, sizeof(UINT32));
  323. memory += sizeof(UINT32);
  324. for (UINT32 i = 0; i < numElements; i++)
  325. {
  326. Key key;
  327. UINT32 keySize = RTTIPlainType<Key>::fromMemory(key, memory);
  328. memory += keySize;
  329. Value value;
  330. UINT32 valueSize = RTTIPlainType<Value>::fromMemory(value, memory);
  331. memory += valueSize;
  332. data[key] = value;
  333. }
  334. return size;
  335. }
  336. /**
  337. * @copydoc RTTIPlainType::getDynamicSize
  338. */
  339. static UINT32 getDynamicSize(const MapType& data)
  340. {
  341. UINT64 dataSize = sizeof(UINT32)* 2;
  342. for (auto iter = data.begin(); iter != data.end(); ++iter)
  343. {
  344. dataSize += RTTIPlainType<Key>::getDynamicSize(iter->first);
  345. dataSize += RTTIPlainType<Value>::getDynamicSize(iter->second);
  346. }
  347. assert(dataSize <= std::numeric_limits<UINT32>::max());
  348. return (UINT32)dataSize;
  349. }
  350. };
  351. /**
  352. * @brief RTTIPlainType for std::pair.
  353. *
  354. * @see RTTIPlainType
  355. */
  356. template<class A, class B> struct RTTIPlainType<std::pair<A, B>>
  357. {
  358. enum { id = TID_Pair }; enum { hasDynamicSize = 1 };
  359. /**
  360. * @copydoc RTTIPlainType::toMemory
  361. */
  362. static void toMemory(const std::pair<A, B>& data, char* memory)
  363. {
  364. UINT32 size = sizeof(UINT32);
  365. char* memoryStart = memory;
  366. memory += sizeof(UINT32);
  367. UINT32 firstSize = RTTIPlainType<A>::getDynamicSize(data.first);
  368. RTTIPlainType<A>::toMemory(data.first, memory);
  369. memory += firstSize;
  370. size += firstSize;
  371. UINT32 secondSize = RTTIPlainType<B>::getDynamicSize(data.second);
  372. RTTIPlainType<B>::toMemory(data.second, memory);
  373. memory += secondSize;
  374. size += secondSize;
  375. memcpy(memoryStart, &size, sizeof(UINT32));
  376. }
  377. /**
  378. * @copydoc RTTIPlainType::fromMemory
  379. */
  380. static UINT32 fromMemory(std::pair<A, B>& data, char* memory)
  381. {
  382. UINT32 size = 0;
  383. memcpy(&size, memory, sizeof(UINT32));
  384. memory += sizeof(UINT32);
  385. UINT32 firstSize = RTTIPlainType<A>::fromMemory(data.first, memory);
  386. memory += firstSize;
  387. UINT32 secondSize = RTTIPlainType<B>::fromMemory(data.second, memory);
  388. memory += secondSize;
  389. return size;
  390. }
  391. /**
  392. * @copydoc RTTIPlainType::getDynamicSize
  393. */
  394. static UINT32 getDynamicSize(const std::pair<A, B>& data)
  395. {
  396. UINT64 dataSize = sizeof(UINT32);
  397. dataSize += RTTIPlainType<A>::getDynamicSize(data.first);
  398. dataSize += RTTIPlainType<B>::getDynamicSize(data.second);
  399. assert(dataSize <= std::numeric_limits<UINT32>::max());
  400. return (UINT32)dataSize;
  401. }
  402. };
  403. }