BsBinaryDiff.h 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. #pragma once
  2. #include "BsPrerequisitesUtil.h"
  3. #include "BsSerializedObject.h"
  4. namespace BansheeEngine
  5. {
  6. /**
  7. * @brief Generates and applies "diffs". Diffs contain per-field differences between
  8. * an original and new object. These differences can be saved and then applied
  9. * to an original object to transform it to the new version.
  10. *
  11. * @note Objects must be in intermediate serialized format generated by BinarySerializer.
  12. */
  13. class BS_UTILITY_EXPORT BinaryDiff
  14. {
  15. typedef UnorderedMap<SPtr<SerializedObject>, SPtr<SerializedObject>> ObjectMap;
  16. typedef UnorderedMap<SPtr<SerializedObject>, SPtr<IReflectable>> DiffObjectMap;
  17. public:
  18. /**
  19. * @brief Generates per-field differences between the provided original and new object. Any field
  20. * or array entry that is different in the new object compared to the original will be output
  21. * in the resulting object, with a full hierarchy of that field.
  22. *
  23. * Will return null if there is no difference.
  24. */
  25. static SPtr<SerializedObject> generateDiff(const SPtr<SerializedObject>& orgObj, const SPtr<SerializedObject>& newObj);
  26. /**
  27. * @brief Applies a previously generated per-field differences to the provided object. This will
  28. * essentially transform the original object the differences were generated for into the modified
  29. * version.
  30. */
  31. static void applyDiff(const SPtr<IReflectable>& object, const SPtr<SerializedObject>& diff);
  32. private:
  33. /**
  34. * @brief Types of commands that are used when applying difference field values.
  35. */
  36. enum DiffCommandType
  37. {
  38. Diff_Plain = 0x01,
  39. Diff_Reflectable = 0x02,
  40. Diff_ReflectablePtr = 0x03,
  41. Diff_DataBlock = 0x04,
  42. Diff_ArraySize = 0x05,
  43. Diff_ObjectStart = 0x06,
  44. Diff_ObjectEnd = 0x07,
  45. Diff_ArrayFlag = 0x10
  46. };
  47. /**
  48. * @brief A command that is used for delaying writing to an object, it contains
  49. * all necessary information for setting RTTI field values on an object.
  50. */
  51. struct DiffCommand
  52. {
  53. RTTIField* field;
  54. UINT32 type;
  55. SPtr<IReflectable> object;
  56. UINT8* value;
  57. UINT32 size;
  58. union
  59. {
  60. UINT32 arrayIdx;
  61. UINT32 arraySize;
  62. };
  63. };
  64. /**
  65. * @brief Recursive version of generateDiff(const SPtr<SerializedObject>&, const SPtr<SerializedObject>&).
  66. *
  67. * @see generateDiff(const SPtr<SerializedObject>&, const SPtr<SerializedObject>&)
  68. */
  69. static SPtr<SerializedObject> generateDiff(const SPtr<SerializedObject>& orgObj, const SPtr<SerializedObject>& newObj, ObjectMap& objectMap);
  70. /**
  71. * @brief Generates a difference between data of a specific field type indiscriminately of the
  72. * specific field type.
  73. *
  74. * @see generateDiff(const SPtr<SerializedObject>&, const SPtr<SerializedObject>&)
  75. */
  76. static SPtr<SerializedInstance> generateDiff(UINT32 fieldType, const SPtr<SerializedInstance>& orgData,
  77. const SPtr<SerializedInstance>& newData, ObjectMap& objectMap);
  78. /**
  79. * @brief Recursive version of applyDiff(const SPtr<IReflectable>& object, const SPtr<SerializedObject>& diff).
  80. * Outputs a set of commands that then must be executed in order to actually apply the difference to the
  81. * provided object.
  82. *
  83. * @see applyDiff(const SPtr<IReflectable>& object, const SPtr<SerializedObject>& diff)
  84. */
  85. static void applyDiff(const SPtr<IReflectable>& object, const SPtr<SerializedObject>& diff, DiffObjectMap& objectMap, Vector<DiffCommand>& diffCommands);
  86. /**
  87. * @brief Helper method that clones any object with RTTI implemented.
  88. */
  89. static SPtr<IReflectable> clone(IReflectable* object);
  90. };
  91. }