Lumiera 0.pre.04~rc.1
»edit your freedom«
Loading...
Searching...
No Matches
tree-diff.cpp
Go to the documentation of this file.
1/*
2 TreeDiff - implementation of diff application to opaque data
3
4 Copyright (C)
5 2016, Hermann Vosseler <Ichthyostega@web.de>
6
7  **Lumiera** is free software; you can redistribute it and/or modify it
8  under the terms of the GNU General Public License as published by the
9  Free Software Foundation; either version 2 of the License, or (at your
10  option) any later version. See the file COPYING for further details.
11
12* *****************************************************************/
13
14
34#include "lib/error.hpp"
36
37
38
39namespace lib {
40namespace diff{
41
43
45
46
47
48
49
50 /* ======= Implementation of Tree Diff Application via TreeMutator ======= */
51
52 using util::unConst;
53 using util::_Fmt;
54 using std::move;
55 using std::swap;
56
57
63 template<>
64 void
66 {
67 buff.emplace (
69 .attach (*this));
70 }
71
72
73
74
75
76 /* == Forwarding: error handling == */
77
78
79 void
81 {
82 throw error::State{_Fmt("Unable to %s element %s. Current shape of target "
83 "data does not match expectations") % oper % spec
84 , LERR_(DIFF_CONFLICT)};
85 }
86
87 void
89 {
90 if (not treeMutator_->hasSrc())
91 throw error::State{_Fmt("Premature end of target sequence, still expecting element %s; "
92 "unable to apply diff further.") % elm
93 , LERR_(DIFF_CONFLICT)};
94 }
95
96 void
98 {
99 throw error::State{_Fmt("Premature end of sequence; unable to locate "
100 "element %s in the remainder of the target.") % elm
101 , LERR_(DIFF_CONFLICT)};
102 }
103
104 void
106 {
107 if (not treeMutator_->completeScope())
108 throw error::State{_Fmt("Diff application floundered in nested scope %s; "
109 "unexpected extra elements found when diff "
110 "should have settled everything.") % idi.getSym()
111 , LERR_(DIFF_STRUCTURE)};
112 }
113
114 void
116 {
117 if (0 == scopeManger_->depth())
118 throw error::Fatal{_Fmt("Diff application floundered after leaving scope %s; "
119 "unbalanced nested scopes, diff attempts to pop root.") % idi.getSym()
120 , LERR_(DIFF_STRUCTURE)};
121 }
122
123
124
125
126
127 /* == Implementation of the list diff application primitives == */
128
129 void
131 {
132 bool success = treeMutator_->injectNew(n);
133 if (not success)
134 __failMismatch ("insert", n);
135 }
136
137 void
139 {
140 __expect_further_elements(n);
141 if (not treeMutator_->matchSrc(n))
142 __failMismatch("remove", n);
143
144 treeMutator_->skipSrc(n);
145 }
146
147 void
149 {
150 bool success = treeMutator_->acceptSrc (n);
151 if (not success)
152 __failMismatch ("pick", n);
153 }
154
155 void
157 {
158 __expect_further_elements (n);
159 treeMutator_->skipSrc(n);
160 } // assume the actual content has been moved away by a previous find()
161
162 void
164 {
165 __expect_further_elements (n);
166 // consume and leave waste, expected to be cleaned-up by skip() later
167 if (not treeMutator_->findSrc(n))
168 __fail_not_found (n);
169 }
170
171
172
173
174 /* == Implementation of the tree diff application primitives == */
175
179 void
181 {
182 if (not treeMutator_->accept_until(n))
183 __fail_not_found (n);
184 }
185
187 void
189 {
190 if (not treeMutator_->assignElm(n))
191 __failMismatch("assign", n);
192 }
193
195 void
197 {
198 TreeMutator::Handle buffHandle = scopeManger_->openScope(); // hint: treeMutatorSize(...)
199 if (not treeMutator_->mutateChild(n, buffHandle))
200 __failMismatch("enter nested scope", n);
201
202 TRACE (diff, "tree-diff: ENTER scope %s", cStr(n.idi));
203 treeMutator_ = buffHandle.get();
204 }
205
207 void
209 {
210 TRACE (diff, "tree-diff: LEAVE scope %s", cStr(n.idi));
211
212 __expect_end_of_scope (n.idi);
213 treeMutator_ = &scopeManger_->closeScope();
214 __expect_valid_parent_scope (n.idi);
215 }
216
217
218
219}} // namespace lib::diff
Inline string literal.
Definition symbol.hpp:78
A handle to allow for safe »remote implantation« of an unknown subclass into a given opaque InPlaceBu...
SUB & emplace(SUB &&implementation)
move-construct an instance of a subclass into the opaque buffer
void buildMutator(BufferHandle)
attachment point to receive and apply tree-diff changes.
virtual ~ScopeManager()
this is an interface
Definition tree-diff.cpp:44
void __expect_further_elements(GenNode const &elm)
Definition tree-diff.cpp:88
void __failMismatch(Literal oper, GenNode const &spec)
Definition tree-diff.cpp:80
virtual void ins(GenNode const &n) override
virtual void mut(GenNode const &n) override
open nested scope to apply diff to child object
virtual void skip(GenNode const &n) override
virtual void set(GenNode const &n) override
assignment of changed value in one step
virtual void emu(GenNode const &n) override
finish and leave child object scope, return to parent
virtual void del(GenNode const &n) override
void __fail_not_found(GenNode const &elm)
Definition tree-diff.cpp:97
virtual void find(GenNode const &n) override
virtual void pick(GenNode const &n) override
void __expect_valid_parent_scope(GenNode::ID const &idi)
void __expect_end_of_scope(GenNode::ID const &idi)
virtual void after(GenNode const &n) override
cue to a position behind the named node, thereby picking (accepting) all traversed elements into the ...
virtual ~TreeMutator()
this is an interface
Definition tree-diff.cpp:42
static Builder< TreeMutator > build()
DSL: start building a custom adapted tree mutator, where the operations are tied by closures or wrapp...
string const & getSym() const
Definition entry-id.hpp:169
Derived specific exceptions within Lumiera's exception hierarchy.
Definition error.hpp:193
A front-end for using printf-style formatting.
Lumiera error handling (C++ interface).
#define LERR_(_NAME_)
Definition error.hpp:45
Implementation namespace for support and library code.
LumieraError< LERR_(STATE)> State
Definition error.hpp:209
OBJ * unConst(const OBJ *)
shortcut to save some typing when having to define const and non-const variants of member functions
Definition util.hpp:358
generic data element node within a tree
Definition gen-node.hpp:224
CStr cStr(std::string const &rendered)
convenience shortcut: forced conversion to c-String via string.
Definition symbol.hpp:60
Concrete implementation to apply structural changes to hierarchical data structures.