on second thought: yet a better solution

...is to let the diff applicator work *on* a Rec::Mutator
This is outright natural -- why is it that I needed 2 days
to come up with this solution?
This commit is contained in:
Fischlurch 2015-10-23 01:32:47 +02:00
parent eabeee3b7b
commit c90e6a6f65
5 changed files with 59 additions and 65 deletions

View file

@ -296,7 +296,6 @@ namespace diff{
{
for ( ; diff; ++diff )
diff->applyTo(target_);
target_.finalise();
}
};

View file

@ -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 */ }
};

View file

@ -40,20 +40,34 @@
#include "lib/diff/tree-diff.hpp"
#include "lib/diff/gen-node.hpp"
#include <utility>
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<GenNode> elements.
* made from #Record<GenNode> 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<Rec>
class DiffApplicationStrategy<Rec::Mutator>
: public TreeDiffInterpreter
{
using Storage = RecordSetup<GenNode>::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);
}
};

View file

@ -138,16 +138,17 @@ namespace test{
virtual void
run (Arg)
{
Rec target;
DiffApplicator<Rec> application(target);
Rec::Mutator target;
Rec& subject = target;
DiffApplicator<Rec::Mutator> 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<int>()); // has gotten our int attribute "α"
CHECK (2L == target.get("β").data.get<int64_t>()); // ... the long attribute "β"
CHECK (3.45 == target.get("γ").data.get<double>()); // ... 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<int>()); // has gotten our int attribute "α"
CHECK (2L == subject.get("β").data.get<int64_t>()); // ... the long attribute "β"
CHECK (3.45 == subject.get("γ").data.get<double>()); // ... 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<Rec>(); // and our nested Record, which too has been altered:

View file

@ -1810,7 +1810,27 @@
</richcontent>
</node>
</node>
<node CREATED="1445550873904" ID="ID_1781797833" MODIFIED="1445550888011" TEXT="copy + transaktional als 2.Layer"/>
<node CREATED="1445555721981" ID="ID_292803227" MODIFIED="1445556598964">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
L&#246;sung: wir arbeiten <i>auf </i>einem Mutator
</p>
</body>
</html>
</richcontent>
<icon BUILTIN="idea"/>
<node CREATED="1445556525714" ID="ID_1223708278" MODIFIED="1445556595037" TEXT="damit funktioniert es 1:1 wie List-Diff">
<icon BUILTIN="ksmiletris"/>
</node>
<node CREATED="1445556567980" ID="ID_783100840" MODIFIED="1445556591370" TEXT="Voraussetzung: der Mutator mu&#xdf; die Attribut/Kinder-Listen exponieren">
<icon BUILTIN="messagebox_warning"/>
</node>
</node>
<node CREATED="1445550873904" ID="ID_1781797833" MODIFIED="1445556509368" TEXT="copy + transaktional als optionaler 2.Layer"/>
<node CREATED="1445550893222" ID="ID_2118555" MODIFIED="1445550915111" TEXT="Diff-Applikator = destruktiver Mutator"/>
<node CREATED="1445389311690" ID="ID_1926972913" MODIFIED="1445389323819" TEXT="und dieses rekursiv..."/>
</node>
@ -1832,45 +1852,7 @@
</node>
<node CREATED="1445392105075" ID="ID_1377567733" MODIFIED="1445392113677" TEXT="zwei neue, lokale Vektoren aufbauen"/>
<node CREATED="1445392114217" ID="ID_71124283" MODIFIED="1445392120973" TEXT="daraus den neuen Record konstruieren"/>
<node CREATED="1445392127015" ID="ID_883189076" MODIFIED="1445392201654">
<richcontent TYPE="NODE"><html>
<head>
</head>
<body>
<p>
Problem: Konstruktion <i>nach </i>Diff
</p>
</body>
</html>
</richcontent>
<icon BUILTIN="flag-yellow"/>
<node CREATED="1445392161508" ID="ID_425268274" MODIFIED="1445392188383" TEXT="API daf&#xfc;r fehlt">
<icon BUILTIN="messagebox_warning"/>
</node>
<node CREATED="1445392169019" ID="ID_475848296" MODIFIED="1445392193215" TEXT="doppelte H&#xfc;lle">
<icon BUILTIN="idea"/>
</node>
<node CREATED="1445392174969" ID="ID_387417089" MODIFIED="1445392183796" TEXT="DiffAplicator ist generisch">
<icon BUILTIN="messagebox_warning"/>
</node>
<node CREATED="1445550928897" ID="ID_911120047" MODIFIED="1445551003670" TEXT="-&gt; mu&#xdf; inneres API erweitern">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
d.h. es gibt eine Methode applyChanges.
</p>
<p>
Die generische Implementierung verwendet diese nach Aufspielen des Diff
</p>
</body>
</html>
</richcontent>
</node>
</node>
<node CREATED="1445556634395" ID="ID_1143865339" MODIFIED="1445556649348" TEXT="technische Komplikation: &quot;2 Listen&quot;-Modell"/>
</node>
</node>
</node>