Lumiera  0.pre.03
»edit your freedom«
iter-source.hpp
Go to the documentation of this file.
1 /*
2  ITER-SOURCE.hpp - an interface to build an opaque iterator-based data source
3 
4  Copyright (C)
5  2010, 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 
42 #ifndef LIB_ITER_SOURCE_H
43 #define LIB_ITER_SOURCE_H
44 
45 
46 #include "lib/meta/util.hpp"
47 #include "lib/iter-adapter.hpp"
48 #include "lib/itertools.hpp"
49 #include "lib/nocopy.hpp"
50 
51 #include <type_traits>
52 #include <utility>
53 #include <string>
54 #include <memory>
55 
56 
57 
58 
59 namespace lib {
60 
61  using std::string;
62  using std::shared_ptr;
63  using std::forward;
64 
65 
66 
78  template<typename TY>
79  class IterSource
80  {
81 
82  protected: /* == data source API to implement == */
83 
84  typedef TY* Pos;
86 
88 
91  virtual Pos firstResult () =0;
92 
97  virtual void nextResult(Pos& pos) =0;
98 
105  virtual void disconnect () { }
106 
107 
108 
109  public:
110  virtual ~IterSource() { };
111 
112  virtual
113  operator string() const
114  {
115  return "IterSource<" + lib::meta::typeStr<TY>()+ ">";
116  }
117 
118 
119  /* == Iteration control API for IterAdapter frontend == */
120 
121  friend bool
122  checkPoint (DataHandle const&, Pos const& pos)
123  {
124  return bool(pos);
125  }
126 
127  friend void
128  iterNext (DataHandle& source, Pos& pos)
129  {
130  ASSERT (source);
131  source->nextResult(pos);
132  }
133 
134 
135  /* == public builder API to create instances == */
136 
137  struct iterator
138  : IterAdapter<Pos, DataHandle>
139  {
141  using _I::IterAdapter;
142 
143  operator string() const {return _I::source()? string(*_I::source()) : "⟂"; }
144  };
145 
150  static iterator
151  build (IterSource& sourceImpl)
152  {
153  return std::move(
154  startIteration (DataHandle{&sourceImpl, &detach_without_destroy}));
155  }
156 
163  static iterator
164  build (IterSource* sourceImplObject)
165  {
166  return std::move(
167  startIteration (DataHandle{sourceImplObject, &destroy_managed_source}));
168  }
169 
170  static iterator EMPTY_SOURCE;
171 
172  using value_type = TY;
173  using reference = TY&;
174  using pointer = TY*;
175 
176 
177 
178  private:
179  static iterator
180  startIteration (DataHandle sourceHandle)
181  {
182  REQUIRE (sourceHandle);
183  Pos first = sourceHandle->firstResult();
184  return {move(sourceHandle), first};
185  }
186 
187 
188  static void
189  detach_without_destroy (IterSource * source)
190  {
191  WARN_IF (!source, library, "IterSource deleter called with NULL source pointer");
192  if (source)
193  source->disconnect();
194  }
195 
196  static void
197  destroy_managed_source (IterSource * source)
198  {
199  WARN_IF (!source, library, "IterSource deleter called with NULL source pointer");
200  if (source)
201  {
202  source->disconnect();
203  delete source;
204  }
205  }
206  };
207 
208 
210  template<typename TY>
212 
213 
214 
215 
216 
223  template<class IT, class ISO = IterSource<typename meta::ValueTypeBinding<IT>::value_type>>
225  : public ISO
227  {
228  IT src_;
229 
230  protected:
231  using Pos = typename ISO::Pos;
232 
233  Pos
234  firstResult ()
235  {
236  if (!src_)
237  return 0;
238  else
239  return & *src_;
240  }
241 
242  void
243  nextResult (Pos& pos)
244  {
245  if (!pos) return;
246  if (src_) ++src_;
247  if (src_)
248  pos = & *src_;
249  else
250  pos = 0;
251  }
252 
253 
254 
255  public:
256  WrappedLumieraIter (IT const& orig)
257  : src_(orig)
258  { }
259 
260  WrappedLumieraIter (IT&& orig)
261  : src_(forward<IT>(orig))
262  { }
263 
264 
265  protected:
266  IT& wrappedIter() { return src_; }
267  IT const& wrappedIter() const { return src_; }
268  };
269 
270 
271 
272 
273  /* === pre-defined Adapters for frequently used Containers === */
274 
275  namespace iter_source {
276  namespace { // traits and helpers...
277 
278  template<class CON>
279  struct _SeqT
280  {
281  using Val = typename CON::iterator::value_type;
282  using Iter = typename IterSource<Val>::iterator;
283  };
284 
285  template<class IT>
286  struct _RangeT
287  {
288  using Val = typename IT::value_type;
289  using Iter = typename IterSource<Val>::iterator;
290  };
291 
292  template<class MAP>
293  struct _MapT
294  {
295  using Key = typename MAP::key_type;
296  using Val = typename MAP::value_type::second_type;
297  using KeyIter = typename IterSource<Key>::iterator;
298  using ValIter = typename IterSource<Val>::iterator;
299  };
300 
301 
302  template<class IT>
303  struct _IterT
304  {
305  using Src = typename std::remove_reference<IT>::type;
306  using Val = typename Src::value_type;
307  using Iter = typename IterSource<Val>::iterator;
308  };
309 
310  template<class IT, class FUN>
312  {
313  using Src = typename std::remove_reference<IT>::type;
314  using ResVal = typename lib::meta::_Fun<FUN>::Ret;
316  using Iter = typename IterSource<ResVal>::iterator;
317  };
318 
319  template<class IT>
320  struct _PairIterT
321  {
322  using Src = typename std::remove_reference<IT>::type;
323  using PairType = typename Src::value_type;
324  using ValType = typename PairType::second_type;
325  using ConstKeyType = typename PairType::first_type;
326 
327  // since we're returning the keys always by value,
328  // we can strip the const added by the STL map types
329  using KeyType = typename std::remove_const<ConstKeyType>::type;
330 
333 
334  static KeyType takeFirst (PairType const& pair) { return pair.first; }
335  static ValType takeSecond(PairType const& pair) { return pair.second;}
336  };
337 
338 
339  template<class IT>
340  typename _PairIterT<IT>::KeyIter
341  takePairFirst (IT&& source)
342  {
343  return transformIterator(forward<IT>(source), _PairIterT<IT>::takeFirst );
344  }
345 
346  template<class IT>
347  typename _PairIterT<IT>::ValIter
348  takePairSecond (IT&& source)
349  {
350  return transformIterator(forward<IT>(source), _PairIterT<IT>::takeSecond );
351  }
352 
353  } //(END) type helpers...
354 
355 
356 
360  template<class IT>
361  typename _IterT<IT>::Iter
363  {
364  using Src = typename _IterT<IT>::Src;
365  using Val = typename _IterT<IT>::Val;
366 
367  return IterSource<Val>::build (new WrappedLumieraIter<Src> (forward<IT>(source)));
368  }
369 
370 
376  template<typename VAL>
377  auto
378  singleVal (VAL&& something)
379  {
380  using Src = decltype(singleValIterator (forward<VAL>(something)));
381  using Val = typename _IterT<Src>::Val;
382 
383  return IterSource<Val>::build (new WrappedLumieraIter<Src>{singleValIterator (forward<VAL>(something))});
384  }
385 
386 
396  template<class IT, class FUN>
397  typename _TransformIterT<IT,FUN>::Iter
398  transform (IT&& source, FUN processingFunc)
399  {
400  typedef typename _TransformIterT<IT,FUN>::ResVal ValType;
401  typedef typename _TransformIterT<IT,FUN>::TransIter TransIT;
402 
405  transformIterator (forward<IT>(source), processingFunc)));
406  }
407 
408 
412  template<class MAP>
413  typename _MapT<MAP>::KeyIter
414  eachMapKey (MAP& map)
415  {
416  using Range = RangeIter<typename MAP::iterator>;
417 
418  Range contents (map.begin(), map.end());
419  return wrapIter (takePairFirst (contents));
420  }
421 
422 
426  template<class MAP>
427  typename _MapT<MAP>::ValIter
428  eachMapVal (MAP& map)
429  {
430  using Range = RangeIter<typename MAP::iterator>;
431 
432  Range contents (map.begin(), map.end());
433  return wrapIter (takePairSecond(contents));
434  }
435 
436 
442  template<class MAP>
443  typename _MapT<MAP>::KeyIter
444  eachDistinctKey (MAP& map)
445  {
446  using Range = RangeIter<typename MAP::iterator>;
447 
448  Range contents (map.begin(), map.end());
449  return wrapIter (filterRepetitions (takePairFirst(contents)));
450  }
451 
452 
457  template<class MAP>
458  typename _MapT<MAP>::ValIter
459  eachValForKey (MAP& map, typename _MapT<MAP>::Key key)
460  {
461  using Pos = typename MAP::iterator;
462  using Range = RangeIter<Pos>;
463 
464  std::pair<Pos,Pos> valuesForKey = map.equal_range(key);
465  Range contents (valuesForKey.first, valuesForKey.second);
466  return wrapIter (takePairSecond(contents));
467  }
468 
469 
476  template<class CON>
477  typename _SeqT<CON>::Iter
478  eachEntry (CON& container)
479  {
480  using ValType = typename _SeqT<CON>::Val;
481  using Range = RangeIter<typename CON::iterator>;
482 
483  Range contents (container.begin(), container.end());
485  }
486 
487 
491  template<class IT>
492  typename _RangeT<IT>::Iter
493  eachEntry (IT const& begin, IT const& end)
494  {
495  using ValType = typename _RangeT<IT>::Val;
496  using Range = RangeIter<IT>;
497 
498  Range contents (begin, end);
500  }
501 
502 
503 }} // namespace lib::iter_source
504 #endif
_IterT< IT >::Iter wrapIter(IT &&source)
wraps a given Lumiera Forward Iterator, exposing just a IterSource based frontend.
static iterator EMPTY_SOURCE
storage for the empty data-source constant
Helper template(s) for creating Lumiera Forward Iterators.
Simple and lightweight helpers for metaprogramming and type detection.
Any copy and copy construction prohibited.
Definition: nocopy.hpp:37
Helper for uniform access to function signature types.
Definition: function.hpp:99
ConRef source()
allow derived classes to access backing container
Implementation namespace for support and library code.
virtual void nextResult(Pos &pos)=0
iteration step: switch on to the next element.
Iteration source interface to abstract a data source, which then can be accessed through IterAdapter ...
Definition: iter-source.hpp:79
Mix-Ins to allow or prohibit various degrees of copying and cloning.
Iterator tool treating pulled data by a custom transformation (function)
Definition: itertools.hpp:754
auto singleVal(VAL &&something)
an IterSource frontend to return just a single value once.
_MapT< MAP >::KeyIter eachMapKey(MAP &map)
_TransformIterT< IT, FUN >::Iter transform(IT &&source, FUN processingFunc)
pipes a given Lumiera Forward Iterator through a transformation function and wraps the resulting tran...
auto singleValIterator(VAL &&something)
Build a SingleValIter: convenience free function shortcut, to pick up just any value and wrap it as L...
Definition: itertools.hpp:655
_MapT< MAP >::ValIter eachMapVal(MAP &map)
static iterator build(IterSource &sourceImpl)
build an iterator frontend for the given source,
virtual Pos firstResult()=0
iteration start: prepare the first element.
Helpers for working with iterators based on the pipeline model.
Accessing a STL element range through a Lumiera forward iterator, An instance of this iterator adapte...
auto transformIterator(IT const &src, FUN processingFunc)
Build a TransformIter: convenience free function shortcut, picking up the involved types automaticall...
Definition: itertools.hpp:788
Standard implementation of the IterSource interface: a wrapped "Lumiera Forward Iterator".
string contents(Rec const &object)
render the child elements as string data for test/verification
Adapter for building an implementation of the »Lumiera Forward Iterator« concept. ...
virtual void disconnect()
disconnect the data source / iteration frontend.
_SeqT< CON >::Iter eachEntry(CON &container)
auto filterRepetitions(IT const &source)
filters away repeated values emitted by source iterator
Definition: itertools.hpp:846
static iterator build(IterSource *sourceImplObject)
build an iterator frontend, thereby managing the given heap allocated source object instance...