BALL
1.4.1
|
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