From e5ffcf224f7e7f5364cf0db0331f87e37f9e67a9 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Thu, 29 Oct 2015 04:14:18 +0100 Subject: [PATCH] implementation: list diff operations in tree-diff-applicator implement the list handling primitives analogous to the implementation of list-diff-applicator -- just again with the additional twist to keep the attribute and child scopes separated. --- src/lib/diff/tree-diff-application.hpp | 76 ++++++++++++++++++++++++-- 1 file changed, 72 insertions(+), 4 deletions(-) diff --git a/src/lib/diff/tree-diff-application.hpp b/src/lib/diff/tree-diff-application.hpp index d5152beef..0abf507c1 100644 --- a/src/lib/diff/tree-diff-application.hpp +++ b/src/lib/diff/tree-diff-application.hpp @@ -60,12 +60,14 @@ #include "lib/diff/tree-diff.hpp" #include "lib/diff/gen-node.hpp" +#include "lib/format-string.hpp" #include namespace lib { namespace diff{ + using util::_Fmt; using std::move; using std::swap; @@ -85,11 +87,70 @@ namespace diff{ : public TreeDiffInterpreter { using Content = Rec::ContentMutator; + using Iter = Content::Iter; Rec::Mutator& target_; Content content_; + + bool + end_of_target() + { + return content_.pos == content_.end(); + } + + void + __expect_in_target (GenNode const& elm, Literal oper) + { + if (end_of_target()) + throw error::State(_Fmt("Unable to %s element %s from target as demanded; " + "no (further) elements in target sequence") % oper % elm + , LUMIERA_ERROR_DIFF_CONFLICT); + if (*content_.pos != elm) + throw error::State(_Fmt("Unable to %s element %s from target as demanded; " + "found element %s on current target position instead") + % oper % elm % *content_.pos + , LUMIERA_ERROR_DIFF_CONFLICT); + } + + void + __expect_further_elements (GenNode const& elm) + { + if (end_of_target()) + throw error::State(_Fmt("Premature end of target sequence, still expecting element %s; " + "unable to apply diff further.") % elm + , LUMIERA_ERROR_DIFF_CONFLICT); + } + + void + __expect_found (GenNode const& elm, Iter const& targetPos) + { + if (targetPos == content_.end()) + throw error::State(_Fmt("Premature end of sequence; unable to locate " + "element %s in the remainder of the target.") % elm + , LUMIERA_ERROR_DIFF_CONFLICT); + } + + Iter + find_in_current_scope (GenNode const& elm) + { + Iter end_of_scope = content_.currIsAttrib()? content_.attribs.end() + : content_.children.end(); + return std::find (content_.pos, end_of_scope, elm); + } + + void + move_into_new_sequence (Iter pos) + { + if (content_.currIsAttrib()) + target_.appendAttrib (move(*pos)); + else + target_.appendChild (move(*pos)); + } + + + /* == Implementation of the list diff application primitives == */ void @@ -108,25 +169,32 @@ namespace diff{ void del (GenNode const& n) override { - UNIMPLEMENTED("delete next node"); + __expect_in_target(n, "remove"); + ++content_; } void pick (GenNode const& n) override { - UNIMPLEMENTED("accept next node as-is"); + __expect_in_target(n, "pick"); + move_into_new_sequence (content_.pos); + ++content_; } void skip (GenNode const& n) override { - UNIMPLEMENTED("skip void position left by find"); + __expect_further_elements (n); + ++content_; } // assume the actual content has been moved away by a previous find() void find (GenNode const& n) override { - UNIMPLEMENTED("search the named node and insert it here"); + __expect_further_elements (n); + Iter found = find_in_current_scope(n); + __expect_found (n, found); + move_into_new_sequence (found); } // consume and leave waste, expected to be cleaned-up by skip() later