From b251b9a022bce80e7b7ee6d9cf044adba03ba02c Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sun, 2 Oct 2016 23:34:07 +0200 Subject: [PATCH] MutationMessage: generic implementation based on the DiffMutable interface --- src/gui/ctrl/bus-controller.cpp | 2 +- src/gui/ctrl/mutation-message.hpp | 69 +++++++++++++++----------- src/lib/diff/diff-language.hpp | 3 +- src/lib/diff/tree-diff-application.hpp | 4 +- src/lib/diff/tree-diff-traits.hpp | 5 +- src/lib/opaque-holder.hpp | 2 + 6 files changed, 51 insertions(+), 34 deletions(-) diff --git a/src/gui/ctrl/bus-controller.cpp b/src/gui/ctrl/bus-controller.cpp index 91d64746c..213973b4c 100644 --- a/src/gui/ctrl/bus-controller.cpp +++ b/src/gui/ctrl/bus-controller.cpp @@ -188,7 +188,7 @@ namespace ctrl { bool BusTerm::change (ID subject, MutationMessage& diff) { - theBus_.change(subject, diff); + return theBus_.change(subject, diff); } diff --git a/src/gui/ctrl/mutation-message.hpp b/src/gui/ctrl/mutation-message.hpp index 8c4f4bf50..08e0ecd4c 100644 --- a/src/gui/ctrl/mutation-message.hpp +++ b/src/gui/ctrl/mutation-message.hpp @@ -37,9 +37,8 @@ ** ## Creating mutation messages ** The UI-Bus invocation actually takes a reference to MutationMessage, and thus on usage a ** concrete instance needs to be created. This concrete Message embeds an actual diff sequence, - ** which is an iterable sequence of lib::diff::DiffStep records. - ** - ** @todo as of 10/2016 this is WIP-WIP-WIP + ** which is some iterable sequence of lib::diff::DiffStep records. + ** @warning be sure to understand that the diff sequence is really moved away and then consumed. ** ** @see [AbstractTangible_test] ** @@ -51,38 +50,32 @@ #include "lib/error.hpp" -//#include "lib/symbol.hpp" #include "lib/opaque-holder.hpp" -//#include "lib/util.hpp" -//#include "lib/idi/entry-id.hpp" #include "lib/diff/diff-mutable.hpp" +#include "lib/diff/tree-diff-application.hpp" +#include "lib/format-util.hpp" -//#include -//#include #include #include namespace gui { -namespace model { - class Tangible; -} namespace ctrl{ -// using lib::HashVal; -// using util::isnil; -// using lib::idi::EntryID; -// using lib::diff::GenNode; using std::string; - namespace diff_msg { + namespace diff_msg { // implementation details for embedding concrete diff messages + + using lib::diff::DiffMutable; + using lib::diff::DiffApplicator; + using std::move; class Holder { public: - virtual ~Holder(); ///< this is an interface - virtual void applyTo (lib::diff::DiffMutable&) =0; - virtual string describe() const =0; + virtual ~Holder(); ///< this is an interface + virtual void applyTo (DiffMutable&) =0; + virtual string describe() const =0; }; template @@ -92,25 +85,43 @@ namespace ctrl{ DIFF diff_; virtual void - applyTo (lib::diff::DiffMutable& target) override + applyTo (DiffMutable& target) override { - UNIMPLEMENTED("how to embed a diff sequence and apply this to the target"); + DiffApplicator applicator(target); + applicator.consume (move(diff_)); } virtual string describe() const override { - UNIMPLEMENTED("string representation of diff/mutation messages"); + DIFF copy(diff_); // NOTE: we copy, since each iteration consumes. + return util::join (move(copy)); } public: Wrapped (DIFF&& diffSeq) - : diff_(std::move(diffSeq)) + : diff_(move(diffSeq)) { } }; - using Buffer = lib::InPlaceBuffer; - } + + /** standard size to reserve for the concrete diff representation + * @note this is a pragmatic guess, based on the actual usage pattern within Lumiera. + * This determines the size of the inline buffer within MutationMessage. + * You'll get an static assertion failure when creating a MutationMessage + * from a concrete diff representation requiring more size... + */ + enum { SIZE_OF_DIFF_REPRESENTATION = sizeof(std::vector) + + sizeof(size_t) + + sizeof(void*) + }; + + using Buffer = lib::InPlaceBuffer; + }//(End) implementation details... + + + + /** * Message on the UI-Bus holding an embedded diff sequence. @@ -120,8 +131,11 @@ namespace ctrl{ class MutationMessage : public diff_msg::Buffer { - public: + /** build a MutationMessage by _consuming_ the given diff sequence + * @param diffSeq some iterable DiffStep sequence. + * @warning parameter will be moved into the embedded buffer and consumed + */ template MutationMessage(DIFF&& diffSeq) : diff_msg::Buffer{ embedType>() @@ -143,9 +157,6 @@ namespace ctrl{ }; - - - /** */ }} // namespace gui::ctrl diff --git a/src/lib/diff/diff-language.hpp b/src/lib/diff/diff-language.hpp index 4f8587939..6229cb401 100644 --- a/src/lib/diff/diff-language.hpp +++ b/src/lib/diff/diff-language.hpp @@ -167,7 +167,8 @@ namespace diff{ operator string() const { - return string(verb()) + "("+string(elm())+")"; + return string(unConst(this)->verb()) + + "("+string(unConst(this)->elm())+")"; } void diff --git a/src/lib/diff/tree-diff-application.hpp b/src/lib/diff/tree-diff-application.hpp index 34585ff67..b4230cdea 100644 --- a/src/lib/diff/tree-diff-application.hpp +++ b/src/lib/diff/tree-diff-application.hpp @@ -376,7 +376,9 @@ namespace diff{ void initDiffApplication() { - auto target = mutatorBinding (subject_); + using Target = typename TreeDiffTraits::Ret; + + Target target = mutatorBinding (subject_); buildMutator (target); TreeDiffMutatorBinding::scopeManger_ = &scopes_; TreeDiffMutatorBinding::treeMutator_ = &scopes_.currentScope(); diff --git a/src/lib/diff/tree-diff-traits.hpp b/src/lib/diff/tree-diff-traits.hpp index 9914a5e2b..838aa10d5 100644 --- a/src/lib/diff/tree-diff-traits.hpp +++ b/src/lib/diff/tree-diff-traits.hpp @@ -149,7 +149,8 @@ namespace diff{ META_DETECT_FUNCTION (void, buildMutator, (TreeMutator::Handle)); public: - enum{ value = HasFunSig_buildMutator::value }; + enum{ value = HasFunSig_buildMutator::value + and not is_same::value}; }; @@ -212,7 +213,7 @@ namespace diff{ mutatorBinding (TAR& subject) { using Wrapper = typename TreeDiffTraits::Ret; - return Wrapper{subject}; + return Wrapper(subject); } diff --git a/src/lib/opaque-holder.hpp b/src/lib/opaque-holder.hpp index 41ebe662d..15e2b7fe6 100644 --- a/src/lib/opaque-holder.hpp +++ b/src/lib/opaque-holder.hpp @@ -630,6 +630,8 @@ namespace lib { template InPlaceBuffer (TY*, ARGS&& ...args) { + static_assert (siz >= sizeof(TY), "InPlaceBuffer to small"); + new(&buf_) TY (std::forward (args)...); }