//********************************** Banshee Engine (www.banshee3d.com) **************************************************// //**************** Copyright (c) 2016 Marko Pintera (marko.pintera@gmail.com). All rights reserved. **********************// #pragma once #include "Prerequisites/BsPrerequisitesUtil.h" namespace bs { /** @addtogroup Internal-Utility * @{ */ /** @addtogroup Serialization-Internal * @{ */ /** * Represents an interface RTTI objects need to implement if they want to provide custom "diff" generation and applying. */ class BS_UTILITY_EXPORT IDiff { public: virtual ~IDiff() { } /** * Generates per-field differences between the provided original and new object. Any field or array entry that is * different in the new object compared to the original will be output in the resulting object, with a full * hierarchy of that field. * * Will return null if there is no difference. */ SPtr generateDiff(const SPtr& orgObj, const SPtr& newObj); /** * Applies a previously generated per-field differences to the provided object. This will essentially transform the * original object the differences were generated for into the modified version. */ void applyDiff(const SPtr& object, const SPtr& diff); protected: typedef UnorderedMap, SPtr> ObjectMap; typedef UnorderedMap, SPtr> DiffObjectMap; /** Types of commands that are used when applying difference field values. */ enum DiffCommandType { Diff_Plain = 0x01, Diff_Reflectable = 0x02, Diff_ReflectablePtr = 0x03, Diff_DataBlock = 0x04, Diff_ArraySize = 0x05, Diff_ObjectStart = 0x06, Diff_ObjectEnd = 0x07, Diff_ArrayFlag = 0x10 }; /** * A command that is used for delaying writing to an object, it contains all necessary information for setting RTTI * field values on an object. */ struct DiffCommand { RTTIField* field; UINT32 type; SPtr object; UINT8* value; SPtr streamValue; UINT32 size; union { UINT32 arrayIdx; UINT32 arraySize; }; }; /** * Recursive version of generateDiff(const SPtr&, const SPtr&). * * @see generateDiff(const SPtr&, const SPtr&) */ virtual SPtr generateDiff(const SPtr& orgObj, const SPtr& newObj, ObjectMap& objectMap) = 0; /** * Generates a difference between data of a specific field type indiscriminately of the specific field type. * * @see generateDiff(const SPtr&, const SPtr&) */ SPtr generateDiff(RTTITypeBase* rtti, UINT32 fieldType, const SPtr& orgData, const SPtr& newData, ObjectMap& objectMap); /** * Recursive version of applyDiff(const SPtr& object, const SPtr& diff). Outputs a * set of commands that then must be executed in order to actually apply the difference to the provided object. * * @see applyDiff(const SPtr& object, const SPtr& diff) */ virtual void applyDiff(const SPtr& object, const SPtr& diff, DiffObjectMap& objectMap, Vector& diffCommands) = 0; /** * Applies diff according to the diff handler retrieved from the provided RTTI object. * * @see applyDiff(const SPtr& object, const SPtr& diff) */ void applyDiff(RTTITypeBase* rtti, const SPtr& object, const SPtr& diff, DiffObjectMap& objectMap, Vector& diffCommands); }; /** * Generates and applies "diffs". Diffs contain per-field differences between an original and new object. These * differences can be saved and then applied to an original object to transform it to the new version. * * @note Objects must be in intermediate serialized format generated by BinarySerializer. */ class BS_UTILITY_EXPORT BinaryDiff : public IDiff { private: /** @copydoc IDiff::generateDiff(const SPtr&, const SPtr&, ObjectMap&) */ SPtr generateDiff(const SPtr& orgObj, const SPtr& newObj, ObjectMap& objectMap) override; /** @copydoc IDiff::applyDiff(const SPtr&, const SPtr&, DiffObjectMap&, Vector&) */ void applyDiff(const SPtr& object, const SPtr& diff, DiffObjectMap& objectMap, Vector& diffCommands) override; }; /** @} */ /** @} */ }