Lumiera  0.pre.03
»edit your freedom«
itertools.hpp
Go to the documentation of this file.
1 /*
2  ITERTOOLS.hpp - collection of tools for building and combining iterators
3 
4  Copyright (C) Lumiera.org
5  2009, 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 
76 #ifndef LIB_ITERTOOLS_H
77 #define LIB_ITERTOOLS_H
78 
79 
80 #include "lib/iter-adapter.hpp"
82 #include "lib/meta/function.hpp"
83 #include "lib/meta/trait.hpp"
84 #include "lib/wrapper.hpp"
85 #include "lib/util.hpp"
86 
87 #include <functional>
88 #include <utility>
89 
90 
91 
92 namespace lib {
93 
94  using std::forward;
95  using std::function;
96  using util::unConst;
97 
99 
100 
101 
113  template<class IT>
115  {
116  IT source_;
117 
118  IdentityCore (IT&& orig)
119  : source_{forward<IT>(orig)}
120  { }
121  IdentityCore (IT const& orig)
122  : source_{orig}
123  { }
124 
125  IT&
126  pipe ()
127  {
128  return source_;
129  }
130 
131  IT const&
132  pipe () const
133  {
134  return source_;
135  }
136 
137  void
138  advance ()
139  {
140  ++source_;
141  }
142 
143  bool
144  evaluate () const
145  {
146  return bool(source_);
147  }
148 
149  typedef typename IT::pointer pointer;
150  typedef typename IT::reference reference;
151  typedef typename IT::value_type value_type;
152  };
153 
154 
163  template<class CORE>
164  class IterTool
165  {
166 
167  protected: /* == iteration control == */
168  CORE core_;
169 
170  bool
171  hasData() const
172  {
173  return core_.evaluate()
174  || unConst(this)->iterate();
175  } // to skip irrelevant results doesn't count as "mutation"
176 
177  bool
178  iterate ()
179  {
180  if (!core_.pipe()) return false;
181 
182  do core_.advance();
183  while (core_.pipe() && !core_.evaluate());
184 
185  return bool{core_.pipe()};
186  }
187 
188  void
189  _maybe_throw() const
190  {
191  if (!isValid())
192  _throwIterExhausted();
193  }
194 
195 
196 
197  public:
198  typedef typename CORE::pointer pointer;
199  typedef typename CORE::reference reference;
200  typedef typename CORE::value_type value_type;
201 
202 
203  IterTool (CORE&& setup)
204  : core_{std::move(setup)}
205  {
206  hasData();
207  }
208 
209  explicit
210  operator bool() const
211  {
212  return isValid();
213  }
214 
215 
216 
217  /* === lumiera forward iterator concept === */
218 
219  reference
220  operator*() const
221  {
222  _maybe_throw();
223  return *core_.pipe();
224  }
225 
226  pointer
227  operator->() const
228  {
229  _maybe_throw();
230  return & *core_.pipe();
231  }
232 
233  IterTool&
234  operator++()
235  {
236  _maybe_throw();
237  iterate();
238  return *this;
239  }
240 
241  bool
242  isValid () const
243  {
244  return hasData();
245  }
246 
247  bool
248  empty () const
249  {
250  return not isValid();
251  }
252 
253  };
254 
255 
256  template<class CX>
257  inline bool
258  operator== (IterTool<CX> const& it1, IterTool<CX> const& it2)
259  {
260  return (!it1 && !it2 )
261  || ( it1 && it2 && (*it1) == (*it2) )
262  ;
263  }
264 
265  template<class CX>
266  inline bool
267  operator!= (IterTool<CX> const& ito1, IterTool<CX> const& ito2)
268  {
269  return not (ito1 == ito2);
270  }
271 
272 
273 
274 
275 
276 
277 
278 
287  template<class IT>
288  struct FilterCore
289  : IdentityCore<IT>
290  {
291  using Raw = IdentityCore<IT>;
292  using Val = typename IT::reference;
293 
294 
295  function<bool(Val)> predicate_;
296 
297  bool
298  evaluate () const
299  {
300  return Raw::pipe()
301  && currVal_isOK();
302  }
303 
304 
305  mutable bool cached_;
306  mutable bool isOK_;
307 
308  bool
309  currVal_isOK () const
310  {
311  return (cached_ && isOK_)
312  || (cached_ = true
313  &&(isOK_ = predicate_(*Raw::pipe())));
314  }
315 
316  void
317  advance ()
318  {
319  cached_ = false;
320  Raw::advance();
321  }
322 
323 
324  template<typename PRED>
325  FilterCore (IT&& source, PRED prediDef)
326  : Raw{forward<IT>(source)}
327  , predicate_(prediDef) // induces a signature check
328  , cached_(false) // not yet cached
329  , isOK_(false) // not yet relevant
330  { }
331 
332  template<typename PRED>
333  FilterCore (IT const& source, PRED prediDef)
334  : Raw{source}
335  , predicate_(prediDef)
336  , cached_(false)
337  , isOK_(false)
338  { }
339  };
340 
341 
345  template<class IT>
347  : public IterTool<FilterCore<IT>>
348  {
349  typedef FilterCore<IT> _Filter;
350  typedef IterTool<_Filter> _Impl;
351 
352  public:
353  static bool acceptAll(typename _Filter::Val) { return true; }
354 
355 
356  FilterIter ()
357  : _Impl{FilterCore<IT>(IT(), acceptAll)}
358  { }
359 
360  template<typename PRED>
361  FilterIter (IT const& src, PRED filterPredicate)
362  : _Impl{_Filter(src, filterPredicate)}
363  { }
364 
365  template<typename PRED>
366  FilterIter (IT&& src, PRED filterPredicate)
367  : _Impl{_Filter(forward<IT>(src), filterPredicate)}
368  { }
369 
371  };
372 
373 
379  template<class IT, typename PRED>
380  inline auto
381  filterIterator (IT const& src, PRED filterPredicate)
382  {
383  return FilterIter<IT>{src, filterPredicate};
384  }
385 
386  template<class IT, typename PRED>
387  inline auto
388  filterIterator (IT&& src, PRED filterPredicate)
389  {
390  using SrcIT = typename std::remove_reference<IT>::type;
391  return FilterIter<SrcIT>{forward<IT>(src), filterPredicate};
392  }
393 
394 
418  template<class IT>
420  : public FilterIter<IT>
421  {
422  using _Filter = FilterCore<IT>;
423  using Val = typename _Filter::Val;
424 
425  void
426  reEvaluate()
427  {
428  this->core_.cached_ = false;
429  this->hasData(); // re-evaluate head element
430  }
431 
432  public:
434 
435  template<typename PRED>
436  ExtensibleFilterIter (IT&& src, PRED initialFilterPredicate)
437  : FilterIter<IT>{forward<IT>(src), initialFilterPredicate}
438  { }
439  template<typename PRED>
440  ExtensibleFilterIter (IT const& src, PRED initialFilterPredicate)
441  : FilterIter<IT>{src, initialFilterPredicate}
442  { }
443 
444  ExtensibleFilterIter (IT&& src)
446  { }
447 
448  // standard copy operations acceptable
449 
450 
453  IT&
454  underlying()
455  {
456  return this->core_.source_;
457  }
458 
459 
460  template<typename COND>
462  andFilter (COND conjunctiveClause)
463  {
464  function<bool(Val)>& filter = this->core_.predicate_;
465 
466  filter = [=](Val val)
467  {
468  return filter(val)
469  and conjunctiveClause(val);
470  };
471  reEvaluate();
472  return *this;
473  }
474 
475  template<typename COND>
477  andNotFilter (COND conjunctiveClause)
478  {
479  function<bool(Val)>& filter = this->core_.predicate_;
480 
481  filter = [=](Val val)
482  {
483  return filter(val)
484  and not conjunctiveClause(val);
485  };
486  reEvaluate();
487  return *this;
488  }
489 
490  template<typename COND>
492  orFilter (COND disjunctiveClause)
493  {
494  function<bool(Val)>& filter = this->core_.predicate_;
495 
496  filter = [=](Val val)
497  {
498  return filter(val)
499  or disjunctiveClause(val);
500  };
501  reEvaluate();
502  return *this;
503  }
504 
505  template<typename COND>
507  orNotFilter (COND disjunctiveClause)
508  {
509  function<bool(Val)>& filter = this->core_.predicate_;
510 
511  filter = [=](Val val)
512  {
513  return filter(val)
514  or not disjunctiveClause(val);
515  };
516  reEvaluate();
517  return *this;
518  }
519 
520 
521  template<typename COND>
523  setNewFilter (COND entirelyDifferentPredicate)
524  {
525  this->core_.predicate_ = entirelyDifferentPredicate;
526  reEvaluate();
527  return *this;
528  }
529 
531  flipFilter ()
532  {
533  function<bool(Val)>& filter = this->core_.predicate_;
534 
535  filter = [=](Val val)
536  {
537  return not filter(val);
538  };
539  reEvaluate();
540  return *this;
541  }
542  };
543 
544 
545 
551  template<typename VAL>
553  {
555 
556  Item prev_;
557 
558  public:
559  bool
560  operator() (VAL const& elm)
561  {
562  if (prev_ &&
563  (*prev_ == elm))
564  return false;
565 
566  // element differs from predecessor
567  prev_ = elm;
568  return true;
569  }
570 
571  typedef bool result_type;
572  };
573 
574 
575 
576 
577 
578 
579 
580 
581 
582 
587  template<typename VAL>
589  {
591 
592  Item theValue_;
593 
594  public:
596 
597  SingleValCore (VAL&& something)
598  : theValue_{forward<VAL> (something)}
599  { }
600 
601  Item const&
602  pipe () const
603  {
604  return theValue_;
605  }
606 
607  void
608  advance ()
609  {
610  theValue_.reset();
611  }
612 
613  bool
614  evaluate () const
615  {
616  return theValue_.isValid();
617  }
618 
619  typedef std::remove_reference_t<VAL> * pointer;
620  typedef std::remove_reference_t<VAL> & reference;
621  typedef std::remove_reference_t<VAL> value_type;
622  };
623 
624 
634  template<class VAL>
636  : public IterTool<SingleValCore<VAL>>
637  {
640 
641  public:
642  SingleValIter ()
644  { }
645 
646  SingleValIter (VAL&& something)
647  : _IteratorImpl{_ValHolder{forward<VAL>(something)}}
648  { }
649 
651  };
652 
653 
654 
662  template<class VAL>
663  inline auto
664  singleValIterator (VAL&& something)
665  {
666  return SingleValIter<VAL>{forward<VAL>(something)};
667  }
668 
669 
671  template<class VAL>
672  inline auto
674  {
675  return SingleValIter<VAL>();
676  }
677 
678 
679 
680 
681 
687  template<class IT, class VAL>
689  {
690  typedef typename IT::reference InType;
692 
693  function<VAL(InType)> trafo_;
694 
695  IT source_;
696  Item treated_;
697 
698  void
699  processItem ()
700  {
701  if (source_)
702  treated_ = trafo_(*source_);
703  else
704  treated_.reset();
705  }
706 
707 
708 
709  public:
710  TransformingCore ()
711  : trafo_()
712  , source_()
713  , treated_()
714  { }
715 
716  template<typename FUN>
717  TransformingCore (IT&& orig, FUN processor)
718  : trafo_(processor) // induces a signature check
719  , source_(forward<IT> (orig))
720  {
721  processItem();
722  }
723 
724  template<typename FUN>
725  TransformingCore (IT const& orig, FUN processor)
726  : trafo_(processor) // induces a signature check
727  , source_(orig)
728  {
729  processItem();
730  }
731 
732  Item const&
733  pipe () const
734  {
735  return treated_;
736  }
737 
738  void
739  advance ()
740  {
741  ++source_;
742  processItem();
743  }
744 
745  bool
746  evaluate () const
747  {
748  return bool(source_);
749  }
750 
751  using pointer = typename ValueTypeBinding<VAL>::pointer;
752  using reference = typename ValueTypeBinding<VAL>::reference;
753  using value_type = typename ValueTypeBinding<VAL>::value_type;
754  };
755 
756 
762  template<class IT, class VAL>
764  : public IterTool<TransformingCore<IT,VAL>>
765  {
768 
769  public:
770  TransformIter ()
771  : _IteratorImpl(_Trafo())
772  { }
773 
774  template<typename FUN>
775  TransformIter (IT&& src, FUN trafoFunc)
776  : _IteratorImpl{_Trafo(forward<IT>(src), trafoFunc)}
777  { }
778  template<typename FUN>
779  TransformIter (IT const& src, FUN trafoFunc)
780  : _IteratorImpl{_Trafo(src, trafoFunc)}
781  { }
782 
784  };
785 
786 
787 
788 
789 
795  template<class IT, typename FUN>
796  inline auto
797  transformIterator (IT const& src, FUN processingFunc)
798  {
799  using OutVal = typename lib::meta::_Fun<FUN>::Ret;
800  return TransformIter<IT,OutVal>{src,processingFunc};
801  }
802 
803  template<class IT, typename FUN>
804  inline auto
805  transformIterator (IT&& src, FUN processingFunc)
806  {
807  using SrcIT = typename std::remove_reference<IT>::type;
808  using OutVal = typename lib::meta::_Fun<FUN>::Ret;
809  return TransformIter<SrcIT,OutVal>{forward<IT>(src), processingFunc};
810  }
811 
812 
813 
814 
815  /* === utility functions === */
816 
817  template<class IT, class CON>
818  inline void
819  append_all (IT iter, CON& container)
820  {
821  for ( ; iter; ++iter )
822  container.push_back (*iter);
823  }
824 
825 
826  template<class IT>
827  inline typename IT::value_type
828  pull_last (IT iter)
829  {
830  using Val = typename IT::value_type;
831  using Item = wrapper::ItemWrapper<Val>;
832 
833  Item lastElm;
834 
835  while (iter)
836  {
837  lastElm = *iter;
838  ++iter;
839  }
840 
841  if (lastElm)
842  return *lastElm;
843  else
844  throw lumiera::error::State ("attempt to retrieve the last element "
845  "of an exhausted or empty iterator"
846  ,lumiera::error::LUMIERA_ERROR_ITER_EXHAUST);
847  }
848 
849 
850 
853  template<class IT>
854  inline auto
855  filterRepetitions (IT const& source)
856  {
857  using Val = typename meta::ValueTypeBinding<IT>::value_type;
858  return filterIterator (source, SkipRepetition<Val>());
859  }
860 
861  template<class IT>
862  inline auto
863  filterRepetitions (IT&& source)
864  {
865  using Val = typename meta::ValueTypeBinding<IT>::value_type;
866  return filterIterator (forward<IT>(source), SkipRepetition<Val>() );
867  }
868 
869 
870 
871 
872 
873 } // namespace lib
874 #endif
Iterator tool filtering pulled data according to a predicate.
Definition: itertools.hpp:346
bool currVal_isOK() const
<
Definition: itertools.hpp:309
SingleValCore()
passive and empty
Definition: itertools.hpp:595
A neutral identity-function core, also serving as point-of reference how any core is intended to work...
Definition: itertools.hpp:114
bool filter(Placement< DummyMO > const &candidate)
a filter predicate to pick some objects from a resultset.
Implementation of a singleton value holder, which discards the contained value once "iterated"...
Definition: itertools.hpp:588
Helper template(s) for creating Lumiera Forward Iterators.
Type re-binding helper template for custom containers and adapters.
bool operator==(PtrDerefIter< I1 > const &il, PtrDerefIter< I2 > const &ir)
Supporting equality comparisons...
Helper for uniform access to function signature types.
Definition: function.hpp:108
Additional capabilities for FilterIter, allowing to extend the filter condition underway.
Definition: itertools.hpp:419
#define ENABLE_USE_IN_STD_RANGE_FOR_LOOPS(ITER)
use a given Lumiera Forward Iterator in standard "range for loops"
Implementation namespace for support and library code.
Derived specific exceptions within Lumiera&#39;s exception hierarchy.
Definition: error.hpp:199
Metaprogramming tools for transforming functor types.
Standard functionality to build up any iterator tool.
Definition: itertools.hpp:164
auto nilIterator()
not-anything-at-all iterator
Definition: itertools.hpp:673
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
Iterator tool treating pulled data by a custom transformation (function)
Definition: itertools.hpp:763
Helper: predicate returning true whenever the argument value changes during a sequence of invocations...
Definition: itertools.hpp:552
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:664
Helpers for type detection, type rewriting and metaprogramming.
Implementation of the filter logic.
Definition: itertools.hpp:288
auto setup(FUN &&workFun)
Helper: setup a Worker-Pool configuration for the test.
Pseudo-Iterator to yield just a single value.
Definition: itertools.hpp:635
Implementation of custom processing logic.
Definition: itertools.hpp:688
Type re-binding helper template for creating nested typedefs usable by custom containers and iterator...
auto filterIterator(IT const &src, PRED filterPredicate)
Build a FilterIter: convenience free function shortcut, picking up the involved types automatically...
Definition: itertools.hpp:381
auto transformIterator(IT const &src, FUN processingFunc)
Build a TransformIter: convenience free function shortcut, picking up the involved types automaticall...
Definition: itertools.hpp:797
Library implementation: smart-pointer variations, wrappers and managing holders.
auto filterRepetitions(IT const &source)
filters away repeated values emitted by source iterator
Definition: itertools.hpp:855