diff --git a/src/lib/diff/diff-language.hpp b/src/lib/diff/diff-language.hpp index ee31a026a..471ab6234 100644 --- a/src/lib/diff/diff-language.hpp +++ b/src/lib/diff/diff-language.hpp @@ -296,7 +296,6 @@ namespace diff{ { for ( ; diff; ++diff ) diff->applyTo(target_); - target_.finalise(); } }; diff --git a/src/lib/diff/list-diff-application.hpp b/src/lib/diff/list-diff-application.hpp index 35a6b8449..5f24ae0f6 100644 --- a/src/lib/diff/list-diff-application.hpp +++ b/src/lib/diff/list-diff-application.hpp @@ -167,9 +167,6 @@ namespace diff{ swap (seq_, orig_); // pos_ still refers to original input sequence, which has been moved to orig_ seq_.reserve (targetVector.size() * 120 / 100); // heuristics for storage pre-allocation } - - /** clean-up and make changes effective within target */ - void finalise() { /* NOP for this implementation */ } }; diff --git a/src/lib/diff/tree-diff-application.hpp b/src/lib/diff/tree-diff-application.hpp index 2e66f42ac..915b5c70f 100644 --- a/src/lib/diff/tree-diff-application.hpp +++ b/src/lib/diff/tree-diff-application.hpp @@ -40,20 +40,34 @@ #include "lib/diff/tree-diff.hpp" #include "lib/diff/gen-node.hpp" +#include + namespace lib { namespace diff{ + using std::move; + using std::swap; + + /** * concrete strategy to apply a structural diff to a target data structure - * made from #Record elements. + * made from #Record elements. This data structure is assumed to be + * recursive, tree-like. But because Record elements are conceived as immutable + * and value-like, the tree diff application actually works on a Rec::Mutator + * wrapping the target record to be altered through consuming the diff. * @throws lumiera::error::State when diff application fails due to the * target sequence being different than assumed by the given diff. * @see #TreeDiffInterpreter explanation of the verbs */ template<> - class DiffApplicationStrategy + class DiffApplicationStrategy : public TreeDiffInterpreter { + using Storage = RecordSetup::Storage; + + Rec::Mutator& target_; + Storage attribs_; + Storage children_; /* == Implementation of the list diff application primitives == */ @@ -113,16 +127,17 @@ namespace diff{ public: explicit - DiffApplicationStrategy(Rec& targetRecord) + DiffApplicationStrategy(Rec::Mutator& mutableTargetRecord) + : target_(mutableTargetRecord) + , attribs_() + , children_() { - UNIMPLEMENTED(); - } - - /** clean-up and make changes effective within target */ - void - finalise() - { - UNIMPLEMENTED("push rebuilt Record into target"); + swap (attribs_, target_.attribs()); + swap (children_, target_.children()); + + // heuristics for storage pre-allocation + target_.attribs().reserve (attribs_.size() * 120 / 100); + target_.children().reserve (children_.size() * 120 / 100); } }; diff --git a/tests/library/diff/diff-tree-application-test.cpp b/tests/library/diff/diff-tree-application-test.cpp index 86a86bd97..964a46b72 100644 --- a/tests/library/diff/diff-tree-application-test.cpp +++ b/tests/library/diff/diff-tree-application-test.cpp @@ -138,16 +138,17 @@ namespace test{ virtual void run (Arg) { - Rec target; - DiffApplicator application(target); + Rec::Mutator target; + Rec& subject = target; + DiffApplicator application(target); application.consume(populationDiff()); - CHECK (!isnil (target)); // nonempty -- content has been added - CHECK ("X" == target.getType()); // type was set to "X" - CHECK (1 == target.get("α").data.get()); // has gotten our int attribute "α" - CHECK (2L == target.get("β").data.get()); // ... the long attribute "β" - CHECK (3.45 == target.get("γ").data.get()); // ... and double attribute "γ" - auto scope = target.scope(); // look into the scope contents... + CHECK (!isnil (subject)); // nonempty -- content has been added + CHECK ("X" == subject.getType()); // type was set to "X" + CHECK (1 == subject.get("α").data.get()); // has gotten our int attribute "α" + CHECK (2L == subject.get("β").data.get()); // ... the long attribute "β" + CHECK (3.45 == subject.get("γ").data.get()); // ... and double attribute "γ" + auto scope = subject.scope(); // look into the scope contents... CHECK ( *scope == CHILD_A); // there is CHILD_A CHECK (*++scope == CHILD_T); // followed by a copy of CHILD_T CHECK (*++scope == CHILD_T); // and another copy of CHILD_T @@ -157,8 +158,8 @@ namespace test{ CHECK (isnil(++scope)); // thats all -- no more children application.consume(mutationDiff()); - CHECK (join (target.keys()) == "α, β, γ"); // the attributes weren't altered - scope = target.scope(); // but the scope was reordered + CHECK (join (subject.keys()) == "α, β, γ"); // the attributes weren't altered + scope = subject.scope(); // but the scope was reordered CHECK ( *scope == CHILD_T); // CHILD_T CHECK (*++scope == CHILD_A); // CHILD_A Rec nested = (++scope)->data.get(); // and our nested Record, which too has been altered: diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index da1bd08e7..a1bed87c1 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -1810,7 +1810,27 @@ - + + + + + + +

+ Lösung: wir arbeiten auf einem Mutator +

+ + +
+ + + + + + + +
+ @@ -1832,45 +1852,7 @@ - - - - - - -

- Problem: Konstruktion nach Diff -

- - -
- - - - - - - - - - - - - - - - -

- d.h. es gibt eine Methode applyChanges. -

-

- Die generische Implementierung verwendet diese nach Aufspielen des Diff -

- - -
-
-
+