BsManagedSerializableDiff.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #pragma once
  4. #include "BsScriptEnginePrerequisites.h"
  5. #include "Reflection/BsIReflectable.h"
  6. namespace bs
  7. {
  8. /** @addtogroup SBansheeEngine
  9. * @{
  10. */
  11. /**
  12. * Handles creation and applying of managed diffs. A diff contains differences between two objects of identical types.
  13. * If the initial state of an object is known the recorded differences can be saved and applied to the original state to
  14. * restore the modified object.
  15. *
  16. * Differences are recorded per primitive field in an object. Complex objects are recursed. Special handling is
  17. * implemented to properly generate diffs for arrays, lists and dictionaries.
  18. *
  19. * All primitive types supported by managed serialization are supported (see ScriptPrimitiveType).
  20. */
  21. class BS_SCR_BE_EXPORT ManagedSerializableDiff : public IReflectable
  22. {
  23. public:
  24. /** A base class for all modifications recorded in a diff. */
  25. struct Modification : IReflectable
  26. {
  27. virtual ~Modification();
  28. /************************************************************************/
  29. /* RTTI */
  30. /************************************************************************/
  31. public:
  32. friend class ModificationRTTI;
  33. static RTTITypeBase* getRTTIStatic();
  34. RTTITypeBase* getRTTI() const override;
  35. };
  36. /**
  37. * Contains a modification of a specific field in an object along with information about the field and its parent
  38. * object.
  39. */
  40. struct ModifiedField : IReflectable
  41. {
  42. ModifiedField() { }
  43. ModifiedField(const SPtr<ManagedSerializableTypeInfo>& parentType,
  44. const SPtr<ManagedSerializableMemberInfo>& fieldType, const SPtr<Modification>& modification);
  45. SPtr<ManagedSerializableTypeInfo> parentType; /**< Type of the parent object the field belongs to. */
  46. SPtr<ManagedSerializableMemberInfo> fieldType; /**< Data type of the field. */
  47. SPtr<Modification> modification; /**< Recorded modification(s) on the field. */
  48. /************************************************************************/
  49. /* RTTI */
  50. /************************************************************************/
  51. public:
  52. friend class ModifiedFieldRTTI;
  53. static RTTITypeBase* getRTTIStatic();
  54. RTTITypeBase* getRTTI() const override;
  55. };
  56. /** Represents a single modified array or list entry. */
  57. struct ModifiedArrayEntry : IReflectable
  58. {
  59. ModifiedArrayEntry() { }
  60. ModifiedArrayEntry(UINT32 idx, const SPtr<Modification>& modification);
  61. UINT32 idx; /**< Index of the array/list entry that is modified. */
  62. SPtr<Modification> modification; /**< Recorded modification(s) on the entry. */
  63. /************************************************************************/
  64. /* RTTI */
  65. /************************************************************************/
  66. public:
  67. friend class ModifiedArrayEntryRTTI;
  68. static RTTITypeBase* getRTTIStatic();
  69. RTTITypeBase* getRTTI() const override;
  70. };
  71. /** Represents a single modified dictionary entry. */
  72. struct ModifiedDictionaryEntry : IReflectable
  73. {
  74. ModifiedDictionaryEntry() { }
  75. ModifiedDictionaryEntry(const SPtr<ManagedSerializableFieldData>& key, const SPtr<Modification>& modification);
  76. SPtr<ManagedSerializableFieldData> key; /**< Serialized value of the key for the modified entry. */
  77. SPtr<Modification> modification; /**< Recorded modification(s) on the dictionary entry value. */
  78. /************************************************************************/
  79. /* RTTI */
  80. /************************************************************************/
  81. public:
  82. friend class ModifiedArrayEntryRTTI;
  83. static RTTITypeBase* getRTTIStatic();
  84. RTTITypeBase* getRTTI() const override;
  85. };
  86. /**
  87. * Contains data about all modifications in a single complex object (aside from arrays, list, dictionaries which are
  88. * handled specially).
  89. */
  90. struct ModifiedObject : Modification
  91. {
  92. static SPtr<ModifiedObject> create();
  93. Vector<ModifiedField> entries; /**< A list of entries containing each modified field in the object. */
  94. /************************************************************************/
  95. /* RTTI */
  96. /************************************************************************/
  97. public:
  98. friend class ModifiedObjectRTTI;
  99. static RTTITypeBase* getRTTIStatic();
  100. RTTITypeBase* getRTTI() const override;
  101. };
  102. /** Contains data about all modifications in an array or a list. */
  103. struct ModifiedArray : Modification
  104. {
  105. static SPtr<ModifiedArray> create();
  106. Vector<ModifiedArrayEntry> entries; /**< A list of all modified array/list entries along with their indices. */
  107. Vector<UINT32> origSizes; /**< Original size of the array/list (one size per dimension). */
  108. Vector<UINT32> newSizes; /**< New size of the array/list (one size per dimension). */
  109. /************************************************************************/
  110. /* RTTI */
  111. /************************************************************************/
  112. public:
  113. friend class ModifiedArrayRTTI;
  114. static RTTITypeBase* getRTTIStatic();
  115. RTTITypeBase* getRTTI() const override;
  116. };
  117. /** Contains data about all modifications in a dictionary. */
  118. struct ModifiedDictionary : Modification
  119. {
  120. static SPtr<ModifiedDictionary> create();
  121. /** A list of modified entries in the dictionary. */
  122. Vector<ModifiedDictionaryEntry> entries;
  123. /** A list of keys for entries that were removed from the dictionary. */
  124. Vector<SPtr<ManagedSerializableFieldData>> removed;
  125. /************************************************************************/
  126. /* RTTI */
  127. /************************************************************************/
  128. public:
  129. friend class ModifiedDictionaryRTTI;
  130. static RTTITypeBase* getRTTIStatic();
  131. RTTITypeBase* getRTTI() const override;
  132. };
  133. /** Contains data about modification of a primitive field (field's new value). */
  134. struct ModifiedEntry : Modification
  135. {
  136. ModifiedEntry() { }
  137. ModifiedEntry(const SPtr<ManagedSerializableFieldData>& value);
  138. static SPtr<ModifiedEntry> create(const SPtr<ManagedSerializableFieldData>& value);
  139. SPtr<ManagedSerializableFieldData> value;
  140. /************************************************************************/
  141. /* RTTI */
  142. /************************************************************************/
  143. public:
  144. friend class ModifiedEntryRTTI;
  145. static RTTITypeBase* getRTTIStatic();
  146. RTTITypeBase* getRTTI() const override;
  147. };
  148. public:
  149. ManagedSerializableDiff();
  150. ~ManagedSerializableDiff();
  151. /**
  152. * Generates a new managed diff object by comparing two objects of the same type. Callers must ensure both objects
  153. * are not null and of identical types.
  154. *
  155. * @param[in] oldObj Original object. This is the object you can apply the diff to to convert it to @p newObj.
  156. * @param[in] newObj New modified object. Any values in this object that differ from the original object will be
  157. * recorded in the diff.
  158. * @return Returns null if objects are identical.
  159. */
  160. static SPtr<ManagedSerializableDiff> create(const SPtr<ManagedSerializableObject>& oldObj, const SPtr<ManagedSerializableObject>& newObj);
  161. /**
  162. * Applies the diff data stored in this object to the specified object, modifying all fields in the object to
  163. * correspond to the stored diff data.
  164. */
  165. void apply(const SPtr<ManagedSerializableObject>& obj);
  166. private:
  167. /**
  168. * Recursively generates a diff between all fields of the specified objects. Returns null if objects are identical.
  169. */
  170. SPtr<ModifiedObject> generateDiff(const SPtr<ManagedSerializableObject>& oldObj, const SPtr<ManagedSerializableObject>& newObj);
  171. /**
  172. * Generates a diff between two fields. Fields can be of any type and the system will generate the diff
  173. * appropriately. Diff is generated recursively on all complex objects as well. Returns null if fields contain
  174. * identical data.
  175. */
  176. SPtr<Modification> generateDiff(const SPtr<ManagedSerializableFieldData>& oldData, const SPtr<ManagedSerializableFieldData>& newData,
  177. UINT32 fieldTypeId);
  178. /**
  179. * Applies an object modification to a managed object. Modifications are applied recursively.
  180. *
  181. * @param[in] mod Object modification to apply.
  182. * @param[in] obj Object to apply the modification to.
  183. * @return New field data in the case modification needed the object to be re-created instead of just modified.
  184. */
  185. SPtr<ManagedSerializableFieldData> applyDiff(const SPtr<ModifiedObject>& mod, const SPtr<ManagedSerializableObject>& obj);
  186. /**
  187. * Applies an array modification to a managed array. Modifications are applied recursively.
  188. *
  189. * @param[in] mod Array modification to apply.
  190. * @param[in] obj Array to apply the modification to.
  191. * @return New field data in the case modification needed the array to be re-created instead of just modified.
  192. */
  193. SPtr<ManagedSerializableFieldData> applyDiff(const SPtr<ModifiedArray>& mod, const SPtr<ManagedSerializableArray>& obj);
  194. /**
  195. * Applies an list modification to a managed list. Modifications are applied recursively.
  196. *
  197. * @param[in] mod List modification to apply.
  198. * @param[in] obj List to apply the modification to.
  199. * @return New field data in the case modification needed the list to be re-created instead of just modified.
  200. */
  201. SPtr<ManagedSerializableFieldData> applyDiff(const SPtr<ModifiedArray>& mod, const SPtr<ManagedSerializableList>& obj);
  202. /**
  203. * Applies an dictionary modification to a managed dictionary. Modifications are applied recursively.
  204. *
  205. * @param[in] mod Dictionary modification to apply.
  206. * @param[in] obj Dictionary to apply the modification to.
  207. * @return New field data in the case modification needed the dictionary to be re-created instead of just modified.
  208. */
  209. SPtr<ManagedSerializableFieldData> applyDiff(const SPtr<ModifiedDictionary>& mod, const SPtr<ManagedSerializableDictionary>& obj);
  210. /**
  211. * Applies a modification to a single field. Field type is determined and the modification is applied to the
  212. * specific field type as needed. Modifications are applied recursively.
  213. *
  214. * @param[in] mod Modification to apply.
  215. * @param[in] fieldType Type of the field we're applying the modification to.
  216. * @param[in] origData Original data of the field.
  217. * @return New field data in the case modification needed the field data to be re-created instead
  218. * of just modified.
  219. */
  220. SPtr<ManagedSerializableFieldData> applyDiff(const SPtr<Modification>& mod, const SPtr<ManagedSerializableTypeInfo>& fieldType,
  221. const SPtr<ManagedSerializableFieldData>& origData);
  222. SPtr<ModifiedObject> mModificationRoot;
  223. /************************************************************************/
  224. /* RTTI */
  225. /************************************************************************/
  226. public:
  227. friend class ManagedSerializableDiffRTTI;
  228. static RTTITypeBase* getRTTIStatic();
  229. RTTITypeBase* getRTTI() const override;
  230. };
  231. /** @} */
  232. }