Sierra Toolkit Version of the Day
Iterators.hpp
00001 #ifndef Toolkit_Iterators_hpp
00002 #define Toolkit_Iterators_hpp
00003 
00004 #include <stk_mesh/base/Bucket.hpp>
00005 #include <stk_mesh/base/Selector.hpp>
00006 
00007 #include <boost/iterator/filter_iterator.hpp>
00008 
00009 #include <vector>
00010 #include <algorithm>
00011 
00012 namespace stk {
00013 namespace mesh {
00014 
00015 // Requirements:
00016 //   Dereference of HighLevelItrType gives a container (OR pointer to container) with iterators compatible with LowLevelItrType
00017 //   Dereference of LowLevelItrType gives ValueType
00018 //   LowLevelItrType must default-construct to a deterministic invalid value
00019 //
00020 // Incrementing this iterator will take us to the next valid low-level iterator, skipping past
00021 // empty high-level containers, until the end iterator.
00022 template<typename HighLevelItrType, typename LowLevelItrType, typename ValueType>
00023 class TwoLevelIterator : public std::iterator<std::forward_iterator_tag, ValueType>
00024 {
00025  public:
00026   typedef TwoLevelIterator<HighLevelItrType, LowLevelItrType, ValueType>  self;
00027 
00028   // Construct an iterator from a starting point specified by high_itr and low_itr
00029   TwoLevelIterator(HighLevelItrType high_itr, LowLevelItrType low_itr, HighLevelItrType high_end_itr) :
00030     m_high_itr(high_itr),
00031     m_low_itr(low_itr),
00032     m_high_end_itr(high_end_itr)
00033   {
00034     if (high_itr != high_end_itr) {
00035       find_next_valid_item();
00036     }
00037   }
00038 
00039   // Construct the "end" iterator
00040   TwoLevelIterator(HighLevelItrType high_end_itr) :
00041     m_high_itr(high_end_itr),
00042     m_low_itr(),
00043     m_high_end_itr(high_end_itr)
00044   {}
00045 
00046   TwoLevelIterator(const self& rhs) :
00047     m_high_itr(rhs.m_high_itr),
00048     m_low_itr(rhs.m_low_itr),
00049     m_high_end_itr(rhs.m_high_end_itr)
00050   {}
00051 
00052   self& operator=(const self& rhs)
00053   {
00054     m_high_itr     = rhs.m_high_itr;
00055     m_low_itr      = rhs.m_low_itr;
00056     m_high_end_itr = rhs.m_high_end_itr;
00057 
00058     return *this;
00059   }
00060 
00061   bool operator==(const self& rhs) const
00062   {
00063     return (m_high_itr == rhs.m_high_itr && m_low_itr == rhs.m_low_itr);
00064   }
00065 
00066   bool operator!=(const self& rhs) const
00067   {
00068     return !(*this == rhs);
00069   }
00070 
00071   // ++x
00072   self& operator++(int)
00073   {
00074     increment();
00075     return *this;
00076   }
00077 
00078   // x++
00079   self operator++()
00080   {
00081     self copy = *this;
00082     increment();
00083     return copy;
00084   }
00085 
00086   ValueType operator*() const
00087   {
00088     return *m_low_itr;
00089   }
00090 
00091   ValueType* operator->() const
00092   {
00093     return &*m_low_itr;
00094   }
00095 
00096  private:
00097   void find_next_valid_item()
00098   {
00099     // if low_itr is at the end of current container, go to next container
00100     while (m_low_itr == get_end(*m_high_itr)) {
00101       ++m_high_itr;
00102       if (m_high_itr == m_high_end_itr) {
00103         // We reached the end! Set low_itr to invalid and return
00104         m_low_itr = LowLevelItrType();
00105         return;
00106       }
00107       m_low_itr = get_begin(*m_high_itr);
00108     }
00109   }
00110 
00111   // The 4 methods below are needed for supporting the notion that high_itr
00112   // can dereference to a container or a pointer to a container.
00113 
00114   template <typename Cont>
00115   LowLevelItrType
00116   get_begin(Cont& container)
00117   {
00118     return LowLevelItrType(container.begin());
00119   }
00120 
00121   template <typename Cont>
00122   LowLevelItrType
00123   get_end(Cont& container)
00124   {
00125     return LowLevelItrType(container.end());
00126   }
00127 
00128   template <class Cont>
00129   LowLevelItrType
00130   get_begin(Cont* container_ptr)
00131   {
00132     return LowLevelItrType(container_ptr->begin());
00133   }
00134 
00135   template <class Cont>
00136   LowLevelItrType
00137   get_end(Cont* container_ptr)
00138   {
00139     return LowLevelItrType(container_ptr->end());
00140   }
00141 
00142   void increment()
00143   {
00144     ++m_low_itr;
00145     find_next_valid_item();
00146   }
00147 
00148   HighLevelItrType   m_high_itr;
00149   LowLevelItrType    m_low_itr;
00150   HighLevelItrType   m_high_end_itr;
00151 };
00152 
00153 // Requirements:
00154 //   BucketIteratorType must dereference to a Bucket*
00155 //
00156 // Incrementing this iterator will take us to the next *selected* bucket, skipping past
00157 // unselected buckets, until the end.
00158 template <typename BucketIteratorType>
00159 class SelectedBucketIterator : public std::iterator<std::forward_iterator_tag, Bucket*>
00160 {
00161  public:
00162   typedef SelectedBucketIterator<BucketIteratorType> self;
00163 
00164   SelectedBucketIterator(const Selector& selector, BucketIteratorType bucket_itr, BucketIteratorType bucket_end_itr) :
00165     m_bucket_itr(bucket_itr),
00166     m_bucket_end_itr(bucket_end_itr),
00167     m_selector(selector)
00168   {
00169     if (bucket_itr != bucket_end_itr) {
00170       find_next_valid_item();
00171     }
00172   }
00173 
00174   // Construct the "end" iterator
00175   SelectedBucketIterator(BucketIteratorType bucket_end_itr) :
00176     m_bucket_itr(bucket_end_itr),
00177     m_bucket_end_itr(bucket_end_itr),
00178     m_selector()
00179   {}
00180 
00181   SelectedBucketIterator(const self& rhs) :
00182     m_bucket_itr(rhs.m_bucket_itr),
00183     m_bucket_end_itr(rhs.m_bucket_end_itr),
00184     m_selector(rhs.m_selector)
00185   {}
00186 
00187   self& operator=(const self& rhs)
00188   {
00189     m_bucket_itr     = rhs.m_bucket_itr;
00190     m_bucket_end_itr = rhs.m_bucket_end_itr;
00191     m_selector       = rhs.m_selector;
00192 
00193     return *this;
00194   }
00195 
00196   bool operator==(const self& rhs) const
00197   {
00198     return (m_bucket_itr == rhs.m_bucket_itr);
00199   }
00200 
00201   bool operator==(const BucketIteratorType& rhs) const
00202   {
00203     return (m_bucket_itr == rhs);
00204   }
00205 
00206   bool operator!=(const self& rhs) const
00207   {
00208     return !(*this == rhs);
00209   }
00210 
00211   // ++x
00212   self& operator++(int)
00213   {
00214     increment();
00215     return *this;
00216   }
00217 
00218   // x++
00219   self operator++()
00220   {
00221     self copy = *this;
00222     increment();
00223     return copy;
00224   }
00225 
00226   // The method below is why boost::filter_iterator won't work for us. filter_iterator
00227   // deferences to a reference, tranform iterator dereferences to a copy, making them
00228   // incompatible.
00229   Bucket* operator*() const
00230   {
00231     return *m_bucket_itr;
00232   }
00233 
00234   Bucket** operator->() const
00235   {
00236     return &*m_bucket_itr;
00237   }
00238 
00239  private:
00240   void find_next_valid_item()
00241   {
00242     while (m_bucket_itr != m_bucket_end_itr && !m_selector(**m_bucket_itr)) {
00243       ++m_bucket_itr;
00244     }
00245   }
00246 
00247   void increment()
00248   {
00249     ++m_bucket_itr;
00250     find_next_valid_item();
00251   }
00252 
00253   BucketIteratorType m_bucket_itr;
00254   BucketIteratorType m_bucket_end_itr;
00255   Selector           m_selector;
00256 };
00257 
00258 // Iterator for iterating over all entities within each bucket of a vector of buckets
00259 typedef TwoLevelIterator<std::vector<Bucket*>::const_iterator, BucketPtrIterator, Entity* const> BucketVectorEntityIterator;
00260 typedef std::pair<BucketVectorEntityIterator, BucketVectorEntityIterator>                        BucketVectorEntityIteratorRange;
00261 
00262 // Iterator for iterating over selected buckets within a vector of buckets
00263 typedef SelectedBucketIterator<std::vector<Bucket*>::const_iterator>                      SelectedBucketVectorIterator;
00264 //typedef boost::filter_iterator<Selector, std::vector<Bucket*>::const_iterator>            SelectedBucketVectorIterator;
00265 
00266 // Iterator for iterating over all entities within each *selected* bucket of a vector of buckets
00267 typedef TwoLevelIterator<SelectedBucketVectorIterator, BucketPtrIterator, Entity* const>  SelectedBucketVectorEntityIterator;
00268 typedef std::pair<SelectedBucketVectorEntityIterator, SelectedBucketVectorEntityIterator> SelectedBucketVectorEntityIteratorRange;
00269 
00270 // Iterator for iterating over all buckets in a vector of vectors of buckets
00271 typedef TwoLevelIterator<std::vector<std::vector<Bucket*> >::const_iterator, std::vector<Bucket*>::const_iterator, Bucket* const> AllBucketsIterator;
00272 typedef std::pair<AllBucketsIterator, AllBucketsIterator>                                                                         AllBucketsRange;
00273 
00274 // Iterator for iterating over all *selected* buckets in a bucket range
00275 typedef SelectedBucketIterator<AllBucketsIterator>                         AllSelectedBucketsIterator;
00276 //typedef boost::filter_iterator<Selector, AllBucketsIterator>               AllSelectedBucketsIterator;
00277 typedef std::pair<AllSelectedBucketsIterator, AllSelectedBucketsIterator>  AllSelectedBucketsRange;
00278 
00279 // Iterator for iterating over all entities within each bucket of a bucket range
00280 typedef TwoLevelIterator<AllBucketsIterator, BucketPtrIterator, Entity* const>  BucketRangeEntityIterator;
00281 typedef std::pair<BucketRangeEntityIterator, BucketRangeEntityIterator>         BucketRangeEntityIteratorRange;
00282 
00283 // Iterator for iterating over all *selected* entities withing a bucket range
00284 typedef TwoLevelIterator<AllSelectedBucketsIterator, BucketPtrIterator, Entity* const>    SelectedBucketRangeEntityIterator;
00285 typedef std::pair<SelectedBucketRangeEntityIterator, SelectedBucketRangeEntityIterator>   SelectedBucketRangeEntityIteratorRange;
00286 
00287 //
00288 // API - Convert collections into ranges. For internal use only. Clients should use
00289 //       GetBuckets.hpp, GetEntities.hpp or their BulkData object.
00290 //
00291 
00292 // Get a range allowing you to iterate over all entities withing a collection of buckets
00293 BucketVectorEntityIteratorRange get_entity_range(const std::vector<Bucket*>& buckets);
00294 
00295 // Get a range allowing you to iterate over all *selected* entities withing a collection of buckets
00296 SelectedBucketVectorEntityIteratorRange get_entity_range(const std::vector<Bucket*>& buckets, const Selector& selector);
00297 
00298 // Get a range allowing you to iterate over all buckets within a collection of collections of buckets
00299 AllBucketsRange get_bucket_range(const std::vector<std::vector<Bucket*> >& buckets);
00300 
00301 // Get a range allowing you to iterate over a single collection of buckets within a collection of collections of buckets;
00302 // the single collection is specified by the itr argument.
00303 AllBucketsRange get_bucket_range(const std::vector<std::vector<Bucket*> >& buckets,
00304                                  std::vector<std::vector<Bucket*> >::const_iterator itr);
00305 
00306 // Get a range allowing you to iterate over all *selected* buckets within a collection of collections of buckets
00307 AllSelectedBucketsRange get_selected_bucket_range(const AllBucketsRange& bucket_range, const Selector& selector);
00308 
00309 // Get a range allowing you to iterate over all *selected* buckets within a collection of collections of buckets
00310 SelectedBucketRangeEntityIteratorRange get_selected_bucket_entity_range(const AllBucketsRange& bucket_range, const Selector& selector);
00311 
00312 } //namespace mesh
00313 } //namespace stk
00314 
00315 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends