Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members

predicate_iterator.h

Go to the documentation of this file.
00001 // -*- mode: c++; -*-
00002 //
00003 //The Biomolecule Toolkit (BTK) is a C++ library for use in the
00004 //modeling, analysis, and design of biological macromolecules.
00005 //Copyright (C) 2002, Tim Robertson <kid50@users.sourceforge.net>
00006 //
00007 //This program is free software; you can redistribute it and/or modify
00008 //it under the terms of the GNU Lesser General Public License as published
00009 //by the Free Software Foundation; either version 2.1 of the License, or (at
00010 //your option) any later version.
00011 //
00012 //This program is distributed in the hope that it will be useful,  but
00013 //WITHOUT ANY WARRANTY; without even the implied warranty of
00014 //MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015 //Lesser General Public License for more details. 
00016 //
00017 //You should have received a copy of the GNU Lesser General Public License 
00018 //along with this program; if not, write to the Free Software Foundation, 
00019 //Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00020 
00021 //@file predicate_iterator.h
00022 
00023 #ifndef PREDICATE_ITERATOR_H
00024 #define PREDICATE_ITERATOR_H
00025 
00026 #include "boost/shared_ptr.hpp"
00027 #include <iterator>
00028 #include <vector>
00029 #include <cassert>
00030 
00031 namespace BTK {
00032 
00033 template <class Predicate, class Iterator>  
00034 class MatchListStrategy {
00035 public:
00036   typedef typename Iterator::value_type value_type;
00037   typedef value_type & reference;
00038   typedef Iterator iterator_type;
00039   typedef Predicate predicate_type;
00040 
00041   MatchListStrategy(Iterator const & begin,
00042         Iterator const & end,
00043         Predicate const & pred = Predicate()) :
00044     _iterator(begin), _end(end), 
00045     _match_list(new std::vector<bool>()), _cur(0)
00046   {
00047     Iterator i(begin);
00048 
00049     // if the the range is empty, put a single false in
00050     // the match list
00051     if (begin == end) {
00052       _match_list->push_back(false);
00053     } else {
00054 
00055       // fill up the match list
00056       while (i != end) {
00057   if (pred(*i++)) 
00058     _match_list->push_back(true);
00059   else
00060     _match_list->push_back(false);
00061       }
00062       
00063       // advance to the first selected element.
00064       if (!(*_match_list)[0]) advance();
00065     }
00066   };
00067 
00068   void advance() 
00069   {
00070     // only iterate over the matching elements in the tested range.
00071     // (no iteration past-the-end).
00072     while (_iterator != _end) {
00073       ++_cur;
00074       ++_iterator;
00075       
00076       if (!(*_match_list)[_cur]) continue;
00077       else return;
00078     }
00079   }
00080   
00081   reference dereference() const { return *_iterator; }
00082   const Iterator base() const { return _iterator; }
00083 
00084   MatchListStrategy & operator=(MatchListStrategy const & rhs) 
00085   {
00086     _iterator = rhs._iterator;
00087     _end = rhs._end;
00088     _match_list = rhs._match_list;
00089     _cur = rhs._cur;
00090   }
00091   
00092 private:
00093   Iterator _iterator;
00094   Iterator _end;
00095   boost::shared_ptr<std::vector<bool> > _match_list;
00096   std::vector<bool>::size_type _cur;
00097 };
00098 
00099 template <class Predicate, class Iterator>
00100 class PointerListStrategy {
00101 public:
00102   typedef typename Iterator::value_type value_type;
00103   typedef typename Iterator::reference reference;
00104   typedef Iterator iterator_type;
00105   typedef Predicate predicate_type;
00106 
00107   
00108   PointerListStrategy(Iterator const & begin,
00109           Iterator const & end,
00110           Predicate const & pred = Predicate()) :
00111     _match_list(new std::vector<Iterator>()), _cur()
00112   {
00113     // fill the match list with pointers to matching elements.
00114     for (Iterator i(begin); i != end; ++i) {
00115       if (pred(*i)) {
00116   _match_list->push_back(i);
00117       }
00118     }
00119 
00120     // push the end iterator on the list, in order to guarantee
00121     // that the end iterator is returned during iteration.
00122     _match_list->push_back(end);
00123 
00124     _cur = _match_list->begin();
00125   }
00126 
00127   void advance() { ++_cur; }
00128 
00129   reference dereference() const { return **_cur; }
00130 
00131   Iterator base() const { return *_cur; }
00132 
00133   PointerListStrategy & operator=(PointerListStrategy const & rhs)
00134   {
00135     _match_list = rhs._match_list;
00136     _cur = rhs._cur;  // this is only safe because _match_list is a shared_ptr
00137   }
00138 
00139 private:
00140   boost::shared_ptr<std::vector<Iterator> > _match_list;
00141   typename std::vector<Iterator>::iterator _cur;
00142 };
00143 
00167 template <class Predicate, class Iterator, 
00168     class Strategy = PointerListStrategy<Predicate,Iterator> > 
00169 class PredicateIterator
00170 {
00171  public:
00172 
00180   typedef std::forward_iterator_tag iterator_category;
00181 
00182   typedef typename std::iterator_traits<Iterator>::value_type
00183   value_type;
00184 
00185   typedef typename std::iterator_traits<Iterator>::difference_type
00186   difference_type;
00187 
00188   typedef typename std::iterator_traits<Iterator>::pointer
00189   pointer;
00190 
00191   typedef typename std::iterator_traits<Iterator>::reference
00192   reference;
00194 
00199   typedef PredicateIterator<Predicate,Iterator,Strategy> self_type;
00200   typedef Iterator iterator_type;
00201   typedef Predicate predicate_type;
00202   typedef Strategy strategy_type;
00204 
00210   PredicateIterator(Iterator const & begin, 
00211         Iterator const & end,
00212         Predicate const & p = Predicate()) :
00213     _predicate(p), _strategy(begin,end,p) {}
00214 
00220   PredicateIterator(Iterator const & end,
00221         Predicate const & p = Predicate()) :
00222     _predicate(p), _strategy(end,end,p) {}
00223 
00225   inline self_type & operator++()
00226   {  
00227     _strategy.advance();
00228     return *this;
00229   } 
00230 
00232   inline self_type operator++(int)
00233   {
00234     self_type tmp(*this);
00235     _strategy.advance();
00236     return tmp;
00237   }
00238   
00243   bool inline operator==(self_type const & rhs) const
00244   {
00245     return (_strategy.base() == rhs._strategy.base());
00246   }
00247 
00248   bool inline operator!=(self_type const & rhs) const
00249   {
00250     return (_strategy.base() != rhs._strategy.base());
00251   }
00252 
00253   bool inline operator==(Iterator const & rhs) const
00254   {
00255     return _strategy.base() == rhs;
00256   }
00257 
00258   bool inline operator!=(Iterator const & rhs) const
00259   {
00260     return _strategy.base() != rhs;
00261   }
00262 
00263   friend bool operator==(Iterator const & lhs,
00264        self_type const & rhs) 
00265   {
00266     return (lhs == rhs._iterator);
00267   }
00268 
00269   friend bool operator!=(Iterator const & lhs,
00270        self_type const & rhs)
00271   {
00272     return (lhs != rhs._iterator);
00273   }
00275 
00277   inline reference operator*() const
00278   {
00279     return _strategy.dereference();
00280   }
00281 
00283   inline pointer operator->() const
00284   {
00285     // this is unintuitive, i know, but it has to be
00286     // done this way to ensure that a pointer is returned,
00287     // and not some iterator-intermediate thing.
00288     return &(_strategy.dereference());
00289   }
00290 
00291   inline self_type & operator=(self_type const & rhs) 
00292   {
00293     _predicate = rhs._predicate;
00294     _strategy = rhs._strategy;
00295     return *this;
00296   }
00297 
00298  private:
00299   Predicate _predicate;
00300   Strategy _strategy;
00301 };
00302 
00307 template <class Predicate, class Iterator>
00308 inline PredicateIterator<Predicate,Iterator> 
00309 make_predicate_iterator(Iterator const & begin,
00310       Iterator const & end,
00311       Predicate const & p) 
00312 {
00313   return PredicateIterator<Predicate,Iterator>(begin,end,p);
00314 }
00315 
00316 template <class Predicate, class Iterator>
00317 inline PredicateIterator<Predicate,Iterator>
00318 make_predicate_iterator(Iterator const & end,
00319       Predicate const & p)
00320 {
00321   return PredicateIterator<Predicate,Iterator>(end,p);
00322 }
00324 
00325 }; // namespace BTK
00326 
00327 #endif // PREDICATE_ITERATOR_H

Generated on Wed Apr 14 00:43:17 2004 for BTK by doxygen 1.3.6