Serializer.h 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. // Copyright (C) 2009-2020, 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 : public NonCopyable
  68. {
  69. public:
  70. /// Serialize a class.
  71. /// @param x What to serialize.
  72. /// @param tmpAllocator A temp allocator for some memory needed.
  73. /// @param file The file to populate.
  74. template<typename T>
  75. ANKI_USE_RESULT Error serialize(const T& x, GenericMemoryPoolAllocator<U8> tmpAllocator, File& file)
  76. {
  77. const Error err = serializeInternal(x, tmpAllocator, file);
  78. if(err)
  79. {
  80. ANKI_UTIL_LOGE("There was a serialization error");
  81. }
  82. return err;
  83. }
  84. /// Write a single value. Can't call this directly.
  85. template<typename T>
  86. void doValue(CString varName, PtrSize memberOffset, const T& x)
  87. {
  88. doArray(varName, memberOffset, &x, 1);
  89. }
  90. /// Write an array of complex values. Can't call this directly.
  91. template<typename T, ANKI_ENABLE(!_ANKI_SIMPLE_TYPE)>
  92. void doArray(CString varName, PtrSize memberOffset, const T* arr, PtrSize size)
  93. {
  94. if(!m_err)
  95. {
  96. m_err = doArrayComplexType(arr, size, memberOffset);
  97. }
  98. }
  99. /// Write an array of int or float types. Can't call this directly.
  100. template<typename T, ANKI_ENABLE(_ANKI_SIMPLE_TYPE)>
  101. void doArray(CString varName, PtrSize memberOffset, const T* arr, PtrSize size)
  102. {
  103. // Do nothing, it's already copied
  104. }
  105. /// Write a pointer. Can't call this directly.
  106. template<typename T>
  107. void doPointer(CString varName, PtrSize memberOffset, const T* ptr)
  108. {
  109. doDynamicArray(varName, memberOffset, ptr, (ptr) ? 1 : 0);
  110. }
  111. /// Write a dynamic array of complex types. Can't call this directly.
  112. template<typename T, ANKI_ENABLE(!_ANKI_SIMPLE_TYPE)>
  113. void doDynamicArray(CString varName, PtrSize memberOffset, const T* arr, PtrSize size)
  114. {
  115. if(!m_err)
  116. {
  117. m_err = doDynamicArrayComplexType(arr, size, memberOffset);
  118. }
  119. }
  120. /// Write a dynamic array of int and float values. Can't call this directly.
  121. template<typename T, ANKI_ENABLE(_ANKI_SIMPLE_TYPE)>
  122. void doDynamicArray(CString varName, PtrSize memberOffset, const T* arr, PtrSize size)
  123. {
  124. if(!m_err)
  125. {
  126. m_err = doDynamicArrayBasicType(arr, size * sizeof(T), alignof(T), memberOffset);
  127. }
  128. }
  129. private:
  130. class PointerInfo
  131. {
  132. public:
  133. PtrSize m_filePos; ///< Pointer location inside the file.
  134. PtrSize m_value; ///< Where it points to. It's an offset after the header.
  135. };
  136. File* m_file = nullptr;
  137. PtrSize m_eofPos; ///< A logical end of the file. Used for allocations.
  138. PtrSize m_beginOfDataFilePos; ///< Where the data are located in the file.
  139. GenericMemoryPoolAllocator<U8> m_alloc;
  140. DynamicArray<PointerInfo> m_pointerFilePositions; ///< Array of file positions that contain pointers.
  141. DynamicArray<PtrSize> m_structureFilePos;
  142. Error m_err = Error::NONE;
  143. template<typename T>
  144. ANKI_USE_RESULT Error doArrayComplexType(const T* arr, PtrSize size, PtrSize memberOffset);
  145. template<typename T>
  146. ANKI_USE_RESULT Error doDynamicArrayComplexType(const T* arr, PtrSize size, PtrSize memberOffset);
  147. ANKI_USE_RESULT Error doDynamicArrayBasicType(const void* arr, PtrSize size, U32 alignment, PtrSize memberOffset);
  148. template<typename T>
  149. ANKI_USE_RESULT Error serializeInternal(const T& x, GenericMemoryPoolAllocator<U8> tmpAllocator, File& file);
  150. void check()
  151. {
  152. ANKI_ASSERT(m_file && "Can't call this function");
  153. ANKI_ASSERT(m_file->tell() <= m_eofPos);
  154. }
  155. template<typename T>
  156. static void checkStruct()
  157. {
  158. static_assert(!std::is_polymorphic<T>::value, "Only PODs are supported in this serializer");
  159. static_assert(alignof(T) <= ANKI_SAFE_ALIGNMENT, "Alignments can't exceed ANKI_SAFE_ALIGNMENT");
  160. }
  161. };
  162. /// Deserializes binary files.
  163. class BinaryDeserializer : public NonCopyable
  164. {
  165. public:
  166. /// Serialize a class.
  167. /// @param x The struct to read.
  168. /// @param allocator The allocator to use to allocate the new structures.
  169. /// @param file The file to read from.
  170. template<typename T>
  171. static ANKI_USE_RESULT Error deserialize(T*& x, GenericMemoryPoolAllocator<U8> allocator, File& file);
  172. /// Read a single value. Can't call this directly.
  173. template<typename T>
  174. void doValue(CString varName, PtrSize memberOffset, T& x)
  175. {
  176. // Do nothing
  177. }
  178. /// Read an array. Can't call this directly.
  179. template<typename T>
  180. void doArray(CString varName, PtrSize memberOffset, T* arr, PtrSize size)
  181. {
  182. // Do nothing
  183. }
  184. /// Read a pointer. Can't call this directly.
  185. template<typename T>
  186. void doPointer(CString varName, PtrSize memberOffset, T* ptr)
  187. {
  188. // Do nothing
  189. }
  190. /// Read a dynamic array of complex types. Can't call this directly.
  191. template<typename T>
  192. void doDynamicArray(CString varName, PtrSize memberOffset, T* arr, PtrSize size)
  193. {
  194. // Do nothing
  195. }
  196. };
  197. /// @}
  198. #undef _ANKI_SIMPLE_TYPE
  199. } // end namespace anki
  200. #include <anki/util/Serializer.inl.h>