Lumiera 0.pre.04
»edit your freedom«
Loading...
Searching...
No Matches
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)
5 2009, 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
67#ifndef LIB_ITERTOOLS_H
68#define LIB_ITERTOOLS_H
69
70
71#include "lib/iter-adapter.hpp"
72#include "lib/item-wrapper.hpp"
74#include "lib/meta/function.hpp"
75#include "lib/meta/trait.hpp"
76#include "lib/util.hpp"
77
78#include <functional>
79#include <utility>
80
81
82
83namespace lib {
84
85 using std::forward;
86 using std::function;
87 using util::unConst;
88
90
91
92
104 template<class IT>
106 {
108
109 IdentityCore (IT&& orig)
110 : source_{forward<IT>(orig)}
111 { }
112 IdentityCore (IT const& orig)
113 : source_{orig}
114 { }
115
116 IT&
118 {
119 return source_;
120 }
121
122 IT const&
123 pipe () const
124 {
125 return source_;
126 }
127
128 void
130 {
131 ++source_;
132 }
133
134 bool
135 evaluate () const
136 {
137 return bool(source_);
138 }
139
140 using pointer = IT::pointer;
141 using reference = IT::reference;
142 using value_type = IT::value_type;
143 };
144
145
154 template<class CORE>
156 {
157
158 protected: /* == iteration control == */
159 CORE core_;
160
161 bool
162 hasData() const
163 {
164 return core_.evaluate()
165 or unConst(this)->iterate();
166 } // to skip irrelevant results doesn't count as "mutation"
167
168 bool
170 {
171 if (not core_.pipe()) return false;
172
173 do core_.advance();
174 while (core_.pipe() and not core_.evaluate());
175
176 return bool{core_.pipe()};
177 }
178
179 void
181 {
182 if (!isValid())
183 _throwIterExhausted();
184 }
185
186
187
188 public:
189 using pointer = CORE::pointer;
190 using reference = CORE::reference;
191 using value_type = CORE::value_type;
192
193
194 IterTool (CORE&& setup)
195 : core_{std::move(setup)}
196 {
197 hasData();
198 }
199
200 explicit
201 operator bool() const
202 {
203 return isValid();
204 }
205
206
207
208 /* === lumiera forward iterator concept === */
209
211 operator*() const
212 {
213 _maybe_throw();
214 return *core_.pipe();
215 }
216
217 pointer
219 {
220 _maybe_throw();
221 return & *core_.pipe();
222 }
223
224 IterTool&
226 {
227 _maybe_throw();
228 iterate();
229 return *this;
230 }
231
232 bool
233 isValid () const
234 {
235 return hasData();
236 }
237
238 bool
239 empty () const
240 {
241 return not isValid();
242 }
243
244 };
245
246
247 template<class CX>
248 inline bool
249 operator== (IterTool<CX> const& it1, IterTool<CX> const& it2)
250 {
251 return (!it1 and !it2 )
252 or ( it1 and it2 and (*it1) == (*it2) )
253 ;
254 }
255
256 template<class CX>
257 inline bool
258 operator!= (IterTool<CX> const& ito1, IterTool<CX> const& ito2)
259 {
260 return not (ito1 == ito2);
261 }
262
263
264
265
266
267
268
269
278 template<class IT>
280 : IdentityCore<IT>
281 {
283 using Val = iter::Yield<IT>;
284
285
286 function<bool(Val)> predicate_;
287
288 bool
289 evaluate () const
290 {
291 return Raw::pipe()
292 and currVal_isOK();
293 }
294
295
296 mutable bool cached_;
297 mutable bool isOK_;
298
299 bool
300 currVal_isOK () const
301 {
302 return (cached_ and isOK_)
303 or (cached_ = true
304 and (isOK_ = predicate_(*Raw::pipe())));
305 }
306
307 void
309 {
310 cached_ = false;
311 Raw::advance();
312 }
313
314
315 template<typename PRED>
316 FilterCore (IT&& source, PRED prediDef)
317 : Raw{forward<IT>(source)}
318 , predicate_(prediDef) // induces a signature check
319 , cached_(false) // not yet cached
320 , isOK_(false) // not yet relevant
321 { }
322
323 template<typename PRED>
324 FilterCore (IT const& source, PRED prediDef)
325 : Raw{source}
326 , predicate_(prediDef)
327 , cached_(false)
328 , isOK_(false)
329 { }
330 };
331
332
336 template<class IT>
338 : public IterTool<FilterCore<IT>>
339 {
342
343 public:
344 static bool acceptAll(_Filter::Val) { return true; }
345
346
348 : _Impl{FilterCore<IT>(IT(), acceptAll)}
349 { }
350
351 template<typename PRED>
352 FilterIter (IT const& src, PRED filterPredicate)
353 : _Impl{_Filter(src, filterPredicate)}
354 { }
355
356 template<typename PRED>
357 FilterIter (IT&& src, PRED filterPredicate)
358 : _Impl{_Filter(forward<IT>(src), filterPredicate)}
359 { }
360
362 };
363
364
370 template<class IT, typename PRED>
371 inline auto
372 filterIterator (IT const& src, PRED filterPredicate)
373 {
374 return FilterIter<IT>{src, filterPredicate};
375 }
376
377 template<class IT, typename PRED>
378 inline auto
379 filterIterator (IT&& src, PRED filterPredicate)
380 {
381 using SrcIT = std::remove_reference<IT>::type;
382 return FilterIter<SrcIT>{forward<IT>(src), filterPredicate};
383 }
384
385
409 template<class IT>
411 : public FilterIter<IT>
412 {
414 using Val = _Filter::Val;
415
416 void
418 {
419 this->core_.cached_ = false;
420 this->hasData(); // re-evaluate head element
421 }
422
423 public:
425
426 template<typename PRED>
427 ExtensibleFilterIter (IT&& src, PRED initialFilterPredicate)
428 : FilterIter<IT>{forward<IT>(src), initialFilterPredicate}
429 { }
430 template<typename PRED>
431 ExtensibleFilterIter (IT const& src, PRED initialFilterPredicate)
432 : FilterIter<IT>{src, initialFilterPredicate}
433 { }
434
436 : ExtensibleFilterIter{forward<IT>(src), FilterIter<IT>::acceptAll}
437 { }
438
439 // standard copy operations acceptable
440
441
444 IT&
446 {
447 return this->core_.source_;
448 }
449
450
451 template<typename COND>
453 andFilter (COND conjunctiveClause)
454 {
455 function<bool(Val)>& filter = this->core_.predicate_;
456
457 filter = [=](Val val)
458 {
459 return filter(val)
460 and conjunctiveClause(val);
461 };
462 reEvaluate();
463 return *this;
464 }
465
466 template<typename COND>
468 andNotFilter (COND conjunctiveClause)
469 {
470 function<bool(Val)>& filter = this->core_.predicate_;
471
472 filter = [=](Val val)
473 {
474 return filter(val)
475 and not conjunctiveClause(val);
476 };
477 reEvaluate();
478 return *this;
479 }
480
481 template<typename COND>
483 orFilter (COND disjunctiveClause)
484 {
485 function<bool(Val)>& filter = this->core_.predicate_;
486
487 filter = [=](Val val)
488 {
489 return filter(val)
490 or disjunctiveClause(val);
491 };
492 reEvaluate();
493 return *this;
494 }
495
496 template<typename COND>
498 orNotFilter (COND disjunctiveClause)
499 {
500 function<bool(Val)>& filter = this->core_.predicate_;
501
502 filter = [=](Val val)
503 {
504 return filter(val)
505 or not disjunctiveClause(val);
506 };
507 reEvaluate();
508 return *this;
509 }
510
511
512 template<typename COND>
514 setNewFilter (COND entirelyDifferentPredicate)
515 {
516 this->core_.predicate_ = entirelyDifferentPredicate;
517 reEvaluate();
518 return *this;
519 }
520
523 {
524 function<bool(Val)>& filter = this->core_.predicate_;
525
526 filter = [=](Val val)
527 {
528 return not filter(val);
529 };
530 reEvaluate();
531 return *this;
532 }
533 };
534
535
536
542 template<typename VAL>
544 {
546
548
549 public:
550 bool
551 operator() (VAL const& elm)
552 {
553 if (prev_ and
554 (*prev_ == elm))
555 return false;
556
557 // element differs from predecessor
558 prev_ = elm;
559 return true;
560 }
561
562 using result_type = bool;
563 };
564
565
566
567
568
569
570
571
572
573
578 template<typename VAL>
580 {
582
584
585 public:
587
588 SingleValCore (VAL&& something)
589 : theValue_{forward<VAL> (something)}
590 { }
591
592 Item const&
593 pipe () const
594 {
595 return theValue_;
596 }
597
598 void
600 {
602 }
603
604 bool
605 evaluate () const
606 {
607 return theValue_.isValid();
608 }
609
610 using pointer = std::remove_reference_t<VAL> *;
611 using reference = std::remove_reference_t<VAL> &;
612 using value_type = std::remove_reference_t<VAL> ;
613 };
614
615
625 template<class VAL>
627 : public IterTool<SingleValCore<VAL>>
628 {
631
632 public:
636
637 SingleValIter (VAL&& something)
638 : _IteratorImpl{_ValHolder{forward<VAL>(something)}}
639 { }
640
642 };
643
644
645
653 template<class VAL>
654 inline auto
655 singleValIterator (VAL&& something)
656 {
657 return SingleValIter<VAL>{forward<VAL>(something)};
658 }
659
660
662 template<class VAL>
663 inline auto
665 {
666 return SingleValIter<VAL>();
667 }
668
669
670
671
672
678 template<class IT, class VAL>
680 {
681 using InType = iter::Yield<IT>;
683
684 function<VAL(InType)> trafo_;
685
688
689 void
691 {
692 if (source_)
694 else
695 treated_.reset();
696 }
697
698
699
700 public:
702 : trafo_()
703 , source_()
704 , treated_()
705 { }
706
707 template<typename FUN>
708 TransformingCore (IT&& orig, FUN processor)
709 : trafo_(processor) // induces a signature check
710 , source_(forward<IT> (orig))
711 {
712 processItem();
713 }
714
715 template<typename FUN>
716 TransformingCore (IT const& orig, FUN processor)
717 : trafo_(processor) // induces a signature check
718 , source_(orig)
719 {
720 processItem();
721 }
722
723 Item const&
724 pipe () const
725 {
726 return treated_;
727 }
728
729 void
731 {
732 ++source_;
733 processItem();
734 }
735
736 bool
737 evaluate () const
738 {
739 return bool(source_);
740 }
741
745 };
746
747
753 template<class IT, class VAL>
755 : public IterTool<TransformingCore<IT,VAL>>
756 {
759
760 public:
763 { }
764
765 template<typename FUN>
766 TransformIter (IT&& src, FUN trafoFunc)
767 : _IteratorImpl{_Trafo(forward<IT>(src), trafoFunc)}
768 { }
769 template<typename FUN>
770 TransformIter (IT const& src, FUN trafoFunc)
771 : _IteratorImpl{_Trafo(src, trafoFunc)}
772 { }
773
775 };
776
777
778
779
780
786 template<class IT, typename FUN>
787 inline auto
788 transformIterator (IT const& src, FUN processingFunc)
789 {
790 using OutVal = lib::meta::_Fun<FUN>::Ret;
791 return TransformIter<IT,OutVal>{src,processingFunc};
792 }
793
794 template<class IT, typename FUN>
795 inline auto
796 transformIterator (IT&& src, FUN processingFunc)
797 {
798 using SrcIT = std::remove_reference<IT>::type;
799 using OutVal = lib::meta::_Fun<FUN>::Ret;
800 return TransformIter<SrcIT,OutVal>{forward<IT>(src), processingFunc};
801 }
802
803
804
805
806 /* === utility functions === */
807
808 template<class IT, class CON>
809 inline void
810 append_all (IT iter, CON& container)
811 {
812 for ( ; iter; ++iter )
813 container.push_back (*iter);
814 }
815
816
817 template<class IT>
818 inline IT::value_type
820 {
821 using Val = IT::value_type;
822 using Item = wrapper::ItemWrapper<Val>;
823
824 Item lastElm;
825
826 while (iter)
827 {
828 lastElm = *iter;
829 ++iter;
830 }
831
832 if (lastElm)
833 return *lastElm;
834 else
835 throw lumiera::error::State ("attempt to retrieve the last element "
836 "of an exhausted or empty iterator"
837 ,lumiera::error::LUMIERA_ERROR_ITER_EXHAUST);
838 }
839
840
841
844 template<class IT>
845 inline auto
846 filterRepetitions (IT const& source)
847 {
849 return filterIterator (source, SkipRepetition<Val>());
850 }
851
852 template<class IT>
853 inline auto
854 filterRepetitions (IT&& source)
855 {
857 return filterIterator (forward<IT>(source), SkipRepetition<Val>() );
858 }
859
860
861
862
863
864} // namespace lib
865#endif
Additional capabilities for FilterIter, allowing to extend the filter condition underway.
IT & underlying()
access the unfiltered source iterator in current state
ExtensibleFilterIter & andFilter(COND conjunctiveClause)
ExtensibleFilterIter & flipFilter()
ExtensibleFilterIter(IT &&src, PRED initialFilterPredicate)
ExtensibleFilterIter & setNewFilter(COND entirelyDifferentPredicate)
FilterCore< IT > _Filter
ExtensibleFilterIter(IT const &src, PRED initialFilterPredicate)
ExtensibleFilterIter & orFilter(COND disjunctiveClause)
ExtensibleFilterIter & andNotFilter(COND conjunctiveClause)
ExtensibleFilterIter & orNotFilter(COND disjunctiveClause)
Iterator tool filtering pulled data according to a predicate.
static bool acceptAll(_Filter::Val)
IterTool< _Filter > _Impl
FilterIter(IT const &src, PRED filterPredicate)
FilterIter(IT &&src, PRED filterPredicate)
FilterCore< IT > _Filter
Standard functionality to build up any iterator tool.
CORE::pointer pointer
bool hasData() const
void _maybe_throw() const
bool isValid() const
bool empty() const
CORE::reference reference
reference operator*() const
IterTool & operator++()
CORE::value_type value_type
IterTool(CORE &&setup)
pointer operator->() const
Implementation of a singleton value holder, which discards the contained value once "iterated".
SingleValCore(VAL &&something)
bool evaluate() const
wrapper::ItemWrapper< VAL > Item
std::remove_reference_t< VAL > * pointer
SingleValCore()
passive and empty
std::remove_reference_t< VAL > value_type
Item const & pipe() const
std::remove_reference_t< VAL > & reference
Pseudo-Iterator to yield just a single value.
SingleValCore< VAL > _ValHolder
IterTool< _ValHolder > _IteratorImpl
SingleValIter(VAL &&something)
Helper: predicate returning true whenever the argument value changes during a sequence of invocations...
bool operator()(VAL const &elm)
Iterator tool treating pulled data by a custom transformation (function)
TransformingCore< IT, VAL > _Trafo
TransformIter(IT &&src, FUN trafoFunc)
TransformIter(IT const &src, FUN trafoFunc)
IterTool< _Trafo > _IteratorImpl
Implementation of custom processing logic.
ValueTypeBinding< VAL >::value_type value_type
ValueTypeBinding< VAL >::reference reference
TransformingCore(IT const &orig, FUN processor)
bool evaluate() const
wrapper::ItemWrapper< VAL > Item
function< VAL(InType)> trafo_
TransformingCore(IT &&orig, FUN processor)
iter::Yield< IT > InType
Item const & pipe() const
ValueTypeBinding< VAL >::pointer pointer
Metaprogramming tools for detecting and transforming function types.
Adapter to store and hold an element of arbitrary type in local storage.
Helper template(s) for creating Lumiera Forward Iterators.
#define ENABLE_USE_IN_STD_RANGE_FOR_LOOPS(ITER)
use a given Lumiera Forward Iterator in standard "range for loops"
RefTraits< TY >::Reference reference
RefTraits< TY >::Value value_type
RefTraits< TY >::Pointer pointer
Type re-binding helper template for creating nested typedefs usable by custom containers and iterator...
Implementation namespace for support and library code.
auto filterRepetitions(IT const &source)
filters away repeated values emitted by source iterator
bool operator==(PtrDerefIter< I1 > const &il, PtrDerefIter< I2 > const &ir)
Supporting equality comparisons...
void append_all(IT iter, CON &container)
auto nilIterator()
not-anything-at-all iterator
IT::value_type pull_last(IT iter)
auto transformIterator(IT const &src, FUN processingFunc)
Build a TransformIter: convenience free function shortcut, picking up the involved types automaticall...
bool operator!=(PtrDerefIter< I1 > const &il, PtrDerefIter< I2 > const &ir)
auto filterIterator(IT const &src, PRED filterPredicate)
Build a FilterIter: convenience free function shortcut, picking up the involved types automatically.
auto singleValIterator(VAL &&something)
Build a SingleValIter: convenience free function shortcut, to pick up just any value and wrap it as L...
LumieraError< LERR_(STATE)> State
Definition error.hpp:209
STL namespace.
OBJ * unConst(const OBJ *)
shortcut to save some typing when having to define const and non-const variants of member functions
Definition util.hpp:358
Implementation of the filter logic.
bool currVal_isOK() const
<
FilterCore(IT const &source, PRED prediDef)
bool evaluate() const
iter::Yield< IT > Val
IdentityCore< IT > Raw
FilterCore(IT &&source, PRED prediDef)
function< bool(Val)> predicate_
A neutral identity-function core, also serving as point-of reference how any core is intended to work...
IT::pointer pointer
bool evaluate() const
IdentityCore(IT &&orig)
IT::value_type value_type
IdentityCore(IT const &orig)
IT const & pipe() const
IT::reference reference
Trait template for uniform access to function signature types.
Definition function.hpp:144
Helpers for type detection, type rewriting and metaprogramming.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
Type re-binding helper template for custom containers and adapters.