00001
00002
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 };
00064
00066
00070
00073 EnumeratorIndex()
00074 ;
00075
00079 template <typename Variant, typename VariantIterator>
00080 EnumeratorIndex(const std::list<std::pair<VariantIterator, std::vector<Variant> > >& variant_list)
00081 ;
00082
00085 ~EnumeratorIndex()
00086 ;
00087
00089
00095 const EnumeratorIndex& operator = (const EnumeratorIndex& rhs)
00096 ;
00097
00100 const EnumeratorIndex& operator = (Position index)
00101 throw(Exception::IndexOverflow);
00102
00105 template <typename Variant, typename VariantIterator>
00106 const EnumeratorIndex& operator = (const std::list<std::pair<VariantIterator, std::vector<Variant> > >& variant_list)
00107 ;
00109
00113
00116 const std::vector<Size>& getModulus() const
00117 ;
00118
00121 Size getModulus(Position pos) const
00122 ;
00123
00128 EnumeratorIndex& operator ++ ()
00129 throw(Exception::IndexOverflow);
00130
00135 EnumeratorIndex& operator -- ()
00136 throw(Exception::IndexUnderflow);
00137
00140 Position operator [] (Position pos) const
00141 ;
00142
00145 Position& operator [] (Position pos)
00146 ;
00147
00150 Size getSize() const
00151 ;
00152
00164 EnumeratorIndex& operator << (Size modulus)
00165 throw(Exception::OutOfRange);
00167
00171
00176 bool operator == (const EnumeratorIndex& rhs) const
00177 ;
00178
00183 bool operator != (const EnumeratorIndex& rhs) const
00184 ;
00185
00191 bool operator > (const EnumeratorIndex& rhs) const
00192 throw(EnumeratorIndex::IncompatibleIndex);
00193
00199 bool operator < (const EnumeratorIndex& rhs) const
00200 throw(EnumeratorIndex::IncompatibleIndex);
00201
00207 bool operator >= (const EnumeratorIndex& rhs) const
00208 throw(EnumeratorIndex::IncompatibleIndex);
00209
00215 bool operator <= (const EnumeratorIndex& rhs) const
00216 throw(EnumeratorIndex::IncompatibleIndex);
00218
00219 private:
00221 std::vector<Size> modulus_;
00223 std::vector<Size> base_multipliers_;
00224 };
00225
00226
00227 template <typename Variant, typename VariantIterator>
00228 EnumeratorIndex::EnumeratorIndex(const std::list<std::pair<VariantIterator, std::vector<Variant> > >& variant_list)
00229
00230 : std::vector<Position>(variant_list.size()),
00231 modulus_(variant_list.size()),
00232 base_multipliers_(variant_list.size())
00233 {
00234 this->operator = (variant_list);
00235 }
00236
00237
00238 template <typename Variant, typename VariantIterator>
00239 const EnumeratorIndex& EnumeratorIndex::operator =
00240 (const std::list<std::pair<VariantIterator, std::vector<Variant> > >& variant_list)
00241
00242 {
00243 resize(variant_list.size());
00244 modulus_.resize(variant_list.size());
00245 base_multipliers_.resize(variant_list.size());
00246
00247
00248 Index i;
00249 Size multiplier = 1;
00250 typename std::list<std::pair<VariantIterator, std::vector<Variant> > >::const_iterator list_it = variant_list.begin();
00251 for (i = (Size)(size() - 1); i >= 0; i--, list_it++)
00252 {
00253 operator[](i) = 0;
00254 modulus_[i] = (Size)list_it->second.size();
00255
00256 base_multipliers_[i] = multiplier;
00257 multiplier *= modulus_[i];
00258 }
00259
00260 return *this;
00261 }
00262
00263
00292 template <class Container, class SiteIterator, class Variant>
00293 class Enumerator
00294 {
00295 protected:
00296 class IteratorTraits_;
00297
00298 public:
00299
00303
00312 typedef void (*MutatorFunction) (Variant&, const Variant&);
00313
00316 typedef std::vector<Variant>
00317 VariantVector;
00318
00321 typedef std::pair<SiteIterator, VariantVector>
00322 Site;
00323
00326 typedef std::list<Site>
00327 SiteList;
00328
00331 typedef ForwardIterator<Enumerator<Container, SiteIterator, Variant>, Container, EnumeratorIndex*, IteratorTraits_>
00332 Iterator;
00333
00336 typedef ConstForwardIterator<Enumerator<Container, SiteIterator, Variant>, Container, EnumeratorIndex*, IteratorTraits_>
00337 ConstIterator;
00339
00343
00346 Enumerator()
00347 ;
00348
00354 Enumerator(Container& container)
00355 ;
00356
00361 Enumerator(Container& container, MutatorFunction mutator)
00362 ;
00363
00366 ~Enumerator()
00367
00368 {
00369 }
00371
00375
00378 void addVariants(const SiteIterator& it, const VariantVector& variants)
00379
00380 {
00381 variant_sites_.push_back(Site(it, variants));
00382 position_ = variant_sites_;
00383 }
00384
00387 void deleteVariants(const SiteIterator& it, const VariantVector& variants)
00388
00389 {
00390 typename SiteList::iterator var_it;
00391 var_it = std::find(variant_sites_.begin(), variant_sites_.end(), Site(it, variants));
00392 if (var_it != variant_sites_.end())
00393 {
00394 variant_sites_.erase(var_it);
00395 }
00396 position_ = variant_sites_;
00397 }
00398
00402 Size countVariants()
00403
00404 {
00405 Size total = 1;
00406 typename SiteList::iterator it;
00407 for (it = variant_sites_.begin(); it != variant_sites_.end(); ++it)
00408 {
00409 total *= it->second.size();
00410 }
00411 return total;
00412 }
00413
00417 Container& getCurrent()
00418 ;
00419
00423 void createCombination(const Position index)
00424 throw(Exception::IndexOverflow);
00425
00430 void createCombination(const EnumeratorIndex& index)
00431 throw(EnumeratorIndex::IncompatibleIndex);
00433
00437
00439 Iterator begin()
00440 ;
00441
00443 Iterator end()
00444 ;
00445
00447 ConstIterator begin() const
00448 ;
00449
00451 ConstIterator end() const
00452 ;
00454
00455 protected:
00456
00457 friend class IteratorTraits_;
00458
00461 class IteratorTraits_
00462 {
00463 friend class Enumerator<Container, SiteIterator, Variant>;
00464
00465 public:
00466
00467 typedef Enumerator<Container, SiteIterator, Variant>
00468 ContainerType;
00469
00470 typedef Enumerator<Container, SiteIterator, Variant>*
00471 ContainerPointer;
00472
00473 typedef const Enumerator<Container, SiteIterator, Variant>*
00474 ContainerConstPointer;
00475
00476 typedef EnumeratorIndex
00477 IteratorPosition;
00478
00479 typedef Container
00480 ValueType;
00481
00482 IteratorTraits_()
00483
00484 : bound_(0),
00485 position_(),
00486 past_the_end_(false)
00487 {
00488 }
00489
00490 IteratorTraits_(const ContainerType& enumerator)
00491
00492 : bound_(const_cast<ContainerPointer>(&enumerator)),
00493 position_(enumerator.variant_sites_),
00494 past_the_end_(false)
00495 {
00496 }
00497
00498 ContainerConstPointer getContainer() const
00499
00500 {
00501 return bound_;
00502 }
00503
00504 ContainerPointer getContainer()
00505
00506 {
00507 return bound_;
00508 }
00509
00510 bool isSingular() const
00511
00512 {
00513 return (bound_ == 0);
00514 }
00515
00516 IteratorPosition& getPosition()
00517
00518 {
00519 return position_;
00520 }
00521
00522 const IteratorPosition& getPosition() const
00523
00524 {
00525 return position_;
00526 }
00527
00528 bool operator == (const IteratorTraits_& traits) const
00529
00530 {
00531 return ((bound_ == traits.bound_) && (position_ == traits.position_) && (past_the_end_ == traits.past_the_end_));
00532 }
00533
00534 bool operator != (const IteratorTraits_& traits) const
00535
00536 {
00537 return ((bound_ != traits.bound_) || (position_ != traits.position_) || (past_the_end_ != traits.past_the_end_));
00538 }
00539
00540 bool isValid() const
00541
00542 {
00543 return (bound_ != 0);
00544 }
00545
00546 void invalidate()
00547
00548 {
00549 bound_ = 0;
00550 position_ = 0;
00551 past_the_end_ = false;
00552 }
00553
00554 void toBegin()
00555
00556 {
00557 position_ = 0;
00558 past_the_end_ = false;
00559 }
00560
00561 bool isBegin() const
00562
00563 {
00564 return (position_ == EnumeratorIndex()) && (past_the_end_ == false);
00565 }
00566
00567 void toEnd()
00568
00569 {
00570 position_ = 0;
00571 past_the_end_ = true;
00572 }
00573
00574 bool isEnd() const
00575
00576 {
00577 return past_the_end_;
00578 }
00579
00580 ValueType& getData()
00581
00582 {
00583 validate();
00584 return bound_->getCurrent();
00585 }
00586
00587 const ValueType& getData() const
00588
00589 {
00590
00591 const_cast<typename Enumerator<Container, SiteIterator, Variant>::IteratorTraits_*>(this)->validate();
00592 return bound_->getCurrent();
00593 }
00594
00595 void forward()
00596
00597 {
00598 try
00599 {
00600 ++position_;
00601 }
00602 catch (Exception::IndexOverflow&)
00603 {
00604 past_the_end_ = true;
00605 position_ = 0;
00606 }
00607 }
00608
00609 void validate()
00610
00611 {
00612 if (!bound_->is_valid_position_
00613 || (position_ != bound_->position_))
00614 {
00615 bound_->createCombination(position_);
00616 }
00617 }
00618
00619 protected:
00620 ContainerPointer bound_;
00621 EnumeratorIndex position_;
00622 bool past_the_end_;
00623 };
00624
00625
00626 static inline void defaultAssign_(Variant& a, const Variant& b)
00627 {
00628 a = b;
00629 }
00630
00631 void mutate_(SiteIterator& it, const Variant& v)
00632
00633 {
00634 mutator_(*it, v);
00635 }
00636
00637 Container& container_;
00638 MutatorFunction mutator_;
00639 SiteList variant_sites_;
00640 EnumeratorIndex position_;
00641 bool is_valid_position_;
00642 };
00643
00644 template <typename Container, typename SiteIterator, typename Variant>
00645 Enumerator<Container, SiteIterator, Variant>::Enumerator()
00646
00647 : container_(const_cast<Container&>(RTTI::getDefault<Container>())),
00648 mutator_(0)
00649 {
00650 }
00651
00652 template <typename Container, typename SiteIterator, typename Variant>
00653 Enumerator<Container, SiteIterator, Variant>::Enumerator(Container& container)
00654
00655 : container_(container),
00656 mutator_(defaultAssign_)
00657 {
00658 }
00659
00660 template <typename Container, typename SiteIterator, typename Variant>
00661 BALL_INLINE
00662 Enumerator<Container, SiteIterator, Variant>::Enumerator
00663 (Container& container, typename Enumerator<Container, SiteIterator, Variant>::MutatorFunction mutator)
00664
00665 : container_(container),
00666 mutator_(mutator)
00667 {
00668 }
00669
00670
00671 template <typename Container, typename SiteIterator, typename Variant>
00672 BALL_INLINE
00673 Container& Enumerator<Container, SiteIterator, Variant>::getCurrent()
00674
00675 {
00676 return container_;
00677 }
00678
00679 template <typename Container, typename SiteIterator, typename Variant>
00680 void Enumerator<Container, SiteIterator, Variant>::createCombination(const Position index)
00681 throw(Exception::IndexOverflow)
00682 {
00683 try
00684 {
00685 position_ = index;
00686 createCombination(position_);
00687 }
00688 catch (EnumeratorIndex::IncompatibleIndex&)
00689 {
00690 throw Exception::IndexOverflow(__FILE__, __LINE__, index);
00691 }
00692 }
00693
00694 template <typename Container, typename SiteIterator, typename Variant>
00695 void Enumerator<Container, SiteIterator, Variant>::createCombination(const EnumeratorIndex& index)
00696 throw(EnumeratorIndex::IncompatibleIndex)
00697 {
00698 if (&index != &position_)
00699 {
00700 position_ = index;
00701 }
00702
00703 typename SiteList::iterator it = variant_sites_.begin();
00704 Position i((Position)(index.getSize() - 1));
00705 for (; it != variant_sites_.end(); ++it, --i)
00706 {
00707 mutate_(it->first, it->second[index[i]]);
00708 }
00709
00710 is_valid_position_ = true;
00711 }
00712
00713 template <typename Container, typename SiteIterator, typename Variant>
00714 BALL_INLINE
00715 typename Enumerator<Container, SiteIterator, Variant>::Iterator Enumerator<Container, SiteIterator, Variant>::begin()
00716
00717 {
00718 return Iterator::begin(*this);
00719 }
00720
00721 template <typename Container, typename SiteIterator, typename Variant>
00722 BALL_INLINE
00723 typename Enumerator<Container, SiteIterator, Variant>::Iterator Enumerator<Container, SiteIterator, Variant>::end()
00724
00725 {
00726 return Iterator::end(*this);
00727 }
00728
00729 template <typename Container, typename VariantConstIterator, typename Variant>
00730 BALL_INLINE
00731 typename Enumerator<Container, VariantConstIterator, Variant>::ConstIterator Enumerator<Container, VariantConstIterator, Variant>::begin() const
00732
00733 {
00734 return ConstIterator::begin(*this);
00735 }
00736
00737 template <typename Container, typename VariantConstIterator, typename Variant>
00738 BALL_INLINE
00739 typename Enumerator<Container, VariantConstIterator, Variant>::ConstIterator Enumerator<Container, VariantConstIterator, Variant>::end() const
00740
00741 {
00742 return ConstIterator::end(*this);
00743 }
00744
00745
00746 # ifndef BALL_NO_INLINE_FUNCTIONS
00747 # include <BALL/CONCEPT/enumerator.iC>
00748 # endif
00749
00750 }
00751
00752 #endif // BALL_CONCEPT_ENUMERATOR_H