Serializer.h 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  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. /// @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 tmpAllocator A temp allocator for some memory needed.
  75. /// @param file The file to populate.
  76. template<typename T>
  77. ANKI_USE_RESULT Error serialize(const T& x, GenericMemoryPoolAllocator<U8> tmpAllocator, File& file)
  78. {
  79. const Error err = serializeInternal(x, tmpAllocator, file);
  80. if(err)
  81. {
  82. ANKI_UTIL_LOGE("There was a serialization error");
  83. }
  84. return err;
  85. }
  86. /// Write a single value. Can't call this directly.
  87. template<typename T>
  88. void doValue(CString varName, PtrSize memberOffset, const T& x)
  89. {
  90. doArray(varName, memberOffset, &x, 1);
  91. }
  92. /// Write an array of complex values. Can't call this directly.
  93. template<typename T, ANKI_ENABLE(!_ANKI_SIMPLE_TYPE)>
  94. void doArray(CString varName, PtrSize memberOffset, const T* arr, PtrSize size)
  95. {
  96. if(!m_err)
  97. {
  98. m_err = doArrayComplexType(arr, size, memberOffset);
  99. }
  100. }
  101. /// Write an array of int or float types. Can't call this directly.
  102. template<typename T, ANKI_ENABLE(_ANKI_SIMPLE_TYPE)>
  103. void doArray(CString varName, PtrSize memberOffset, const T* arr, PtrSize size)
  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, ANKI_ENABLE(!_ANKI_SIMPLE_TYPE)>
  115. void doDynamicArray(CString varName, PtrSize memberOffset, const T* arr, PtrSize size)
  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, ANKI_ENABLE(_ANKI_SIMPLE_TYPE)>
  124. void doDynamicArray(CString varName, PtrSize memberOffset, const T* arr, PtrSize size)
  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. File* m_file = nullptr;
  139. PtrSize m_eofPos; ///< A logical end of the file. Used for allocations.
  140. PtrSize m_beginOfDataFilePos; ///< Where the data are located in the file.
  141. GenericMemoryPoolAllocator<U8> m_alloc;
  142. DynamicArray<PointerInfo> m_pointerFilePositions; ///< Array of file positions that contain pointers.
  143. DynamicArray<PtrSize> m_structureFilePos;
  144. Error m_err = Error::NONE;
  145. template<typename T>
  146. ANKI_USE_RESULT Error doArrayComplexType(const T* arr, PtrSize size, PtrSize memberOffset);
  147. template<typename T>
  148. ANKI_USE_RESULT Error doDynamicArrayComplexType(const T* arr, PtrSize size, PtrSize memberOffset);
  149. ANKI_USE_RESULT Error doDynamicArrayBasicType(const void* arr, PtrSize size, U32 alignment, PtrSize memberOffset);
  150. template<typename T>
  151. ANKI_USE_RESULT Error serializeInternal(const T& x, GenericMemoryPoolAllocator<U8> tmpAllocator, File& file);
  152. void check()
  153. {
  154. ANKI_ASSERT(m_file && "Can't call this function");
  155. ANKI_ASSERT(m_file->tell() <= m_eofPos);
  156. }
  157. template<typename T>
  158. static void checkStruct()
  159. {
  160. static_assert(!std::is_polymorphic<T>::value, "Only PODs are supported in this serializer");
  161. static_assert(alignof(T) <= ANKI_SAFE_ALIGNMENT, "Alignments can't exceed ANKI_SAFE_ALIGNMENT");
  162. }
  163. };
  164. /// Deserializes binary files.
  165. class BinaryDeserializer
  166. {
  167. public:
  168. BinaryDeserializer() = default;
  169. BinaryDeserializer(const BinaryDeserializer&) = delete; // Non-copyable
  170. BinaryDeserializer& operator=(const BinaryDeserializer&) = delete; // Non-copyable
  171. /// Serialize a class.
  172. /// @param x The struct to read.
  173. /// @param allocator The allocator to use to allocate the new structures.
  174. /// @param file The file to read from.
  175. template<typename T>
  176. static ANKI_USE_RESULT Error deserialize(T*& x, GenericMemoryPoolAllocator<U8> allocator, File& file);
  177. /// Read a single value. Can't call this directly.
  178. template<typename T>
  179. void doValue(CString varName, PtrSize memberOffset, T& x)
  180. {
  181. // Do nothing
  182. }
  183. /// Read an array. Can't call this directly.
  184. template<typename T>
  185. void doArray(CString varName, PtrSize memberOffset, T* arr, PtrSize size)
  186. {
  187. // Do nothing
  188. }
  189. /// Read a pointer. Can't call this directly.
  190. template<typename T>
  191. void doPointer(CString varName, PtrSize memberOffset, T* ptr)
  192. {
  193. // Do nothing
  194. }
  195. /// Read a dynamic array of complex types. Can't call this directly.
  196. template<typename T>
  197. void doDynamicArray(CString varName, PtrSize memberOffset, T* arr, PtrSize size)
  198. {
  199. // Do nothing
  200. }
  201. };
  202. /// @}
  203. #undef _ANKI_SIMPLE_TYPE
  204. } // end namespace anki
  205. #include <AnKi/Util/Serializer.inl.h>