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