Lumiera  0.pre.03
»edit your freedom«
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) Lumiera.org
5  2016, Hermann Vosseler <Ichthyostega@web.de>
6 
7  This program is free software; you can redistribute it and/or
8  modify it under the terms of the GNU General Public License as
9  published by the Free Software Foundation; either version 2 of
10  the License, or (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21 */
22 
23 
133 #ifndef LIB_DIFF_TREE_DIFF_APPLICATION_H
134 #define LIB_DIFF_TREE_DIFF_APPLICATION_H
135 
136 
137 #include "lib/diff/tree-diff.hpp"
138 #include "lib/diff/tree-mutator.hpp"
139 #include "lib/diff/diff-mutable.hpp"
141 #include "lib/diff/gen-node.hpp"
142 #include "lib/format-string.hpp"
143 #include "lib/util.hpp"
144 
145 #include <utility>
146 #include <stack>
147 
148 namespace lib {
149 namespace diff{
150 
157  {
158  public:
159  virtual ~ScopeManager();
160 
161  virtual TreeMutator::Handle openScope() =0;
162  virtual TreeMutator& closeScope() =0;
163  virtual void clear() =0;
164 
165  virtual size_t depth() const =0;
166  };
167 
168 
169 
178  template<size_t buffSiz>
180  : public ScopeManager
181  {
183  using MutatorStack = std::stack<MutatorBuffer>;
184 
186  MutatorStack scopes_;
187 
188 
189  public:
191  : scopes_()
192  { }
193 
194  TreeMutator&
195  currentScope() const
196  {
197  if (0 == depth())
198  throw error::Logic("Attempt to access the current scope "
199  "without establishing a root scope beforehand."
200  , error::LUMIERA_ERROR_LIFECYCLE);
201  return *scopes_.top();
202  }
203 
204 
205  /* ==== ScopeManager interface ==== */
206 
207  virtual TreeMutator::Handle
209  {
210  scopes_.emplace();
211  TreeMutator::Handle placementHandle (scopes_.top());
212  return placementHandle;
213  }
214 
215  virtual TreeMutator&
216  closeScope()
217  {
218  scopes_.pop();
219  REQUIRE (0 < depth(), "attempt to return beyond root scope");
220  return *scopes_.top();
221  }
222 
223  virtual void
224  clear()
225  {
226  while (0 < scopes_.size())
227  scopes_.pop();
228 
229  ENSURE (scopes_.empty());
230  }
231 
232 
233  virtual size_t
234  depth() const
235  {
236  return scopes_.size();
237  }
238  };
239 
240 
241 
242 
243 
244  /* ======= Implementation of Tree Diff Application via TreeMutator ======= */
245 
246  using util::unConst;
247  using util::_Fmt;
248  using std::move;
249  using std::swap;
250 
251 
273  : public TreeDiffInterpreter
274  {
275  protected:
276  TreeMutator* treeMutator_;
277  ScopeManager* scopeManger_;
278 
279  private:
280 
281  /* == error handling helpers == */
282 
283  void __failMismatch (Literal oper, GenNode const& spec);
284  void __expect_further_elements (GenNode const& elm);
285  void __fail_not_found (GenNode const& elm);
286  void __expect_end_of_scope (GenNode::ID const& idi);
287  void __expect_valid_parent_scope (GenNode::ID const& idi);
288 
289 
290 
291 
292  /* == Implementation of the list diff application primitives == */
293 
294  virtual void ins (GenNode const& n) override;
295  virtual void del (GenNode const& n) override;
296  virtual void pick (GenNode const& n) override;
297  virtual void skip (GenNode const& n) override;
298  virtual void find (GenNode const& n) override;
299 
300 
301  /* == Implementation of the tree diff application primitives == */
302 
303  virtual void after(GenNode const& n) override;
304  virtual void set (GenNode const& n) override;
305  virtual void mut (GenNode const& n) override;
306  virtual void emu (GenNode const& n) override;
307 
308 
309  public:
311  : treeMutator_(nullptr)
312  , scopeManger_(nullptr)
313  { }
314  };
315 
316 
317 
318 
319 
320 
345  template<class TAR>
346  class DiffApplicationStrategy<TAR, enable_if<TreeDiffTraits<TAR>>>
347  : public TreeDiffMutatorBinding
348  {
350 
351 
352  TAR& subject_;
353  Scopes scopes_;
354 
355 
356  TreeMutator*
357  buildMutator (DiffMutable& targetBinding)
358  {
359  scopes_.clear();
360  TreeMutator::Handle buffHandle = scopes_.openScope();
361  targetBinding.buildMutator (buffHandle);
362  return buffHandle.get();
363  }
364 
365  public:
366  explicit
367  DiffApplicationStrategy(TAR& subject)
369  , subject_(subject)
370  , scopes_()
371  { }
372 
373  void
374  initDiffApplication()
375  {
376  using Target = typename TreeDiffTraits<TAR>::Ret;
377 
378  Target target = mutatorBinding (subject_);
379  buildMutator(target)->init();
380  TreeDiffMutatorBinding::scopeManger_ = &scopes_;
381  TreeDiffMutatorBinding::treeMutator_ = &scopes_.currentScope();
382  REQUIRE (this->treeMutator_);
383  }
384 
385  void
386  completeDiffApplication()
387  {
388  if (not treeMutator_->completeScope())
389  throw error::State(_Fmt("Unsettled content remains after diff application. "
390  "Top level == %s") % subject_
391  , LERR_(DIFF_STRUCTURE));
392  // discard storage
393  treeMutator_ = nullptr;
394  scopes_.clear();
395  }
396  };
397 
398 
399 
400 }} // namespace lib::diff
401 #endif /*LIB_DIFF_TREE_DIFF_APPLICATION_H*/
Interpreter interface to define the operations ("verbs"), which describe differences or changes in hi...
Definition: tree-diff.hpp:134
Abstraction or descriptor interface for a data structure exposing the ability for mutation by receivi...
virtual TreeMutator::Handle openScope()
virtual void buildMutator(TreeMutator::Handle buffer)=0
build a custom implementation of the TreeMutator interface, suitably wired to cause appropriate chang...
virtual TreeMutator::Handle openScope()=0
virtual ~ScopeManager()
this is an interface
Definition: tree-diff.cpp:53
Any copy and copy construction prohibited.
Definition: nocopy.hpp:46
inline string literal This is a marker type to indicate that
Definition: symbol.hpp:85
Front-end for printf-style string template interpolation.
A front-end for using printf-style formatting.
Implementation namespace for support and library code.
Definitions and Properties to guide automated tree mutator binding.
Derived specific exceptions within Lumiera&#39;s exception hierarchy.
Definition: error.hpp:199
SUB & emplace(SUB &&implementation)
move-construct an instance of a subclass into the opaque buffer
A handle to allow for safe »remote implantation« of an unknown subclass into a given opaque InPlaceBu...
Definition: record.hpp:113
Typical standard implementation of the ScopeManager.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
MutatorStack scopes_
Allocate Heap Storage for nested TreeMutator(s)
Generic building block for tree shaped (meta)data structures.
Extension point: define how a specific diff language can be applied to elements in a concrete contain...
Management interface to deal with storage for TreeMutators dedicated to nested scopes.
A token language to represent structural changes in a tree like hierarchical data structure...
Customisable intermediary to abstract generic tree mutation operations.
Buffer to place and maintain an object instance privately within another object.
TreeDiffTraits< TAR >::Ret mutatorBinding(TAR &subject)
public access point to this configuration machinery
generic data element node within a tree
Definition: gen-node.hpp:231
Marker or capability interface: an otherwise not further disclosed data structure, which can be transformed through "tree diff messages".
Customisable intermediary to abstract mutating operations on arbitrary, hierarchical object-like data...
Implementation of the tree-diff-language to work on arbitrary tree-like data.