|
Sierra Toolkit
Version of the Day
|
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_classic { 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_classic 00323 00324 #endif