Lumiera  0.pre.03
»edit your freedom«
list-diff-detector.hpp
Go to the documentation of this file.
1 /*
2  LIST-DIFF-DETECTOR.hpp - language to describe differences in linearised form
3 
4  Copyright (C) Lumiera.org
5  2015, 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 
57 #ifndef LIB_DIFF_LIST_DIFF_DETECTOR_H
58 #define LIB_DIFF_LIST_DIFF_DETECTOR_H
59 
60 
61 #include "lib/diff/list-diff.hpp"
62 #include "lib/diff/index-table.hpp"
63 #include "lib/iter-adapter.hpp"
64 #include "lib/nocopy.hpp"
65 
66 #include <utility>
67 
68 
69 namespace lib {
70 namespace diff{
71 
72  using util::unConst;
73  using std::move;
74  using std::swap;
75 
76 
86  template<class SEQ>
89  {
90  using Val = typename SEQ::value_type;
91  using Idx = IndexTable<Val>;
92 
93  Idx refIdx_;
94  SEQ const& currentData_;
95 
96 
97  using DiffStep = typename ListDiffLanguage<Val>::DiffStep;
98 
100  class DiffFrame;
101 
102 
103 
104 
105  public:
106  explicit
107  DiffDetector(SEQ const& refSeq)
108  : refIdx_(refSeq)
109  , currentData_(refSeq)
110  { }
111 
112 
117  bool
118  isChanged() const
119  {
120  auto snapshot = refIdx_.begin();
121  for (auto const& elm : currentData_)
122  if (snapshot != refIdx_.end() && elm != *snapshot++)
123  return true;
124 
125  return false;
126  }
127 
128 
131 
146  Diff
148  {
149  Idx mark (currentData_);
150  swap (mark, refIdx_); // mark now refers to old reference point
151  return Diff(DiffFrame(refIdx_, move(mark)));
152  }
153  };
154 
155 
156 
157 
167  template<class SEQ>
169  {
170  Idx old_;
171  Idx* new_;
172  size_t oldHead_=0,
173  newHead_=0;
174 
176 
177  DiffStep currentStep_;
178 
179 
180  public:
181  DiffFrame(Idx& current, Idx&& refPoint)
182  : old_(refPoint)
183  , new_(&current)
184  , currentStep_(establishNextState())
185  { }
186 
187 
188  /* === Iteration control API for IterStateWrapper === */
189 
190  bool
191  checkPoint() const
192  {
193  return token.NIL != currentStep_;
194  }
195 
196  DiffStep&
197  yield() const
198  {
199  REQUIRE (checkPoint());
200  return unConst(this)->currentStep_;
201  }
202 
203  void
204  iterNext()
205  {
206  currentStep_ = this->establishNextState();
207  }
208 
209  private:
210  DiffStep
211  establishNextState()
212  {
213  if (canPick())
214  {
215  consumeOld();
216  return token.pick (consumeNew());
217  }
218  if (canDelete())
219  return token.del (consumeOld());
220  if (canInsert())
221  return token.ins (consumeNew());
222  if (needFetch())
223  return token.find (consumeNew());
224  if (obsoleted())
225  return token.skip (consumeOld());
226 
227  return token.NIL;
228  }
229 
230  bool hasOld() const { return oldHead_ < old_.size(); }
231  bool hasNew() const { return newHead_ < new_->size(); }
232  bool canPick() const { return hasOld() && hasNew() && oldElm()==newElm(); }
233  bool canDelete() const { return hasOld() && !new_->contains(oldElm()); }
234  bool canInsert() const { return hasNew() && !old_.contains(newElm()); }
235  bool needFetch() const { return hasNew() && oldHead_ < old_.pos(newElm()); }
236  bool obsoleted() const { return hasOld() && newHead_ > new_->pos(oldElm()); }
237 
238  Val const& oldElm() const { return old_.getElement (oldHead_); }
239  Val const& newElm() const { return new_->getElement (newHead_); }
240  Val const& consumeOld() { return old_.getElement (oldHead_++); }
241  Val const& consumeNew() { return new_->getElement (newHead_++); }
242  };
243 
244 
246  template<class SEQ>
248 
249 
250 
251 
252 }} // namespace lib::diff
253 #endif /*LIB_DIFF_LIST_DIFF_DETECTOR_H*/
A token language to represent changes in a list of elements.
bool isChanged() const
does the current state of the underlying sequence differ from the state embodied into the last refere...
Helper template(s) for creating Lumiera Forward Iterators.
Diff pullUpdate()
Diff generation core operation.
Any copy and copy construction prohibited.
Definition: nocopy.hpp:46
Implementation namespace for support and library code.
A diff generation process is built on top of an "old" reference point and a "new" state of the underl...
Mix-Ins to allow or prohibit various degrees of copying and cloning.
Another Lumiera Forward Iterator building block, based on incorporating a state type right into the i...
Detect and describe changes in a monitored data sequence.
Generic lookup table for a sequence of unique values.
lib::IterStateWrapper< DiffStep, DiffFrame > Diff
Diff is a iterator to yield a sequence of DiffStep elements.
static const DiffStep NIL
fixed "invalid" marker token
static ListDiffLanguage< Val > token
allocate static storage for the diff language token builder functions