SerializableObject.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. // SPDX-FileCopyrightText: 2021 Jorrit Rouwe
  2. // SPDX-License-Identifier: MIT
  3. #pragma once
  4. #include <ObjectStream/SerializableAttribute.h>
  5. namespace JPH {
  6. //////////////////////////////////////////////////////////////////////////////////////////
  7. // Helper macros
  8. //////////////////////////////////////////////////////////////////////////////////////////
  9. // JPH_DECLARE_SERIALIZATION_FUNCTIONS
  10. #define JPH_DECLARE_SERIALIZATION_FUNCTIONS(prefix, class_name) \
  11. prefix bool OSReadData(ObjectStreamIn &ioStream, class_name &inInstance); \
  12. prefix bool OSReadData(ObjectStreamIn &ioStream, class_name *&inPointer); \
  13. prefix bool OSIsType(class_name *inNull, int inArrayDepth, ObjectStream::EDataType inDataType, const char *inClassName); \
  14. prefix bool OSIsType(class_name **inNull, int inArrayDepth, ObjectStream::EDataType inDataType, const char *inClassName); \
  15. prefix void OSWriteData(ObjectStreamOut &ioStream, const class_name &inInstance); \
  16. prefix void OSWriteData(ObjectStreamOut &ioStream, class_name *const &inPointer); \
  17. prefix void OSWriteDataType(ObjectStreamOut &ioStream, class_name *inNull); \
  18. prefix void OSWriteDataType(ObjectStreamOut &ioStream, class_name **inNull); \
  19. prefix void OSVisitCompounds(const class_name &inObject, const CompoundVisitor &inVisitor); \
  20. prefix void OSVisitCompounds(const class_name *inObject, const CompoundVisitor &inVisitor);
  21. // JPH_IMPLEMENT_SERIALIZATION_FUNCTIONS
  22. #define JPH_IMPLEMENT_SERIALIZATION_FUNCTIONS(class_name) \
  23. bool OSReadData(ObjectStreamIn &ioStream, class_name &inInstance) \
  24. { \
  25. return ioStream.ReadClassData(#class_name, (void *)&inInstance); \
  26. } \
  27. bool OSReadData(ObjectStreamIn &ioStream, class_name *&inPointer) \
  28. { \
  29. return ioStream.ReadPointerData(JPH_RTTI(class_name), (void **)&inPointer); \
  30. } \
  31. bool OSIsType(class_name *inNull, int inArrayDepth, ObjectStream::EDataType inDataType, const char *inClassName) \
  32. { \
  33. return inArrayDepth == 0 && inDataType == ObjectStream::EDataType::Instance && strcmp(inClassName, #class_name) == 0; \
  34. } \
  35. bool OSIsType(class_name **inNull, int inArrayDepth, ObjectStream::EDataType inDataType, const char *inClassName) \
  36. { \
  37. return inArrayDepth == 0 && inDataType == ObjectStream::EDataType::Pointer && strcmp(inClassName, #class_name) == 0; \
  38. } \
  39. void OSWriteData(ObjectStreamOut &ioStream, const class_name &inInstance) \
  40. { \
  41. ioStream.WriteClassData(JPH_RTTI(class_name), (void *)&inInstance); \
  42. } \
  43. void OSWriteData(ObjectStreamOut &ioStream, class_name *const &inPointer) \
  44. { \
  45. if (inPointer) \
  46. ioStream.WritePointerData(GetRTTI(inPointer), (void *)inPointer); \
  47. else \
  48. ioStream.WritePointerData(nullptr, nullptr); \
  49. } \
  50. void OSWriteDataType(ObjectStreamOut &ioStream, class_name *inNull) \
  51. { \
  52. ioStream.WriteDataType(ObjectStream::EDataType::Instance); \
  53. ioStream.WriteName(#class_name); \
  54. } \
  55. void OSWriteDataType(ObjectStreamOut &ioStream, class_name **inNull) \
  56. { \
  57. ioStream.WriteDataType(ObjectStream::EDataType::Pointer); \
  58. ioStream.WriteName(#class_name); \
  59. } \
  60. void OSVisitCompounds(const class_name &inObject, const CompoundVisitor &inVisitor) \
  61. { \
  62. OSVisitCompounds(&inObject, JPH_RTTI(class_name), inVisitor); \
  63. } \
  64. void OSVisitCompounds(const class_name *inObject, const CompoundVisitor &inVisitor) \
  65. { \
  66. if (inObject != nullptr) \
  67. OSVisitCompounds(inObject, GetRTTI(inObject), inVisitor); \
  68. }
  69. //////////////////////////////////////////////////////////////////////////////////////////
  70. // Use these macros on non-virtual objects to make them serializable
  71. //////////////////////////////////////////////////////////////////////////////////////////
  72. // JPH_DECLARE_SERIALIZABLE_NON_VIRTUAL
  73. #define JPH_DECLARE_SERIALIZABLE_NON_VIRTUAL(class_name) \
  74. public: \
  75. JPH_DECLARE_RTTI_NON_VIRTUAL(class_name) \
  76. JPH_DECLARE_SERIALIZATION_FUNCTIONS(friend, class_name) \
  77. // JPH_IMPLEMENT_SERIALIZABLE_NON_VIRTUAL
  78. #define JPH_IMPLEMENT_SERIALIZABLE_NON_VIRTUAL(class_name) \
  79. JPH_IMPLEMENT_SERIALIZATION_FUNCTIONS(class_name) \
  80. JPH_IMPLEMENT_RTTI_NON_VIRTUAL(class_name) \
  81. //////////////////////////////////////////////////////////////////////////////////////////
  82. // Same as above, but when you cannot insert the declaration in the class itself
  83. //////////////////////////////////////////////////////////////////////////////////////////
  84. // JPH_DECLARE_SERIALIZABLE_OUTSIDE_CLASS
  85. #define JPH_DECLARE_SERIALIZABLE_OUTSIDE_CLASS(class_name) \
  86. JPH_DECLARE_RTTI_OUTSIDE_CLASS(class_name) \
  87. JPH_DECLARE_SERIALIZATION_FUNCTIONS(extern, class_name) \
  88. // JPH_IMPLEMENT_SERIALIZABLE_OUTSIDE_CLASS
  89. #define JPH_IMPLEMENT_SERIALIZABLE_OUTSIDE_CLASS(class_name) \
  90. JPH_IMPLEMENT_SERIALIZATION_FUNCTIONS(class_name) \
  91. JPH_IMPLEMENT_RTTI_OUTSIDE_CLASS(class_name) \
  92. //////////////////////////////////////////////////////////////////////////////////////////
  93. // Same as above, but for classes that have virtual functions
  94. //////////////////////////////////////////////////////////////////////////////////////////
  95. // JPH_DECLARE_SERIALIZABLE_VIRTUAL - Use for concrete, non-base classes
  96. #define JPH_DECLARE_SERIALIZABLE_VIRTUAL(class_name) \
  97. public: \
  98. JPH_DECLARE_RTTI_VIRTUAL(class_name) \
  99. JPH_DECLARE_SERIALIZATION_FUNCTIONS(friend, class_name) \
  100. // JPH_IMPLEMENT_SERIALIZABLE_VIRTUAL
  101. #define JPH_IMPLEMENT_SERIALIZABLE_VIRTUAL(class_name) \
  102. JPH_IMPLEMENT_SERIALIZATION_FUNCTIONS(class_name) \
  103. JPH_IMPLEMENT_RTTI_VIRTUAL(class_name) \
  104. // JPH_DECLARE_SERIALIZABLE_ABSTRACT - Use for abstract, non-base classes
  105. #define JPH_DECLARE_SERIALIZABLE_ABSTRACT(class_name) \
  106. public: \
  107. JPH_DECLARE_RTTI_ABSTRACT(class_name) \
  108. JPH_DECLARE_SERIALIZATION_FUNCTIONS(friend, class_name) \
  109. // JPH_IMPLEMENT_SERIALIZABLE_ABSTRACT
  110. #define JPH_IMPLEMENT_SERIALIZABLE_ABSTRACT(class_name) \
  111. JPH_IMPLEMENT_SERIALIZATION_FUNCTIONS(class_name) \
  112. JPH_IMPLEMENT_RTTI_ABSTRACT(class_name) \
  113. // JPH_DECLARE_SERIALIZABLE_VIRTUAL_BASE - Use for concrete base classes
  114. #define JPH_DECLARE_SERIALIZABLE_VIRTUAL_BASE(class_name) \
  115. public: \
  116. JPH_DECLARE_RTTI_VIRTUAL_BASE(class_name) \
  117. JPH_DECLARE_SERIALIZATION_FUNCTIONS(friend, class_name) \
  118. // JPH_IMPLEMENT_SERIALIZABLE_VIRTUAL_BASE
  119. #define JPH_IMPLEMENT_SERIALIZABLE_VIRTUAL_BASE(class_name) \
  120. JPH_IMPLEMENT_SERIALIZATION_FUNCTIONS(class_name) \
  121. JPH_IMPLEMENT_RTTI_VIRTUAL_BASE(class_name) \
  122. // JPH_DECLARE_SERIALIZABLE_ABSTRACT_BASE - Use for abstract base class
  123. #define JPH_DECLARE_SERIALIZABLE_ABSTRACT_BASE(class_name) \
  124. public: \
  125. JPH_DECLARE_RTTI_ABSTRACT_BASE(class_name) \
  126. JPH_DECLARE_SERIALIZATION_FUNCTIONS(friend, class_name) \
  127. // JPH_IMPLEMENT_SERIALIZABLE_ABSTRACT_BASE
  128. #define JPH_IMPLEMENT_SERIALIZABLE_ABSTRACT_BASE(class_name) \
  129. JPH_IMPLEMENT_SERIALIZATION_FUNCTIONS(class_name) \
  130. JPH_IMPLEMENT_RTTI_ABSTRACT_BASE(class_name) \
  131. //////////////////////////////////////////////////////////////////////////////////////////
  132. // OSVisitCompounds
  133. //
  134. // Allows recursively visiting an object and all of its children depth first
  135. //////////////////////////////////////////////////////////////////////////////////////////
  136. /// Basic visitor that recurses to all attributes
  137. void OSVisitCompounds(const void *inObject, const RTTI *inRTTI, const CompoundVisitor &inVisitor);
  138. // Dummy implementation for OSVisitCompounds for all primitive types
  139. #define JPH_DECLARE_PRIMITIVE(name) \
  140. inline void OSVisitCompounds(const name &inObject, const CompoundVisitor &inVisitor) { }
  141. // This file uses the JPH_DECLARE_PRIMITIVE macro to define all types
  142. #include <ObjectStream/ObjectStreamTypes.h>
  143. /// Define visitor templates
  144. template <class T>
  145. void OSVisitCompounds(const Ref<T> &inObject, const CompoundVisitor &inVisitor)
  146. {
  147. if (inObject != nullptr)
  148. OSVisitCompounds(inObject.GetPtr(), inVisitor);
  149. }
  150. template <class T>
  151. void OSVisitCompounds(const RefConst<T> &inObject, const CompoundVisitor &inVisitor)
  152. {
  153. if (inObject != nullptr)
  154. OSVisitCompounds(inObject.GetPtr(), inVisitor);
  155. }
  156. template <class T>
  157. void OSVisitCompounds(const vector<T> &inObject, const CompoundVisitor &inVisitor)
  158. {
  159. for (const T &v : inObject)
  160. OSVisitCompounds(v, inVisitor);
  161. }
  162. template <class T, uint N>
  163. void OSVisitCompounds(const StaticArray<T, N> &inObject, const CompoundVisitor &inVisitor)
  164. {
  165. for (const T &v : inObject)
  166. OSVisitCompounds(v, inVisitor);
  167. }
  168. template <class T, uint N>
  169. void OSVisitCompounds(const T (&inObject)[N], const CompoundVisitor &inVisitor)
  170. {
  171. for (const T &v : inObject)
  172. OSVisitCompounds(v, inVisitor);
  173. }
  174. /// Classes must be derived from SerializableObject if you want to be able to save pointers or
  175. /// reference counting pointers to objects of this or derived classes. The type will automatically
  176. /// be determined during serialization and upon deserialization it will be restored correctly.
  177. class SerializableObject
  178. {
  179. JPH_DECLARE_SERIALIZABLE_ABSTRACT_BASE(SerializableObject)
  180. public:
  181. /// Constructor
  182. virtual ~SerializableObject() = default;
  183. /// Callback given when object has been loaded from an object stream
  184. /// This is called when all links have been resolved. Objects that this object point to have already received their OnLoaded callback.
  185. virtual void OnLoaded() { }
  186. };
  187. } // JPH