Serializer.h 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. // Copyright (C) 2009-2021, 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. {
  10. /// @addtogroup util_file
  11. /// @{
  12. #define _ANKI_SIMPLE_TYPE (std::is_integral<T>::value || std::is_floating_point<T>::value || std::is_enum<T>::value)
  13. /// Serialize functor. Used to add serialization code to classes that you can't add a serialize() method.
  14. template<typename T>
  15. class SerializeFunctor
  16. {
  17. public:
  18. template<typename TSerializer>
  19. void operator()(const T& x, TSerializer& serializer)
  20. {
  21. x.serialize(serializer);
  22. }
  23. };
  24. /// Deserialize functor. Used to add deserialization code to classes that you can't add a serialize() method.
  25. template<typename T>
  26. class DeserializeFunctor
  27. {
  28. public:
  29. template<typename TDeserializer>
  30. void operator()(T& x, TDeserializer& deserializer)
  31. {
  32. x.deserialize(deserializer);
  33. }
  34. };
  35. /// Specialization for WeakArray.
  36. template<typename T, typename TSize>
  37. class SerializeFunctor<WeakArray<T, TSize>>
  38. {
  39. public:
  40. template<typename TSerializer>
  41. void operator()(const WeakArray<T, TSize>& x, TSerializer& serializer)
  42. {
  43. const TSize size = x.getSize();
  44. serializer.doDynamicArray("m_array", 0, (x.getSize()) ? &x[0] : nullptr, size);
  45. serializer.doValue("m_size", sizeof(void*), size);
  46. }
  47. };
  48. /// Specialization for WeakArray.
  49. template<typename T, typename TSize>
  50. class DeserializeFunctor<WeakArray<T, TSize>>
  51. {
  52. public:
  53. template<typename TDeserializer>
  54. void operator()(WeakArray<T, TSize>& x, TDeserializer& deserializer)
  55. {
  56. TSize size;
  57. deserializer.doValue("m_size", sizeof(void*), size);
  58. T* arr = nullptr;
  59. if(size > 0)
  60. {
  61. deserializer.doDynamicArray("m_array", 0, arr, size);
  62. }
  63. x = WeakArray<T, TSize>(arr, size);
  64. }
  65. };
  66. /// Serializes to binary files.
  67. class BinarySerializer
  68. {
  69. public:
  70. BinarySerializer() = default;
  71. BinarySerializer(const BinarySerializer&) = delete; // Non-copyable
  72. BinarySerializer& operator=(const BinarySerializer&) = delete; // Non-copyable
  73. /// Serialize a class.
  74. /// @param x What to serialize.
  75. /// @param tmpAllocator A temp allocator for some memory needed.
  76. /// @param file The file to populate.
  77. template<typename T>
  78. ANKI_USE_RESULT Error serialize(const T& x, GenericMemoryPoolAllocator<U8> tmpAllocator, File& file)
  79. {
  80. const Error err = serializeInternal(x, tmpAllocator, file);
  81. if(err)
  82. {
  83. ANKI_UTIL_LOGE("There was a serialization error");
  84. }
  85. return err;
  86. }
  87. /// Write a single value. Can't call this directly.
  88. template<typename T>
  89. void doValue(CString varName, PtrSize memberOffset, const T& x)
  90. {
  91. doArray(varName, memberOffset, &x, 1);
  92. }
  93. /// Write an array of complex values. Can't call this directly.
  94. template<typename T, ANKI_ENABLE(!_ANKI_SIMPLE_TYPE)>
  95. void doArray(CString varName, PtrSize memberOffset, const T* arr, PtrSize size)
  96. {
  97. if(!m_err)
  98. {
  99. m_err = doArrayComplexType(arr, size, memberOffset);
  100. }
  101. }
  102. /// Write an array of int or float types. Can't call this directly.
  103. template<typename T, ANKI_ENABLE(_ANKI_SIMPLE_TYPE)>
  104. void doArray(CString varName, PtrSize memberOffset, const T* arr, PtrSize size)
  105. {
  106. // Do nothing, it's already copied
  107. }
  108. /// Write a pointer. Can't call this directly.
  109. template<typename T>
  110. void doPointer(CString varName, PtrSize memberOffset, const T* ptr)
  111. {
  112. doDynamicArray(varName, memberOffset, ptr, (ptr) ? 1 : 0);
  113. }
  114. /// Write a dynamic array of complex types. Can't call this directly.
  115. template<typename T, ANKI_ENABLE(!_ANKI_SIMPLE_TYPE)>
  116. void doDynamicArray(CString varName, PtrSize memberOffset, const T* arr, PtrSize size)
  117. {
  118. if(!m_err)
  119. {
  120. m_err = doDynamicArrayComplexType(arr, size, memberOffset);
  121. }
  122. }
  123. /// Write a dynamic array of int and float values. Can't call this directly.
  124. template<typename T, ANKI_ENABLE(_ANKI_SIMPLE_TYPE)>
  125. void doDynamicArray(CString varName, PtrSize memberOffset, const T* arr, PtrSize size)
  126. {
  127. if(!m_err)
  128. {
  129. m_err = doDynamicArrayBasicType(arr, size * sizeof(T), alignof(T), memberOffset);
  130. }
  131. }
  132. private:
  133. class PointerInfo
  134. {
  135. public:
  136. PtrSize m_filePos; ///< Pointer location inside the file.
  137. PtrSize m_value; ///< Where it points to. It's an offset after the header.
  138. };
  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. GenericMemoryPoolAllocator<U8> m_alloc;
  143. DynamicArray<PointerInfo> m_pointerFilePositions; ///< Array of file positions that contain pointers.
  144. DynamicArray<PtrSize> m_structureFilePos;
  145. Error m_err = Error::NONE;
  146. template<typename T>
  147. ANKI_USE_RESULT Error doArrayComplexType(const T* arr, PtrSize size, PtrSize memberOffset);
  148. template<typename T>
  149. ANKI_USE_RESULT Error doDynamicArrayComplexType(const T* arr, PtrSize size, PtrSize memberOffset);
  150. ANKI_USE_RESULT Error doDynamicArrayBasicType(const void* arr, PtrSize size, U32 alignment, PtrSize memberOffset);
  151. template<typename T>
  152. ANKI_USE_RESULT Error serializeInternal(const T& x, GenericMemoryPoolAllocator<U8> tmpAllocator, 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 allocator The allocator to use to allocate the new structures.
  175. /// @param file The file to read from.
  176. template<typename T>
  177. static ANKI_USE_RESULT Error deserialize(T*& x, GenericMemoryPoolAllocator<U8> allocator, File& file);
  178. /// Read a single value. Can't call this directly.
  179. template<typename T>
  180. void doValue(CString varName, PtrSize memberOffset, T& x)
  181. {
  182. // Do nothing
  183. }
  184. /// Read an array. Can't call this directly.
  185. template<typename T>
  186. void doArray(CString varName, PtrSize memberOffset, T* arr, PtrSize size)
  187. {
  188. // Do nothing
  189. }
  190. /// Read a pointer. Can't call this directly.
  191. template<typename T>
  192. void doPointer(CString varName, PtrSize memberOffset, 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(CString varName, PtrSize memberOffset, T* arr, PtrSize size)
  199. {
  200. // Do nothing
  201. }
  202. };
  203. /// @}
  204. #undef _ANKI_SIMPLE_TYPE
  205. } // end namespace anki
  206. #include <AnKi/Util/Serializer.inl.h>