Lumiera 0.pre.04
»edit your freedom«
Loading...
Searching...
No Matches
tree-diff-application.hpp
Go to the documentation of this file.
1/*
2 TREE-DIFF-APPLICATION.hpp - consume and apply a tree diff
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
124#ifndef LIB_DIFF_TREE_DIFF_APPLICATION_H
125#define LIB_DIFF_TREE_DIFF_APPLICATION_H
126
127
128#include "lib/diff/tree-diff.hpp"
132#include "lib/diff/gen-node.hpp"
133#include "lib/format-string.hpp"
134#include "lib/util.hpp"
135
136#include <utility>
137#include <stack>
138
139namespace lib {
140namespace diff{
141
148 {
149 public:
150 virtual ~ScopeManager();
151
153 virtual TreeMutator& closeScope() =0;
154 virtual void clear() =0;
155
156 virtual size_t depth() const =0;
157 };
158
159
160
169 template<size_t buffSiz>
171 : public ScopeManager
172 {
174 using MutatorStack = std::stack<MutatorBuffer>;
175
178
179
180 public:
182 : scopes_()
183 { }
184
187 {
188 if (0 == depth())
189 throw error::Logic("Attempt to access the current scope "
190 "without establishing a root scope beforehand."
191 , error::LUMIERA_ERROR_LIFECYCLE);
192 return *scopes_.top();
193 }
194
195
196 /* ==== ScopeManager interface ==== */
197
198 virtual TreeMutator::Handle
200 {
202 TreeMutator::Handle placementHandle (scopes_.top());
203 return placementHandle;
204 }
205
206 virtual TreeMutator&
208 {
209 scopes_.pop();
210 REQUIRE (0 < depth(), "attempt to return beyond root scope");
211 return *scopes_.top();
212 }
213
214 virtual void
216 {
217 while (0 < scopes_.size())
218 scopes_.pop();
219
220 ENSURE (scopes_.empty());
221 }
222
223
224 virtual size_t
225 depth() const
226 {
227 return scopes_.size();
228 }
229 };
230
231
232
233
234
235 /* ======= Implementation of Tree Diff Application via TreeMutator ======= */
236
237 using util::unConst;
238 using util::_Fmt;
239 using std::move;
240 using std::swap;
241
242
264 : public TreeDiffInterpreter
265 {
266 protected:
269
270 private:
271
272 /* == error handling helpers == */
273
274 void __failMismatch (Literal oper, GenNode const& spec);
275 void __expect_further_elements (GenNode const& elm);
276 void __fail_not_found (GenNode const& elm);
277 void __expect_end_of_scope (GenNode::ID const& idi);
279
280
281
282
283 /* == Implementation of the list diff application primitives == */
284
285 virtual void ins (GenNode const& n) override;
286 virtual void del (GenNode const& n) override;
287 virtual void pick (GenNode const& n) override;
288 virtual void skip (GenNode const& n) override;
289 virtual void find (GenNode const& n) override;
290
291
292 /* == Implementation of the tree diff application primitives == */
293
294 virtual void after(GenNode const& n) override;
295 virtual void set (GenNode const& n) override;
296 virtual void mut (GenNode const& n) override;
297 virtual void emu (GenNode const& n) override;
298
299
300 public:
302 : treeMutator_(nullptr)
303 , scopeManger_(nullptr)
304 { }
305 };
306
307
308
309
310
311
336 template<class TAR>
337 class DiffApplicationStrategy<TAR, enable_if<TreeDiffTraits<TAR>>>
339 {
341
342
345
346
348 buildMutator (DiffMutable& targetBinding)
349 {
350 scopes_.clear();
351 TreeMutator::Handle buffHandle = scopes_.openScope();
352 targetBinding.buildMutator (buffHandle);
353 return buffHandle.get();
354 }
355
356 public:
357 explicit
360 , subject_(subject)
361 , scopes_()
362 { }
363
364 void
366 {
367 using Target = TreeDiffTraits<TAR>::Ret;
368
369 Target target = mutatorBinding (subject_);
370 buildMutator(target)->init();
373 REQUIRE (this->treeMutator_);
374 }
375
376 void
378 {
379 if (not treeMutator_->completeScope())
380 throw error::State(_Fmt("Unsettled content remains after diff application. "
381 "Top level == %s") % subject_
382 , LERR_(DIFF_STRUCTURE));
383 // discard storage
384 treeMutator_ = nullptr;
385 scopes_.clear();
386 }
387 };
388
389
390
391}} // namespace lib::diff
392#endif /*LIB_DIFF_TREE_DIFF_APPLICATION_H*/
Buffer to place and maintain an object instance privately within another object.
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
Marker or capability interface: an otherwise not further disclosed data structure,...
virtual void buildMutator(TreeMutator::Handle buffer)=0
build a custom implementation of the TreeMutator interface, suitably wired to cause appropriate chang...
Management interface to deal with storage for TreeMutators dedicated to nested scopes.
virtual TreeMutator::Handle openScope()=0
virtual size_t depth() const =0
virtual void clear()=0
virtual TreeMutator & closeScope()=0
virtual ~ScopeManager()
this is an interface
Definition tree-diff.cpp:44
Typical standard implementation of the ScopeManager.
InPlaceBuffer< TreeMutator, buffSiz > MutatorBuffer
virtual TreeMutator::Handle openScope()
MutatorStack scopes_
Allocate Heap Storage for nested TreeMutator(s)
std::stack< MutatorBuffer > MutatorStack
Interpreter interface to define the operations ("verbs"), which describe differences or changes in hi...
Implementation of the tree-diff-language to work on arbitrary tree-like data.
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 ...
Customisable intermediary to abstract mutating operations on arbitrary, hierarchical object-like data...
Any copy and copy construction prohibited.
Definition nocopy.hpp:38
A front-end for using printf-style formatting.
Abstraction or descriptor interface for a data structure exposing the ability for mutation by receivi...
#define LERR_(_NAME_)
Definition error.hpp:45
Front-end for printf-style string template interpolation.
Generic building block for tree shaped (meta)data structures.
TreeDiffTraits< TAR >::Ret mutatorBinding(TAR &subject)
public access point to this configuration machinery
Extension point: define how a specific diff language can be applied to elements in a concrete contain...
Implementation namespace for support and library code.
LumieraError< LERR_(STATE)> State
Definition error.hpp:209
LumieraError< LERR_(LOGIC)> Logic
Definition error.hpp:207
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
Definitions and Properties to guide automated tree mutator binding.
A token language to represent structural changes in a tree like hierarchical data structure.
Customisable intermediary to abstract generic tree mutation operations.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...