/* ITERTOOLS.hpp - collection of tools for building and combining iterators Copyright (C) Lumiera.org 2009, Hermann Vosseler This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /** @file itertools.hpp ** Helpers for working with iterators based on the pipeline model. ** Iterators abstract from the underlying data container and provide ** the contained data as a source to pull values from. Based on this ** model, we can build pipelines, with filters, valves, junction points ** and transforming facilities. The templates in this header enable such, ** based on the Lumiera Forward Iterator concept. They build on generic ** programming techniques, thus are intended to be combined at compile time ** using definitive type information. Contrast this to an iterator model ** as in Java's Commons-Collections, where Iterator is an Interface based ** on virtual functions. Thus, the basic problem to overcome is the lack ** of a single common interface, which could serve as foundation for ** type inference. As a solution, we use a "onion" approach, where a ** generic base gets configured with an active core, implementing ** the filtering or processing functionality, while the base class ** (IterTool) exposes the operations necessary to comply to the ** Forward Iterator Concept. ** ** \par Filtering Iterator ** The FilterIter template can be used to build a filter into a pipeline, ** as it forwards only those elements from its source iterator, which pass ** the predicate evaluation. Anything acceptable as ctor parameter for a ** tr1::function object can be passed in as predicate, but of course the ** signature must be sensible. Please note, that -- depending on the ** predicate -- already the ctor or even a simple \c bool test might ** pull and exhaust the source iterator completely, in an attempt ** to find the first element passing the predicate test. ** ** @todo WIP WIP WIP ** @todo see Ticket #347 ** ** @see IterAdapter ** @see itertools-test.cpp ** @see contents-query.hpp */ #ifndef LIB_ITERTOOLS_H #define LIB_ITERTOOLS_H #include "lib/bool-checkable.hpp" #include "lib/iter-adapter.hpp" #include "lib/util.hpp" #include namespace lib { using std::tr1::function; using util::unConst; /** * A neutral \em identity-function core, * also serving as point-of reference how any * core is intended to work. Any core is intended * to serve as inner part of an iterator tool template. * - it provides the trait typedefs * - it abstracts the "source" * - it abstracts the local operation to be performed * - the ctor of the core sets up the configuration. * @note cores should be copyable without much overhead */ template struct IdentityCore { mutable IT source_; IdentityCore (IT const& orig) : source_(orig) { } IT& pipe () { return source_; } IT const& pipe () const { return source_; } void advance () { ++source_; } bool evaluate () const { return bool(source_); } typedef typename IT::pointer pointer; typedef typename IT::reference reference; typedef typename IT::value_type value_type; }; /** * Standard functionality to build up any iterator tool. * IterTool exposes the frontend functions necessary to * comply to the Lumiera Forward Iterator concept. * The protected part provides the building blocks * to implement the actual processing/filter logic. */ template class IterTool : public lib::BoolCheckable > { protected: /* iteration control */ CORE core_; bool hasData() const { return core_.evaluate() || unConst(this)->iterate(); } // skipping irrelevant results doesn't count as "mutation" bool iterate () { if (!core_.pipe()) return false; do core_.advance(); while (core_.pipe() && !core_.evaluate()); return core_.pipe(); } void _maybe_throw() const { if (!isValid()) _throwIterExhausted(); } public: typedef typename CORE::pointer pointer; typedef typename CORE::reference reference; typedef typename CORE::value_type value_type; IterTool (CORE const& setup) : core_(setup) { hasData(); } /* === lumiera forward iterator concept === */ reference operator*() const { _maybe_throw(); return *core_.pipe(); } pointer operator->() const { _maybe_throw(); return core_.pipe(); } IterTool& operator++() { _maybe_throw(); iterate(); return *this; } bool isValid () const { return hasData(); } bool empty () const { return !isValid(); } /// comparison is allowed to access the feed pipe from core template friend bool operator== (IterTool const& it1, IterTool const& it2); }; template inline bool operator== (IterTool const& it1, IterTool const& it2) { return it1.isValid() == it2.isValid() && it1.core_.pipe() == it2.core_.pipe() ; } template inline bool operator!= (IterTool const& ito1, IterTool const& ito2) { return !(ito1 == ito2); } /** * Implementation of the filter logic. * This core stores a function object instance, * passing each pulled source element to this * predicate function for evaluation. */ template struct FilterCore : IdentityCore { typedef IdentityCore _Par; typedef typename IT::reference Val; function predicate_; bool evaluate () const { return _Par::pipe() && predicate_(*_Par::pipe()); } template FilterCore (IT const& orig, PRED prediDef) : _Par(orig) , predicate_(prediDef) // induces a signature check { } }; /** * Iterator tool filtering pulled data according to a predicate */ template class FilterIter : public IterTool > { typedef FilterCore _Filter; typedef IterTool<_Filter> _Impl; static bool acceptAll(typename _Filter::Val) { return true; } public: FilterIter () : _Impl(FilterCore(IT(), acceptAll)) { } template FilterIter (IT const& src, PRED filterPredicate) : _Impl(_Filter(src,filterPredicate)) { } }; /** Build a FilterIter: convenience free function shortcut, * picking up the involved types automatically. * @param filterPredicate to be invoked for each source element * @return Iterator filtering contents of the source */ template inline FilterIter filterIterator (IT const& src, PRED filterPredicate) { return FilterIter(src,filterPredicate); } } // namespace lib #endif