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)
5  2015, 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 
48 #ifndef LIB_DIFF_LIST_DIFF_DETECTOR_H
49 #define LIB_DIFF_LIST_DIFF_DETECTOR_H
50 
51 
52 #include "lib/diff/list-diff.hpp"
53 #include "lib/diff/index-table.hpp"
54 #include "lib/iter-adapter.hpp"
55 #include "lib/nocopy.hpp"
56 
57 #include <utility>
58 
59 
60 namespace lib {
61 namespace diff{
62 
63  using util::unConst;
64  using std::move;
65  using std::swap;
66 
67 
77  template<class SEQ>
80  {
81  using Val = typename SEQ::value_type;
82  using Idx = IndexTable<Val>;
83 
84  Idx refIdx_;
85  SEQ const& currentData_;
86 
87 
88  using DiffStep = typename ListDiffLanguage<Val>::DiffStep;
89 
91  class DiffFrame;
92 
93 
94 
95 
96  public:
97  explicit
98  DiffDetector(SEQ const& refSeq)
99  : refIdx_(refSeq)
100  , currentData_(refSeq)
101  { }
102 
103 
108  bool
109  isChanged() const
110  {
111  auto snapshot = refIdx_.begin();
112  for (auto const& elm : currentData_)
113  if (snapshot != refIdx_.end() && elm != *snapshot++)
114  return true;
115 
116  return false;
117  }
118 
119 
122 
137  Diff
139  {
140  Idx mark (currentData_);
141  swap (mark, refIdx_); // mark now refers to old reference point
142  return Diff(DiffFrame(refIdx_, move(mark)));
143  }
144  };
145 
146 
147 
148 
158  template<class SEQ>
160  {
161  Idx old_;
162  Idx* new_;
163  size_t oldHead_=0,
164  newHead_=0;
165 
167 
168  DiffStep currentStep_;
169 
170 
171  public:
172  DiffFrame(Idx& current, Idx&& refPoint)
173  : old_(refPoint)
174  , new_(&current)
175  , currentStep_(establishNextState())
176  { }
177 
178 
179  /* === Iteration control API for IterStateWrapper === */
180 
181  bool
182  checkPoint() const
183  {
184  return token.NIL != currentStep_;
185  }
186 
187  DiffStep&
188  yield() const
189  {
190  REQUIRE (checkPoint());
191  return unConst(this)->currentStep_;
192  }
193 
194  void
195  iterNext()
196  {
197  currentStep_ = this->establishNextState();
198  }
199 
200  private:
201  DiffStep
202  establishNextState()
203  {
204  if (canPick())
205  {
206  consumeOld();
207  return token.pick (consumeNew());
208  }
209  if (canDelete())
210  return token.del (consumeOld());
211  if (canInsert())
212  return token.ins (consumeNew());
213  if (needFetch())
214  return token.find (consumeNew());
215  if (obsoleted())
216  return token.skip (consumeOld());
217 
218  return token.NIL;
219  }
220 
221  bool hasOld() const { return oldHead_ < old_.size(); }
222  bool hasNew() const { return newHead_ < new_->size(); }
223  bool canPick() const { return hasOld() && hasNew() && oldElm()==newElm(); }
224  bool canDelete() const { return hasOld() && !new_->contains(oldElm()); }
225  bool canInsert() const { return hasNew() && !old_.contains(newElm()); }
226  bool needFetch() const { return hasNew() && oldHead_ < old_.pos(newElm()); }
227  bool obsoleted() const { return hasOld() && newHead_ > new_->pos(oldElm()); }
228 
229  Val const& oldElm() const { return old_.getElement (oldHead_); }
230  Val const& newElm() const { return new_->getElement (newHead_); }
231  Val const& consumeOld() { return old_.getElement (oldHead_++); }
232  Val const& consumeNew() { return new_->getElement (newHead_++); }
233  };
234 
235 
237  template<class SEQ>
239 
240 
241 
242 
243 }} // namespace lib::diff
244 #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:37
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 as »*State Core*...
Detect and describe changes in a monitored data sequence.
Generic lookup table for a sequence of unique values.
static const DiffStep NIL
fixed "invalid" marker token
static ListDiffLanguage< Val > token
allocate static storage for the diff language token builder functions
lib::IterStateWrapper< DiffFrame > Diff
Diff is a iterator to yield a sequence of DiffStep elements.