Serializer.h 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. // Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #include <AnKi/Util/File.h>
  6. #include <AnKi/Util/WeakArray.h>
  7. #pragma once
  8. namespace anki {
  9. /// @addtogroup util_file
  10. /// @{
  11. #define _ANKI_SIMPLE_TYPE (std::is_integral<T>::value || std::is_floating_point<T>::value || std::is_enum<T>::value)
  12. /// Serialize functor. Used to add serialization code to classes that you can't add a serialize() method.
  13. template<typename T>
  14. class SerializeFunctor
  15. {
  16. public:
  17. template<typename TSerializer>
  18. void operator()(const T& x, TSerializer& serializer)
  19. {
  20. x.serialize(serializer);
  21. }
  22. };
  23. /// Deserialize functor. Used to add deserialization code to classes that you can't add a serialize() method.
  24. template<typename T>
  25. class DeserializeFunctor
  26. {
  27. public:
  28. template<typename TDeserializer>
  29. void operator()(T& x, TDeserializer& deserializer)
  30. {
  31. x.deserialize(deserializer);
  32. }
  33. };
  34. /// Specialization for WeakArray.
  35. template<typename T, typename TSize>
  36. class SerializeFunctor<WeakArray<T, TSize>>
  37. {
  38. public:
  39. template<typename TSerializer>
  40. void operator()(const WeakArray<T, TSize>& x, TSerializer& serializer)
  41. {
  42. const TSize size = x.getSize();
  43. serializer.doDynamicArray("m_array", 0, (x.getSize()) ? &x[0] : nullptr, size);
  44. serializer.doValue("m_size", sizeof(void*), size);
  45. }
  46. };
  47. /// Specialization for WeakArray.
  48. template<typename T, typename TSize>
  49. class DeserializeFunctor<WeakArray<T, TSize>>
  50. {
  51. public:
  52. template<typename TDeserializer>
  53. void operator()(WeakArray<T, TSize>& x, TDeserializer& deserializer)
  54. {
  55. TSize size;
  56. deserializer.doValue("m_size", sizeof(void*), size);
  57. T* arr = nullptr;
  58. if(size > 0)
  59. {
  60. deserializer.doDynamicArray("m_array", 0, arr, size);
  61. }
  62. x = WeakArray<T, TSize>(arr, size);
  63. }
  64. };
  65. /// Serializes to binary files.
  66. class BinarySerializer
  67. {
  68. public:
  69. BinarySerializer() = default;
  70. BinarySerializer(const BinarySerializer&) = delete; // Non-copyable
  71. BinarySerializer& operator=(const BinarySerializer&) = delete; // Non-copyable
  72. /// Serialize a class.
  73. /// @param x What to serialize.
  74. /// @param file The file to populate.
  75. template<typename T>
  76. Error serialize(const T& x, BaseMemoryPool& tmpPool, File& file)
  77. {
  78. const Error err = serializeInternal(x, tmpPool, file);
  79. if(err)
  80. {
  81. ANKI_UTIL_LOGE("There was a serialization error");
  82. }
  83. return err;
  84. }
  85. /// Write a single value. Can't call this directly.
  86. template<typename T>
  87. void doValue(CString varName, PtrSize memberOffset, const T& x)
  88. {
  89. doArray(varName, memberOffset, &x, 1);
  90. }
  91. /// Write an array of complex values. Can't call this directly.
  92. template<typename T>
  93. void doArray([[maybe_unused]] CString varName, PtrSize memberOffset, const T* arr, PtrSize size) requires(!_ANKI_SIMPLE_TYPE)
  94. {
  95. if(!m_err)
  96. {
  97. m_err = doArrayComplexType(arr, size, memberOffset);
  98. }
  99. }
  100. /// Write an array of int or float types. Can't call this directly.
  101. template<typename T>
  102. void doArray([[maybe_unused]] CString varName, [[maybe_unused]] PtrSize memberOffset, [[maybe_unused]] const T* arr,
  103. [[maybe_unused]] PtrSize size) requires(_ANKI_SIMPLE_TYPE)
  104. {
  105. // Do nothing, it's already copied
  106. }
  107. /// Write a pointer. Can't call this directly.
  108. template<typename T>
  109. void doPointer(CString varName, PtrSize memberOffset, const T* ptr)
  110. {
  111. doDynamicArray(varName, memberOffset, ptr, (ptr) ? 1 : 0);
  112. }
  113. /// Write a dynamic array of complex types. Can't call this directly.
  114. template<typename T>
  115. void doDynamicArray([[maybe_unused]] CString varName, PtrSize memberOffset, const T* arr, PtrSize size) requires(!_ANKI_SIMPLE_TYPE)
  116. {
  117. if(!m_err)
  118. {
  119. m_err = doDynamicArrayComplexType(arr, size, memberOffset);
  120. }
  121. }
  122. /// Write a dynamic array of int and float values. Can't call this directly.
  123. template<typename T>
  124. void doDynamicArray([[maybe_unused]] CString varName, PtrSize memberOffset, const T* arr, PtrSize size) requires(_ANKI_SIMPLE_TYPE)
  125. {
  126. if(!m_err)
  127. {
  128. m_err = doDynamicArrayBasicType(arr, size * sizeof(T), alignof(T), memberOffset);
  129. }
  130. }
  131. private:
  132. class PointerInfo
  133. {
  134. public:
  135. PtrSize m_filePos; ///< Pointer location inside the file.
  136. PtrSize m_value; ///< Where it points to. It's an offset after the header.
  137. };
  138. using Pool = MemoryPoolPtrWrapper<BaseMemoryPool>;
  139. File* m_file = nullptr;
  140. PtrSize m_eofPos; ///< A logical end of the file. Used for allocations.
  141. PtrSize m_beginOfDataFilePos; ///< Where the data are located in the file.
  142. Pool m_pool;
  143. DynamicArray<PointerInfo, Pool> m_pointerFilePositions; ///< Array of file positions that contain pointers.
  144. DynamicArray<PtrSize, Pool> m_structureFilePos;
  145. Error m_err = Error::kNone;
  146. template<typename T>
  147. Error doArrayComplexType(const T* arr, PtrSize size, PtrSize memberOffset);
  148. template<typename T>
  149. Error doDynamicArrayComplexType(const T* arr, PtrSize size, PtrSize memberOffset);
  150. Error doDynamicArrayBasicType(const void* arr, PtrSize size, U32 alignment, PtrSize memberOffset);
  151. template<typename T>
  152. Error serializeInternal(const T& x, BaseMemoryPool& tmpPool, File& file);
  153. void check()
  154. {
  155. ANKI_ASSERT(m_file && "Can't call this function");
  156. ANKI_ASSERT(m_file->tell() <= m_eofPos);
  157. }
  158. template<typename T>
  159. static void checkStruct()
  160. {
  161. static_assert(!std::is_polymorphic<T>::value, "Only PODs are supported in this serializer");
  162. static_assert(alignof(T) <= ANKI_SAFE_ALIGNMENT, "Alignments can't exceed ANKI_SAFE_ALIGNMENT");
  163. }
  164. };
  165. /// Deserializes binary files.
  166. class BinaryDeserializer
  167. {
  168. public:
  169. BinaryDeserializer() = default;
  170. BinaryDeserializer(const BinaryDeserializer&) = delete; // Non-copyable
  171. BinaryDeserializer& operator=(const BinaryDeserializer&) = delete; // Non-copyable
  172. /// Serialize a class.
  173. /// @param x The struct to read.
  174. /// @param pool The memory pool to use to allocate the new structures.
  175. /// @param file The file to read from.
  176. template<typename T, typename TFile>
  177. static Error deserialize(T*& x, BaseMemoryPool& pool, TFile& file);
  178. /// Read a single value. Can't call this directly.
  179. template<typename T>
  180. void doValue([[maybe_unused]] CString varName, [[maybe_unused]] PtrSize memberOffset, [[maybe_unused]] T& x)
  181. {
  182. // Do nothing
  183. }
  184. /// Read an array. Can't call this directly.
  185. template<typename T>
  186. void doArray([[maybe_unused]] CString varName, [[maybe_unused]] PtrSize memberOffset, [[maybe_unused]] T* arr, [[maybe_unused]] PtrSize size)
  187. {
  188. // Do nothing
  189. }
  190. /// Read a pointer. Can't call this directly.
  191. template<typename T>
  192. void doPointer([[maybe_unused]] CString varName, [[maybe_unused]] PtrSize memberOffset, [[maybe_unused]] T* ptr)
  193. {
  194. // Do nothing
  195. }
  196. /// Read a dynamic array of complex types. Can't call this directly.
  197. template<typename T>
  198. void doDynamicArray([[maybe_unused]] CString varName, [[maybe_unused]] PtrSize memberOffset, [[maybe_unused]] T* arr,
  199. [[maybe_unused]] PtrSize size)
  200. {
  201. // Do nothing
  202. }
  203. };
  204. /// @}
  205. #undef _ANKI_SIMPLE_TYPE
  206. } // end namespace anki
  207. #include <AnKi/Util/Serializer.inl.h>