BsBinaryDiff.h 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #pragma once
  4. #include "Prerequisites/BsPrerequisitesUtil.h"
  5. namespace bs
  6. {
  7. /** @addtogroup Internal-Utility
  8. * @{
  9. */
  10. /** @addtogroup Serialization-Internal
  11. * @{
  12. */
  13. /**
  14. * Represents an interface RTTI objects need to implement if they want to provide custom "diff" generation and applying.
  15. */
  16. class BS_UTILITY_EXPORT IDiff
  17. {
  18. public:
  19. virtual ~IDiff() { }
  20. /**
  21. * Generates per-field differences between the provided original and new object. Any field or array entry that is
  22. * different in the new object compared to the original will be output in the resulting object, with a full
  23. * hierarchy of that field.
  24. *
  25. * Will return null if there is no difference.
  26. */
  27. SPtr<SerializedObject> generateDiff(const SPtr<SerializedObject>& orgObj, const SPtr<SerializedObject>& newObj);
  28. /**
  29. * Applies a previously generated per-field differences to the provided object. This will essentially transform the
  30. * original object the differences were generated for into the modified version.
  31. */
  32. void applyDiff(const SPtr<IReflectable>& object, const SPtr<SerializedObject>& diff);
  33. protected:
  34. typedef UnorderedMap<SPtr<SerializedObject>, SPtr<SerializedObject>> ObjectMap;
  35. typedef UnorderedMap<SPtr<SerializedObject>, SPtr<IReflectable>> DiffObjectMap;
  36. /** Types of commands that are used when applying difference field values. */
  37. enum DiffCommandType
  38. {
  39. Diff_Plain = 0x01,
  40. Diff_Reflectable = 0x02,
  41. Diff_ReflectablePtr = 0x03,
  42. Diff_DataBlock = 0x04,
  43. Diff_ArraySize = 0x05,
  44. Diff_ObjectStart = 0x06,
  45. Diff_ObjectEnd = 0x07,
  46. Diff_ArrayFlag = 0x10
  47. };
  48. /**
  49. * A command that is used for delaying writing to an object, it contains all necessary information for setting RTTI
  50. * field values on an object.
  51. */
  52. struct DiffCommand
  53. {
  54. RTTIField* field;
  55. UINT32 type;
  56. SPtr<IReflectable> object;
  57. UINT8* value;
  58. SPtr<DataStream> streamValue;
  59. UINT32 size;
  60. union
  61. {
  62. UINT32 arrayIdx;
  63. UINT32 arraySize;
  64. };
  65. };
  66. /**
  67. * Recursive version of generateDiff(const SPtr<SerializedObject>&, const SPtr<SerializedObject>&).
  68. *
  69. * @see generateDiff(const SPtr<SerializedObject>&, const SPtr<SerializedObject>&)
  70. */
  71. virtual SPtr<SerializedObject> generateDiff(const SPtr<SerializedObject>& orgObj, const SPtr<SerializedObject>& newObj, ObjectMap& objectMap) = 0;
  72. /**
  73. * Generates a difference between data of a specific field type indiscriminately of the specific field type.
  74. *
  75. * @see generateDiff(const SPtr<SerializedObject>&, const SPtr<SerializedObject>&)
  76. */
  77. SPtr<SerializedInstance> generateDiff(RTTITypeBase* rtti, UINT32 fieldType, const SPtr<SerializedInstance>& orgData,
  78. const SPtr<SerializedInstance>& newData, ObjectMap& objectMap);
  79. /**
  80. * Recursive version of applyDiff(const SPtr<IReflectable>& object, const SPtr<SerializedObject>& diff). Outputs a
  81. * set of commands that then must be executed in order to actually apply the difference to the provided object.
  82. *
  83. * @see applyDiff(const SPtr<IReflectable>& object, const SPtr<SerializedObject>& diff)
  84. */
  85. virtual void applyDiff(const SPtr<IReflectable>& object, const SPtr<SerializedObject>& diff, DiffObjectMap& objectMap, Vector<DiffCommand>& diffCommands) = 0;
  86. /**
  87. * Applies diff according to the diff handler retrieved from the provided RTTI object.
  88. *
  89. * @see applyDiff(const SPtr<IReflectable>& object, const SPtr<SerializedObject>& diff)
  90. */
  91. void applyDiff(RTTITypeBase* rtti, const SPtr<IReflectable>& object, const SPtr<SerializedObject>& diff, DiffObjectMap& objectMap, Vector<DiffCommand>& diffCommands);
  92. };
  93. /**
  94. * Generates and applies "diffs". Diffs contain per-field differences between an original and new object. These
  95. * differences can be saved and then applied to an original object to transform it to the new version.
  96. *
  97. * @note Objects must be in intermediate serialized format generated by BinarySerializer.
  98. */
  99. class BS_UTILITY_EXPORT BinaryDiff : public IDiff
  100. {
  101. private:
  102. /** @copydoc IDiff::generateDiff(const SPtr<SerializedObject>&, const SPtr<SerializedObject>&, ObjectMap&) */
  103. SPtr<SerializedObject> generateDiff(const SPtr<SerializedObject>& orgObj, const SPtr<SerializedObject>& newObj, ObjectMap& objectMap) override;
  104. /** @copydoc IDiff::applyDiff(const SPtr<IReflectable>&, const SPtr<SerializedObject>&, DiffObjectMap&, Vector<DiffCommand>&) */
  105. void applyDiff(const SPtr<IReflectable>& object, const SPtr<SerializedObject>& diff, DiffObjectMap& objectMap, Vector<DiffCommand>& diffCommands) override;
  106. };
  107. /** @} */
  108. /** @} */
  109. }