00001
00002
00003
00004
00005
00006
00007 #ifndef BALL_CONCEPT_ENUMERATOR_H
00008 #define BALL_CONCEPT_ENUMERATOR_H
00009
00010 #ifndef BALL_COMMON_H
00011 # include <BALL/common.h>
00012 #endif
00013
00014 #ifndef BALL_COMMON_EXCEPTION_H
00015 # include <BALL/COMMON/exception.h>
00016 #endif
00017
00018 #ifndef BALL_COMMON_RTTI_H
00019 # include <BALL/COMMON/rtti.h>
00020 #endif
00021
00022 #ifndef BALL_CONCEPT_FORWARDITERATOR_H
00023 # include <BALL/CONCEPT/forwardIterator.h>
00024 #endif
00025
00026 #include <vector>
00027 #include <list>
00028 #include <algorithm>
00029
00030 namespace BALL
00031 {
00032
00047 class BALL_EXPORT EnumeratorIndex
00048 : private std::vector<Position>
00049 {
00050 public:
00051
00058 class BALL_EXPORT IncompatibleIndex
00059 : public Exception::GeneralException
00060 {
00061 public:
00062
00063 IncompatibleIndex(const char* file, int line)
00064 ;
00065 };
00066
00068
00072
00075 EnumeratorIndex()
00076 ;
00077
00081 template <typename Variant, typename VariantIterator>
00082 EnumeratorIndex(const std::list<std::pair<VariantIterator, std::vector<Variant> > >& variant_list)
00083 ;
00084
00087 ~EnumeratorIndex()
00088 ;
00089
00091
00097 const EnumeratorIndex& operator = (const EnumeratorIndex& rhs)
00098 ;
00099
00102 const EnumeratorIndex& operator = (Position index)
00103 throw(Exception::IndexOverflow);
00104
00107 template <typename Variant, typename VariantIterator>
00108 const EnumeratorIndex& operator = (const std::list<std::pair<VariantIterator, std::vector<Variant> > >& variant_list)
00109 ;
00111
00115
00118 const std::vector<Size>& getModulus() const
00119 ;
00120
00123 Size getModulus(Position pos) const
00124 ;
00125
00130 EnumeratorIndex& operator ++ ()
00131 throw(Exception::IndexOverflow);
00132
00137 EnumeratorIndex& operator -- ()
00138 throw(Exception::IndexUnderflow);
00139
00142 Position operator [] (Position pos) const
00143 ;
00144
00147 Position& operator [] (Position pos)
00148 ;
00149
00152 Size getSize() const
00153 ;
00154
00166 EnumeratorIndex& operator << (Size modulus)
00167 throw(Exception::OutOfRange);
00169
00173
00178 bool operator == (const EnumeratorIndex& rhs) const
00179 ;
00180
00185 bool operator != (const EnumeratorIndex& rhs) const
00186 ;
00187
00193 bool operator > (const EnumeratorIndex& rhs) const
00194 throw(EnumeratorIndex::IncompatibleIndex);
00195
00201 bool operator < (const EnumeratorIndex& rhs) const
00202 throw(EnumeratorIndex::IncompatibleIndex);
00203
00209 bool operator >= (const EnumeratorIndex& rhs) const
00210 throw(EnumeratorIndex::IncompatibleIndex);
00211
00217 bool operator <= (const EnumeratorIndex& rhs) const
00218 throw(EnumeratorIndex::IncompatibleIndex);
00220
00221 private:
00223 std::vector<Size> modulus_;
00225 std::vector<Size> base_multipliers_;
00226 };
00227
00228
00229 template <typename Variant, typename VariantIterator>
00230 EnumeratorIndex::EnumeratorIndex(const std::list<std::pair<VariantIterator, std::vector<Variant> > >& variant_list)
00231
00232 : std::vector<Position>(variant_list.size()),
00233 modulus_(variant_list.size()),
00234 base_multipliers_(variant_list.size())
00235 {
00236 this->operator = (variant_list);
00237 }
00238
00239
00240 template <typename Variant, typename VariantIterator>
00241 const EnumeratorIndex& EnumeratorIndex::operator =
00242 (const std::list<std::pair<VariantIterator, std::vector<Variant> > >& variant_list)
00243
00244 {
00245 resize(variant_list.size());
00246 modulus_.resize(variant_list.size());
00247 base_multipliers_.resize(variant_list.size());
00248
00249
00250 Index i;
00251 Size multiplier = 1;
00252 typename std::list<std::pair<VariantIterator, std::vector<Variant> > >::const_iterator list_it = variant_list.begin();
00253 for (i = (Size)(size() - 1); i >= 0; i--, list_it++)
00254 {
00255 operator[](i) = 0;
00256 modulus_[i] = (Size)list_it->second.size();
00257
00258 base_multipliers_[i] = multiplier;
00259 multiplier *= modulus_[i];
00260 }
00261
00262 return *this;
00263 }
00264
00265
00294 template <class Container, class SiteIterator, class Variant>
00295 class Enumerator
00296 {
00297 protected:
00298 class IteratorTraits_;
00299
00300 public:
00301
00305
00314 typedef void (*MutatorFunction) (Variant&, const Variant&);
00315
00318 typedef std::vector<Variant>
00319 VariantVector;
00320
00323 typedef std::pair<SiteIterator, VariantVector>
00324 Site;
00325
00328 typedef std::list<Site>
00329 SiteList;
00330
00333 typedef ForwardIterator<Enumerator<Container, SiteIterator, Variant>, Container, EnumeratorIndex*, IteratorTraits_>
00334 Iterator;
00335
00338 typedef ConstForwardIterator<Enumerator<Container, SiteIterator, Variant>, Container, EnumeratorIndex*, IteratorTraits_>
00339 ConstIterator;
00341
00345
00348 Enumerator()
00349 ;
00350
00356 Enumerator(Container& container)
00357 ;
00358
00363 Enumerator(Container& container, MutatorFunction mutator)
00364 ;
00365
00368 ~Enumerator()
00369
00370 {
00371 }
00373
00377
00380 void addVariants(const SiteIterator& it, const VariantVector& variants)
00381
00382 {
00383 variant_sites_.push_back(Site(it, variants));
00384 position_ = variant_sites_;
00385 }
00386
00389 void deleteVariants(const SiteIterator& it, const VariantVector& variants)
00390
00391 {
00392 typename SiteList::iterator var_it;
00393 var_it = std::find(variant_sites_.begin(), variant_sites_.end(), Site(it, variants));
00394 if (var_it != variant_sites_.end())
00395 {
00396 variant_sites_.erase(var_it);
00397 }
00398 position_ = variant_sites_;
00399 }
00400
00404 Size countVariants()
00405
00406 {
00407 Size total = 1;
00408 typename SiteList::iterator it;
00409 for (it = variant_sites_.begin(); it != variant_sites_.end(); ++it)
00410 {
00411 total *= it->second.size();
00412 }
00413 return total;
00414 }
00415
00419 Container& getCurrent()
00420 ;
00421
00425 void createCombination(const Position index)
00426 throw(Exception::IndexOverflow);
00427
00432 void createCombination(const EnumeratorIndex& index)
00433 throw(EnumeratorIndex::IncompatibleIndex);
00435
00439
00441 Iterator begin()
00442 ;
00443
00445 Iterator end()
00446 ;
00447
00449 ConstIterator begin() const
00450 ;
00451
00453 ConstIterator end() const
00454 ;
00456
00457 protected:
00458
00459 friend class IteratorTraits_;
00460
00463 class IteratorTraits_
00464 {
00465 friend class Enumerator<Container, SiteIterator, Variant>;
00466
00467 public:
00468
00469 typedef Enumerator<Container, SiteIterator, Variant>
00470 ContainerType;
00471
00472 typedef Enumerator<Container, SiteIterator, Variant>*
00473 ContainerPointer;
00474
00475 typedef const Enumerator<Container, SiteIterator, Variant>*
00476 ContainerConstPointer;
00477
00478 typedef EnumeratorIndex
00479 IteratorPosition;
00480
00481 typedef Container
00482 ValueType;
00483
00484 IteratorTraits_()
00485
00486 : bound_(0),
00487 position_(),
00488 past_the_end_(false)
00489 {
00490 }
00491
00492 IteratorTraits_(const ContainerType& enumerator)
00493
00494 : bound_(const_cast<ContainerPointer>(&enumerator)),
00495 position_(enumerator.variant_sites_),
00496 past_the_end_(false)
00497 {
00498 }
00499
00500 ContainerConstPointer getContainer() const
00501
00502 {
00503 return bound_;
00504 }
00505
00506 ContainerPointer getContainer()
00507
00508 {
00509 return bound_;
00510 }
00511
00512 bool isSingular() const
00513
00514 {
00515 return (bound_ == 0);
00516 }
00517
00518 IteratorPosition& getPosition()
00519
00520 {
00521 return position_;
00522 }
00523
00524 const IteratorPosition& getPosition() const
00525
00526 {
00527 return position_;
00528 }
00529
00530 bool operator == (const IteratorTraits_& traits) const
00531
00532 {
00533 return ((bound_ == traits.bound_) && (position_ == traits.position_) && (past_the_end_ == traits.past_the_end_));
00534 }
00535
00536 bool operator != (const IteratorTraits_& traits) const
00537
00538 {
00539 return ((bound_ != traits.bound_) || (position_ != traits.position_) || (past_the_end_ != traits.past_the_end_));
00540 }
00541
00542 bool isValid() const
00543
00544 {
00545 return (bound_ != 0);
00546 }
00547
00548 void invalidate()
00549
00550 {
00551 bound_ = 0;
00552 position_ = 0;
00553 past_the_end_ = false;
00554 }
00555
00556 void toBegin()
00557
00558 {
00559 position_ = 0;
00560 past_the_end_ = false;
00561 }
00562
00563 bool isBegin() const
00564
00565 {
00566 return (position_ == EnumeratorIndex()) && (past_the_end_ == false);
00567 }
00568
00569 void toEnd()
00570
00571 {
00572 position_ = 0;
00573 past_the_end_ = true;
00574 }
00575
00576 bool isEnd() const
00577
00578 {
00579 return past_the_end_;
00580 }
00581
00582 ValueType& getData()
00583
00584 {
00585 validate();
00586 return bound_->getCurrent();
00587 }
00588
00589 const ValueType& getData() const
00590
00591 {
00592
00593 const_cast<typename Enumerator<Container, SiteIterator, Variant>::IteratorTraits_*>(this)->validate();
00594 return bound_->getCurrent();
00595 }
00596
00597 void forward()
00598
00599 {
00600 try
00601 {
00602 ++position_;
00603 }
00604 catch (Exception::IndexOverflow&)
00605 {
00606 past_the_end_ = true;
00607 position_ = 0;
00608 }
00609 }
00610
00611 void validate()
00612
00613 {
00614 if (!bound_->is_valid_position_
00615 || (position_ != bound_->position_))
00616 {
00617 bound_->createCombination(position_);
00618 }
00619 }
00620
00621 protected:
00622 ContainerPointer bound_;
00623 EnumeratorIndex position_;
00624 bool past_the_end_;
00625 };
00626
00627
00628 static inline void defaultAssign_(Variant& a, const Variant& b)
00629 {
00630 a = b;
00631 }
00632
00633 void mutate_(SiteIterator& it, const Variant& v)
00634
00635 {
00636 mutator_(*it, v);
00637 }
00638
00639 Container& container_;
00640 MutatorFunction mutator_;
00641 SiteList variant_sites_;
00642 EnumeratorIndex position_;
00643 bool is_valid_position_;
00644 };
00645
00646 template <typename Container, typename SiteIterator, typename Variant>
00647 Enumerator<Container, SiteIterator, Variant>::Enumerator()
00648
00649 : container_(const_cast<Container&>(RTTI::getDefault<Container>())),
00650 mutator_(0)
00651 {
00652 }
00653
00654 template <typename Container, typename SiteIterator, typename Variant>
00655 Enumerator<Container, SiteIterator, Variant>::Enumerator(Container& container)
00656
00657 : container_(container),
00658 mutator_(defaultAssign_)
00659 {
00660 }
00661
00662 template <typename Container, typename SiteIterator, typename Variant>
00663 BALL_INLINE
00664 Enumerator<Container, SiteIterator, Variant>::Enumerator
00665 (Container& container, typename Enumerator<Container, SiteIterator, Variant>::MutatorFunction mutator)
00666
00667 : container_(container),
00668 mutator_(mutator)
00669 {
00670 }
00671
00672
00673 template <typename Container, typename SiteIterator, typename Variant>
00674 BALL_INLINE
00675 Container& Enumerator<Container, SiteIterator, Variant>::getCurrent()
00676
00677 {
00678 return container_;
00679 }
00680
00681 template <typename Container, typename SiteIterator, typename Variant>
00682 void Enumerator<Container, SiteIterator, Variant>::createCombination(const Position index)
00683 throw(Exception::IndexOverflow)
00684 {
00685 try
00686 {
00687 position_ = index;
00688 createCombination(position_);
00689 }
00690 catch (EnumeratorIndex::IncompatibleIndex&)
00691 {
00692 throw Exception::IndexOverflow(__FILE__, __LINE__, index);
00693 }
00694 }
00695
00696 template <typename Container, typename SiteIterator, typename Variant>
00697 void Enumerator<Container, SiteIterator, Variant>::createCombination(const EnumeratorIndex& index)
00698 throw(EnumeratorIndex::IncompatibleIndex)
00699 {
00700 if (&index != &position_)
00701 {
00702 position_ = index;
00703 }
00704
00705 typename SiteList::iterator it = variant_sites_.begin();
00706 Position i((Position)(index.getSize() - 1));
00707 for (; it != variant_sites_.end(); ++it, --i)
00708 {
00709 mutate_(it->first, it->second[index[i]]);
00710 }
00711
00712 is_valid_position_ = true;
00713 }
00714
00715 template <typename Container, typename SiteIterator, typename Variant>
00716 BALL_INLINE
00717 typename Enumerator<Container, SiteIterator, Variant>::Iterator Enumerator<Container, SiteIterator, Variant>::begin()
00718
00719 {
00720 return Iterator::begin(*this);
00721 }
00722
00723 template <typename Container, typename SiteIterator, typename Variant>
00724 BALL_INLINE
00725 typename Enumerator<Container, SiteIterator, Variant>::Iterator Enumerator<Container, SiteIterator, Variant>::end()
00726
00727 {
00728 return Iterator::end(*this);
00729 }
00730
00731 template <typename Container, typename VariantConstIterator, typename Variant>
00732 BALL_INLINE
00733 typename Enumerator<Container, VariantConstIterator, Variant>::ConstIterator Enumerator<Container, VariantConstIterator, Variant>::begin() const
00734
00735 {
00736 return ConstIterator::begin(*this);
00737 }
00738
00739 template <typename Container, typename VariantConstIterator, typename Variant>
00740 BALL_INLINE
00741 typename Enumerator<Container, VariantConstIterator, Variant>::ConstIterator Enumerator<Container, VariantConstIterator, Variant>::end() const
00742
00743 {
00744 return ConstIterator::end(*this);
00745 }
00746
00747
00748 # ifndef BALL_NO_INLINE_FUNCTIONS
00749 # include <BALL/CONCEPT/enumerator.iC>
00750 # endif
00751
00752 }
00753
00754 #endif // BALL_CONCEPT_ENUMERATOR_H