Lumiera  0.pre.03
»edit your freedom«
list-diff-application.hpp
Go to the documentation of this file.
1 /*
2  LIST-DIFF-APPLICATION.hpp - consume and apply a list diff
3 
4  Copyright (C)
5  2014, 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 
30 #ifndef LIB_DIFF_LIST_DIFF_APPLICATION_H
31 #define LIB_DIFF_LIST_DIFF_APPLICATION_H
32 
33 
34 #include "lib/diff/list-diff.hpp"
35 #include "lib/format-string.hpp"
36 
37 #include <algorithm>
38 #include <vector>
39 #include <tuple>
40 
41 
42 namespace lib {
43 namespace diff{
44 
45  using util::_Fmt;
46  using std::vector;
47  using std::move;
48 
62  template<typename E, typename...ARGS>
63  class DiffApplicationStrategy<vector<E,ARGS...>>
64  : public ListDiffInterpreter<E>
65  {
66  using Vec = vector<E,ARGS...>;
67  using Iter = typename Vec::iterator;
68 
69  Vec orig_;
70  Vec& seq_;
71  Iter pos_;
72 
73  bool
74  end_of_target()
75  {
76  return pos_ == orig_.end();
77  }
78 
79  void
80  __expect_in_target (E const& elm, Literal oper)
81  {
82  if (end_of_target())
83  throw error::State(_Fmt("Unable to %s element %s from target as demanded; "
84  "no (further) elements in target sequence") % oper % elm
85  , LERR_(DIFF_CONFLICT));
86  if (*pos_ != elm)
87  throw error::State(_Fmt("Unable to %s element %s from target as demanded; "
88  "found element %s on current target position instead")
89  % oper % elm % *pos_
90  , LERR_(DIFF_CONFLICT));
91  }
92 
93  void
94  __expect_further_elements (E const& elm)
95  {
96  if (end_of_target())
97  throw error::State(_Fmt("Premature end of target sequence, still expecting element %s; "
98  "unable to apply diff further.") % elm
99  , LERR_(DIFF_CONFLICT));
100  }
101 
102  void
103  __expect_found (E const& elm, Iter const& targetPos)
104  {
105  if (targetPos == orig_.end())
106  throw error::State(_Fmt("Premature end of sequence; unable to locate "
107  "element %s in the remainder of the target.") % elm
108  , LERR_(DIFF_CONFLICT));
109  }
110 
111 
112  /* == Implementation of the diff application primitives == */
113 
114  void
115  ins (E const& elm) override
116  {
117  seq_.push_back(elm);
118  }
119 
120  void
121  del (E const& elm) override
122  {
123  __expect_in_target(elm, "remove");
124  ++pos_;
125  }
126 
127  void
128  pick (E const& elm) override
129  {
130  __expect_in_target(elm, "pick");
131  seq_.push_back (move(*pos_));
132  ++pos_;
133  }
134 
135  void
136  skip (E const& elm) override
137  {
138  __expect_further_elements (elm);
139  ++pos_;
140  } // assume the actual content has been moved away by a previous find()
141 
142  void
143  find (E const& elm) override
144  {
145  __expect_further_elements (elm);
146  Iter found = std::find(pos_, orig_.end(), elm);
147  __expect_found (elm, found);
148  seq_.push_back (move(*found));
149  } // consume and leave waste, expected to be cleaned-up by skip() later
150 
151 
152  public:
153  explicit
154  DiffApplicationStrategy(vector<E>& targetVector)
155  : seq_(targetVector)
156  { }
157 
158  void
159  initDiffApplication()
160  {
161  swap (seq_, orig_);
162  seq_.reserve (orig_.size() * 120 / 100); // heuristics for storage pre-allocation
163  pos_ = orig_.begin();
164  }
165 
166  void
167  completeDiffApplication()
168  {
169  if (not end_of_target())
170  throw error::State(_Fmt("Not all source data consumed after diff application. "
171  "Element %s waiting to be consumed") % *pos_
172  , LERR_(DIFF_STRUCTURE));
173  // discard storage
174  orig_.clear();
175  }
176  };
177 
178 
179 
180 
181 
182 }} // namespace lib::diff
183 #endif /*LIB_DIFF_LIST_DIFF_APPLICATION_H*/
A token language to represent changes in a list of elements.
Interpreter interface to define the operations ("verbs"), which describe differences or changes in a ...
Definition: list-diff.hpp:63
inline string literal This is a marker type to indicate that
Definition: symbol.hpp:76
Front-end for printf-style string template interpolation.
A front-end for using printf-style formatting.
Implementation namespace for support and library code.
Derived specific exceptions within Lumiera&#39;s exception hierarchy.
Definition: error.hpp:190
Extension point: define how a specific diff language can be applied to elements in a concrete contain...