BALL  1.4.1
enumerator.h
Go to the documentation of this file.
00001 // -*- Mode: C++; tab-width: 2; -*-
00002 // vi: set ts=2:
00003 //
00004 
00005 #ifndef BALL_CONCEPT_ENUMERATOR_H
00006 #define BALL_CONCEPT_ENUMERATOR_H
00007 
00008 #ifndef BALL_COMMON_H
00009 # include <BALL/common.h>
00010 #endif
00011 
00012 #ifndef BALL_COMMON_EXCEPTION_H
00013 # include <BALL/COMMON/exception.h>
00014 #endif
00015 
00016 #ifndef BALL_COMMON_RTTI_H
00017 # include <BALL/COMMON/rtti.h>
00018 #endif
00019 
00020 #ifndef BALL_CONCEPT_FORWARDITERATOR_H
00021 # include <BALL/CONCEPT/forwardIterator.h>
00022 #endif
00023 
00024 #include <vector>
00025 #include <list>
00026 #include <algorithm>
00027 
00028 namespace BALL
00029 {
00030 
00045   class BALL_EXPORT EnumeratorIndex
00046     : private std::vector<Position>
00047   {
00048     public:
00049 
00056     class BALL_EXPORT IncompatibleIndex
00057       : public Exception::GeneralException
00058     {
00059       public:
00060 
00061       IncompatibleIndex(const char* file, int line);
00062     };
00063 
00065 
00069       
00072     EnumeratorIndex();
00073 
00077     template <typename Variant, typename VariantIterator>
00078     EnumeratorIndex(const std::list<std::pair<VariantIterator, std::vector<Variant> > >& variant_list);
00079 
00082     ~EnumeratorIndex();
00083 
00085 
00091     const EnumeratorIndex& operator = (const EnumeratorIndex& rhs);
00092 
00096     const EnumeratorIndex& operator = (Position index);
00097 
00100     template <typename Variant, typename VariantIterator>
00101     const EnumeratorIndex& operator = (const std::list<std::pair<VariantIterator, std::vector<Variant> > >& variant_list);
00103 
00107 
00110     const std::vector<Size>& getModulus() const;
00111 
00114     Size getModulus(Position pos) const;
00115       
00121     EnumeratorIndex& operator ++ ();
00122 
00128     EnumeratorIndex& operator -- ();
00129 
00132     Position operator [] (Position pos) const;
00133 
00136     Position& operator [] (Position pos);
00137 
00140     Size getSize() const;
00141 
00153     EnumeratorIndex& operator << (Size modulus);
00155     
00159 
00164     bool operator == (const EnumeratorIndex& rhs) const;
00165 
00170     bool operator != (const EnumeratorIndex& rhs) const;
00171 
00177     bool operator > (const EnumeratorIndex& rhs) const;
00178 
00184     bool operator < (const EnumeratorIndex& rhs) const;
00185         
00191     bool operator >= (const EnumeratorIndex& rhs) const;
00192 
00198     bool operator <= (const EnumeratorIndex& rhs) const;
00200 
00201     private:
00203     std::vector<Size> modulus_;
00205     std::vector<Size> base_multipliers_;
00206   };
00207 
00208 
00209   template <typename Variant, typename VariantIterator>
00210   EnumeratorIndex::EnumeratorIndex(const std::list<std::pair<VariantIterator, std::vector<Variant> > >& variant_list)
00211     : std::vector<Position>(variant_list.size()),
00212       modulus_(variant_list.size()),
00213       base_multipliers_(variant_list.size())
00214   { 
00215     this->operator = (variant_list);
00216   }
00217 
00218 
00219   template <typename Variant, typename VariantIterator>
00220   const EnumeratorIndex& EnumeratorIndex::operator = 
00221     (const std::list<std::pair<VariantIterator, std::vector<Variant> > >& variant_list)
00222   { 
00223     resize(variant_list.size());
00224     modulus_.resize(variant_list.size());
00225     base_multipliers_.resize(variant_list.size());
00226 
00227     // compute the base multipliers for later usage 
00228     Index i;
00229     Size multiplier = 1;
00230     typename std::list<std::pair<VariantIterator, std::vector<Variant> > >::const_iterator list_it = variant_list.begin();
00231     for (i = (Size)(size() - 1); i >= 0; i--, list_it++)
00232     {
00233       operator[](i) = 0;
00234       modulus_[i] = (Size)list_it->second.size();
00235 
00236       base_multipliers_[i] = multiplier;
00237       multiplier *= modulus_[i];
00238     }
00239     
00240     return *this;
00241   }
00242 
00243 
00272   template <class Container, class SiteIterator, class Variant>
00273   class Enumerator
00274   { 
00275     protected:
00276     class IteratorTraits_;
00277     
00278     public:
00279 
00283       
00292     typedef void (*MutatorFunction) (Variant&, const Variant&);
00293 
00296     typedef std::vector<Variant> VariantVector;
00297 
00300     typedef std::pair<SiteIterator, VariantVector> Site;
00301 
00304     typedef std::list<Site> SiteList;
00305 
00308     typedef ForwardIterator<Enumerator<Container, SiteIterator, Variant>, Container, EnumeratorIndex*, IteratorTraits_>
00309       Iterator;
00310 
00313     typedef ConstForwardIterator<Enumerator<Container, SiteIterator, Variant>, Container, EnumeratorIndex*, IteratorTraits_>
00314       ConstIterator;
00316 
00320 
00323     Enumerator();
00324 
00330     Enumerator(Container& container);
00331 
00336     Enumerator(Container& container, MutatorFunction mutator);
00337 
00340     ~Enumerator()
00341     {
00342     }
00344 
00348 
00351     void addVariants(const SiteIterator& it, const VariantVector& variants)
00352     {
00353       variant_sites_.push_back(Site(it, variants));
00354       position_ = variant_sites_;
00355     }
00356 
00359     void deleteVariants(const SiteIterator& it, const VariantVector& variants)
00360     {
00361       typename SiteList::iterator var_it;
00362       var_it = std::find(variant_sites_.begin(), variant_sites_.end(), Site(it, variants));
00363       if (var_it != variant_sites_.end())
00364       {
00365         variant_sites_.erase(var_it);
00366       }
00367       position_ = variant_sites_;
00368     }
00369 
00373     Size countVariants()
00374     {
00375       Size total = 1;
00376       typename SiteList::iterator it;
00377       for (it = variant_sites_.begin(); it != variant_sites_.end(); ++it)
00378       {
00379         total *= it->second.size();
00380       }
00381       return total;
00382     }
00383 
00387     Container& getCurrent();
00388 
00393     void createCombination(const Position index);
00394 
00400     void createCombination(const EnumeratorIndex& index);
00402 
00406     
00408     Iterator begin();
00409 
00411     Iterator end();
00412 
00414     ConstIterator begin() const;
00415 
00417     ConstIterator end() const;
00419 
00420     protected:
00421 
00422     friend class IteratorTraits_;
00423 
00426     class IteratorTraits_
00427     {
00428       friend class Enumerator<Container, SiteIterator, Variant>;
00429       
00430       public:
00431         
00432       typedef Enumerator<Container, SiteIterator, Variant>
00433         ContainerType;
00434 
00435       typedef Enumerator<Container, SiteIterator, Variant>* 
00436         ContainerPointer;
00437 
00438       typedef const Enumerator<Container, SiteIterator, Variant>* 
00439         ContainerConstPointer;
00440 
00441       typedef EnumeratorIndex
00442         IteratorPosition;
00443 
00444       typedef Container
00445         ValueType;
00446 
00447       IteratorTraits_()
00448         : bound_(0),  
00449           position_(),
00450           past_the_end_(false)
00451       {
00452       }
00453         
00454       IteratorTraits_(const ContainerType& enumerator)
00455         : bound_(const_cast<ContainerPointer>(&enumerator)),
00456           position_(enumerator.variant_sites_),
00457           past_the_end_(false)
00458       {
00459       }
00460       
00461       ContainerConstPointer getContainer() const  
00462       {
00463         return bound_;
00464       }
00465       
00466       ContainerPointer getContainer()
00467       {
00468         return bound_;
00469       }
00470 
00471       bool isSingular() const
00472       {
00473         return (bound_ == 0);
00474       }
00475  
00476       IteratorPosition& getPosition()
00477       {
00478         return position_;
00479       }
00480 
00481       const IteratorPosition& getPosition() const
00482       {
00483         return position_;
00484       }
00485 
00486       bool operator == (const IteratorTraits_& traits) const
00487       {
00488         return ((bound_ == traits.bound_) && (position_ == traits.position_) && (past_the_end_ == traits.past_the_end_));
00489       }
00490 
00491       bool operator != (const IteratorTraits_& traits) const
00492       {
00493         return ((bound_ != traits.bound_) || (position_ != traits.position_) || (past_the_end_ != traits.past_the_end_));
00494       }
00495 
00496       bool isValid() const
00497       {
00498         return (bound_ != 0);
00499       }
00500 
00501       void invalidate()
00502       {
00503         bound_ = 0;
00504         position_ = 0;
00505         past_the_end_ = false;
00506       }
00507 
00508       void toBegin()
00509       {
00510         position_ = 0;
00511         past_the_end_ = false;
00512       }
00513 
00514       bool isBegin() const
00515       {
00516         return (position_ == EnumeratorIndex()) && (past_the_end_ == false);
00517       }
00518       
00519       void toEnd()
00520       {
00521         position_ = 0;
00522         past_the_end_ = true;
00523       }
00524       
00525       bool isEnd() const
00526       {
00527         return past_the_end_;
00528       }
00529       
00530       ValueType& getData()
00531       {
00532         validate();
00533         return bound_->getCurrent();
00534       }
00535       
00536       const ValueType& getData() const
00537       {
00538         // This is logically const only!
00539         const_cast<typename Enumerator<Container, SiteIterator, Variant>::IteratorTraits_*>(this)->validate();
00540         return bound_->getCurrent();
00541       }
00542       
00543       void forward()
00544       {
00545         try
00546         {
00547           ++position_;
00548         }
00549         catch (Exception::IndexOverflow&)
00550         {
00551           past_the_end_ = true;
00552           position_ = 0;
00553         }
00554       }
00555       
00556       void validate()
00557       {
00558         if (!bound_->is_valid_position_
00559             || (position_ != bound_->position_))
00560         {
00561           bound_->createCombination(position_);
00562         }
00563       }
00564 
00565       protected:
00566       ContainerPointer  bound_;
00567       EnumeratorIndex   position_;
00568       bool              past_the_end_;
00569     };
00570 
00571     // the default mutation method (calling asignment operator)
00572     static inline void defaultAssign_(Variant& a, const Variant& b)
00573     {
00574       a = b;
00575     }
00576 
00577     void mutate_(SiteIterator& it, const Variant& v)
00578     {
00579       mutator_(*it, v);
00580     }
00581 
00582     Container&      container_;
00583     MutatorFunction mutator_;
00584     SiteList        variant_sites_;
00585     EnumeratorIndex position_;
00586     bool            is_valid_position_;
00587   };
00588 
00589   template <typename Container, typename SiteIterator, typename Variant>
00590   Enumerator<Container, SiteIterator, Variant>::Enumerator()
00591     : container_(const_cast<Container&>(RTTI::getDefault<Container>())),
00592       mutator_(0)
00593   {
00594   }
00595     
00596   template <typename Container, typename SiteIterator, typename Variant>
00597   Enumerator<Container, SiteIterator, Variant>::Enumerator(Container& container)
00598     : container_(container),
00599       mutator_(defaultAssign_)
00600   {
00601   }
00602     
00603   template <typename Container, typename SiteIterator, typename Variant>
00604   BALL_INLINE
00605   Enumerator<Container, SiteIterator, Variant>::Enumerator
00606     (Container& container, typename Enumerator<Container, SiteIterator, Variant>::MutatorFunction mutator)
00607     : container_(container),
00608       mutator_(mutator)
00609   {
00610   }
00611 
00612 
00613   template <typename Container, typename SiteIterator, typename Variant>
00614   BALL_INLINE
00615   Container& Enumerator<Container, SiteIterator, Variant>::getCurrent()
00616   {
00617     return container_;
00618   }
00619   
00620   template <typename Container, typename SiteIterator, typename Variant>
00621   void Enumerator<Container, SiteIterator, Variant>::createCombination(const Position index)
00622   {
00623     try
00624     {
00625       position_ = index;
00626       createCombination(position_);
00627     }
00628     catch (EnumeratorIndex::IncompatibleIndex&)
00629     {
00630       throw Exception::IndexOverflow(__FILE__, __LINE__, index);
00631     }
00632   }
00633 
00634   template <typename Container, typename SiteIterator, typename Variant>
00635   void Enumerator<Container, SiteIterator, Variant>::createCombination(const EnumeratorIndex& index)
00636   {
00637     if (&index != &position_)
00638     {
00639       position_ = index;
00640     }
00641 
00642     typename SiteList::iterator it = variant_sites_.begin();
00643     Position i((Position)(index.getSize() - 1));
00644     for (; it != variant_sites_.end(); ++it, --i)
00645     {
00646       mutate_(it->first, it->second[index[i]]);
00647     }
00648     
00649     is_valid_position_ = true;
00650   }
00651 
00652   template <typename Container, typename SiteIterator, typename Variant>
00653   BALL_INLINE
00654   typename Enumerator<Container, SiteIterator, Variant>::Iterator Enumerator<Container, SiteIterator, Variant>::begin()
00655   {
00656     return Iterator::begin(*this);
00657   }
00658 
00659   template <typename Container, typename SiteIterator, typename Variant>
00660   BALL_INLINE
00661   typename Enumerator<Container, SiteIterator, Variant>::Iterator Enumerator<Container, SiteIterator, Variant>::end()
00662   {
00663     return Iterator::end(*this);
00664   }
00665 
00666   template <typename Container, typename VariantConstIterator, typename Variant>
00667   BALL_INLINE
00668   typename Enumerator<Container, VariantConstIterator, Variant>::ConstIterator Enumerator<Container, VariantConstIterator, Variant>::begin() const
00669   {
00670     return ConstIterator::begin(*this);
00671   }
00672 
00673   template <typename Container, typename VariantConstIterator, typename Variant>
00674   BALL_INLINE
00675   typename Enumerator<Container, VariantConstIterator, Variant>::ConstIterator Enumerator<Container, VariantConstIterator, Variant>::end() const
00676   {
00677     return ConstIterator::end(*this);
00678   }
00679 
00680   
00681 # ifndef BALL_NO_INLINE_FUNCTIONS
00682 #   include <BALL/CONCEPT/enumerator.iC>
00683 # endif
00684 
00685 }
00686 
00687 #endif // BALL_CONCEPT_ENUMERATOR_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines