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 
213  static_assert (buffSiz >= sizeof(typename MutatorStack::value_type)
214  ,"insufficient working buffer for TreeMutator");
215  return placementHandle;
216  }
217 
218  virtual TreeMutator&
219  closeScope()
220  {
221  scopes_.pop();
222  REQUIRE (0 < depth(), "attempt to return beyond root scope");
223  return *scopes_.top();
224  }
225 
226  virtual void
227  clear()
228  {
229  while (0 < scopes_.size())
230  scopes_.pop();
231 
232  ENSURE (scopes_.empty());
233  }
234 
235 
236  virtual size_t
237  depth() const
238  {
239  return scopes_.size();
240  }
241  };
242 
243 
244 
245 
246 
247  /* ======= Implementation of Tree Diff Application via TreeMutator ======= */
248 
249  using util::unConst;
250  using util::cStr;
251  using util::_Fmt;
252  using std::move;
253  using std::swap;
254 
255 
277  : public TreeDiffInterpreter
278  {
279  protected:
280  TreeMutator* treeMutator_;
281  ScopeManager* scopeManger_;
282 
283  private:
284 
285  /* == error handling helpers == */
286 
287  void __failMismatch (Literal oper, GenNode const& spec);
288  void __expect_further_elements (GenNode const& elm);
289  void __fail_not_found (GenNode const& elm);
290  void __expect_end_of_scope (GenNode::ID const& idi);
291  void __expect_valid_parent_scope (GenNode::ID const& idi);
292 
293 
294 
295 
296  /* == Implementation of the list diff application primitives == */
297 
298  virtual void ins (GenNode const& n) override;
299  virtual void del (GenNode const& n) override;
300  virtual void pick (GenNode const& n) override;
301  virtual void skip (GenNode const& n) override;
302  virtual void find (GenNode const& n) override;
303 
304 
305  /* == Implementation of the tree diff application primitives == */
306 
307  virtual void after(GenNode const& n) override;
308  virtual void set (GenNode const& n) override;
309  virtual void mut (GenNode const& n) override;
310  virtual void emu (GenNode const& n) override;
311 
312 
313  public:
315  : treeMutator_(nullptr)
316  , scopeManger_(nullptr)
317  { }
318  };
319 
320 
321 
322 
323 
324 
349  template<class TAR>
350  class DiffApplicationStrategy<TAR, enable_if<TreeDiffTraits<TAR>>>
351  : public TreeDiffMutatorBinding
352  {
354 
355 
356  TAR& subject_;
357  Scopes scopes_;
358 
359 
360  TreeMutator*
361  buildMutator (DiffMutable& targetBinding)
362  {
363  scopes_.clear();
364  TreeMutator::Handle buffHandle = scopes_.openScope();
365  targetBinding.buildMutator (buffHandle);
366  return buffHandle.get();
367  }
368 
369  public:
370  explicit
371  DiffApplicationStrategy(TAR& subject)
373  , subject_(subject)
374  , scopes_()
375  { }
376 
377  void
378  initDiffApplication()
379  {
380  using Target = typename TreeDiffTraits<TAR>::Ret;
381 
382  Target target = mutatorBinding (subject_);
383  buildMutator(target)->init();
384  TreeDiffMutatorBinding::scopeManger_ = &scopes_;
385  TreeDiffMutatorBinding::treeMutator_ = &scopes_.currentScope();
386  REQUIRE (this->treeMutator_);
387  }
388 
389  void
390  completeDiffApplication()
391  {
392  if (not treeMutator_->completeScope())
393  throw error::State(_Fmt("Unsettled content remains after diff application. "
394  "Top level == %s") % subject_
395  , LERR_(DIFF_STRUCTURE));
396  // discard storage
397  treeMutator_ = nullptr;
398  scopes_.clear();
399  }
400  };
401 
402 
403 
404 }} // namespace lib::diff
405 #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:75
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:196
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.