Sierra Toolkit  Version of the Day
Iterators.hpp
1 #ifndef Toolkit_Iterators_hpp
2 #define Toolkit_Iterators_hpp
3 
4 #include <stk_mesh/base/Bucket.hpp>
5 #include <stk_mesh/base/Selector.hpp>
6 
7 #include <boost/iterator/filter_iterator.hpp>
8 
9 #include <vector>
10 #include <algorithm>
11 
12 namespace stk_classic {
13 namespace mesh {
14 
15 // Requirements:
16 // Dereference of HighLevelItrType gives a container (OR pointer to container) with iterators compatible with LowLevelItrType
17 // Dereference of LowLevelItrType gives ValueType
18 // LowLevelItrType must default-construct to a deterministic invalid value
19 //
20 // Incrementing this iterator will take us to the next valid low-level iterator, skipping past
21 // empty high-level containers, until the end iterator.
22 template<typename HighLevelItrType, typename LowLevelItrType>
23 class TwoLevelIterator : public std::iterator<std::forward_iterator_tag, typename LowLevelItrType::value_type>
24 {
25  public:
26  typedef TwoLevelIterator<HighLevelItrType, LowLevelItrType> self;
27 
28  // Construct an iterator from a starting point specified by high_itr and low_itr
29  TwoLevelIterator(HighLevelItrType high_itr, LowLevelItrType low_itr, HighLevelItrType high_end_itr) :
30  m_high_itr(high_itr),
31  m_low_itr(low_itr),
32  m_high_end_itr(high_end_itr)
33  {
34  if (high_itr != high_end_itr) {
35  find_next_valid_item();
36  }
37  }
38 
39  // Construct the "end" iterator
40  TwoLevelIterator(HighLevelItrType high_end_itr) :
41  m_high_itr(high_end_itr),
42  m_low_itr(),
43  m_high_end_itr(high_end_itr)
44  {}
45 
46  TwoLevelIterator() :
47  m_high_itr(),
48  m_low_itr(),
49  m_high_end_itr()
50  {}
51 
52  bool operator==(const self& rhs) const
53  {
54  return (m_high_itr == rhs.m_high_itr && m_low_itr == rhs.m_low_itr);
55  }
56 
57  bool operator!=(const self& rhs) const
58  {
59  return !(*this == rhs);
60  }
61 
62  // x++
63  self operator++(int)
64  {
65  self copy = *this;
66  increment();
67  return copy;
68  }
69 
70  // ++x
71  self& operator++()
72  {
73  increment();
74  return *this;
75  }
76 
77  typename LowLevelItrType::reference operator*() const
78  {
79  return *m_low_itr;
80  }
81 
82  typename LowLevelItrType::pointer operator->() const
83  {
84  return &*m_low_itr;
85  }
86 
87  private:
88  void find_next_valid_item()
89  {
90  // if low_itr is at the end of current container, go to next container
91  while (m_low_itr == get_end(*m_high_itr)) {
92  ++m_high_itr;
93  if (m_high_itr == m_high_end_itr) {
94  // We reached the end! Set low_itr to invalid and return
95  m_low_itr = LowLevelItrType();
96  return;
97  }
98  m_low_itr = get_begin(*m_high_itr);
99  }
100  }
101 
102  // The 4 methods below are needed for supporting the notion that high_itr
103  // can dereference to a container or a pointer to a container.
104 
105  template <typename Cont>
106  LowLevelItrType
107  get_begin(Cont& container)
108  {
109  return LowLevelItrType(container.begin());
110  }
111 
112  template <typename Cont>
113  LowLevelItrType
114  get_end(Cont& container)
115  {
116  return LowLevelItrType(container.end());
117  }
118 
119  template <class Cont>
120  LowLevelItrType
121  get_begin(Cont* container_ptr)
122  {
123  return LowLevelItrType(container_ptr->begin());
124  }
125 
126  template <class Cont>
127  LowLevelItrType
128  get_end(Cont* container_ptr)
129  {
130  return LowLevelItrType(container_ptr->end());
131  }
132 
133  void increment()
134  {
135  ++m_low_itr;
136  find_next_valid_item();
137  }
138 
139  HighLevelItrType m_high_itr;
140  LowLevelItrType m_low_itr;
141  HighLevelItrType m_high_end_itr;
142 };
143 
144 // Requirements:
145 // BucketIteratorType must dereference to a Bucket*
146 //
147 // Incrementing this iterator will take us to the next *selected* bucket, skipping past
148 // unselected buckets, until the end.
149 //
150 // As long as we're using a pointer as the value type, we need to
151 // specify the reference type to be the value_type in order for this
152 // class to work with boost
153 template <typename BucketIteratorType>
154 class SelectedBucketIterator : public std::iterator<std::forward_iterator_tag,
155  typename BucketIteratorType::value_type,
156  typename BucketIteratorType::difference_type,
157  typename BucketIteratorType::pointer,
158  typename BucketIteratorType::value_type>
159 {
160  public:
161  typedef SelectedBucketIterator<BucketIteratorType> self;
162 
163  SelectedBucketIterator(const Selector& selector, BucketIteratorType bucket_itr, BucketIteratorType bucket_end_itr) :
164  m_bucket_itr(bucket_itr),
165  m_bucket_end_itr(bucket_end_itr),
166  m_selector(selector)
167  {
168  if (bucket_itr != bucket_end_itr) {
169  find_next_valid_item();
170  }
171  }
172 
173  // Construct the "end" iterator
174  SelectedBucketIterator(BucketIteratorType bucket_end_itr) :
175  m_bucket_itr(bucket_end_itr),
176  m_bucket_end_itr(bucket_end_itr),
177  m_selector()
178  {}
179 
180  SelectedBucketIterator() :
181  m_bucket_itr(),
182  m_bucket_end_itr(),
183  m_selector()
184  {}
185 
186  SelectedBucketIterator(const self& rhs) :
187  m_bucket_itr(rhs.m_bucket_itr),
188  m_bucket_end_itr(rhs.m_bucket_end_itr),
189  m_selector(rhs.m_selector)
190  {}
191 
192  self& operator=(const self& rhs)
193  {
194  m_bucket_itr = rhs.m_bucket_itr;
195  m_bucket_end_itr = rhs.m_bucket_end_itr;
196  m_selector = rhs.m_selector;
197 
198  return *this;
199  }
200 
201  bool operator==(const self& rhs) const
202  {
203  return (m_bucket_itr == rhs.m_bucket_itr);
204  }
205 
206  bool operator==(const BucketIteratorType& rhs) const
207  {
208  return (m_bucket_itr == rhs);
209  }
210 
211  bool operator!=(const self& rhs) const
212  {
213  return !(*this == rhs);
214  }
215 
216  // x++
217  self operator++(int)
218  {
219  self copy = *this;
220  increment();
221  return copy;
222  }
223 
224  // ++x
225  self& operator++()
226  {
227  increment();
228  return *this;
229  }
230 
231  // The method below is why boost::filter_iterator won't work for us. filter_iterator
232  // deferences to a reference, tranform iterator dereferences to a copy, making them
233  // incompatible.
234  typename BucketIteratorType::value_type operator*() const
235  {
236  return *m_bucket_itr;
237  }
238 
239  typename BucketIteratorType::pointer operator->() const
240  {
241  return &*m_bucket_itr;
242  }
243 
244  private:
245  void find_next_valid_item()
246  {
247  while (m_bucket_itr != m_bucket_end_itr && !m_selector(**m_bucket_itr)) {
248  ++m_bucket_itr;
249  }
250  }
251 
252  void increment()
253  {
254  ++m_bucket_itr;
255  find_next_valid_item();
256  }
257 
258  BucketIteratorType m_bucket_itr;
259  BucketIteratorType m_bucket_end_itr;
260  Selector m_selector;
261 };
262 
263 // Iterator for iterating over all entities within each bucket of a vector of buckets
264 typedef TwoLevelIterator<std::vector<Bucket*>::const_iterator, BucketPtrIterator> BucketVectorEntityIterator;
265 typedef std::pair<BucketVectorEntityIterator, BucketVectorEntityIterator> BucketVectorEntityIteratorRange;
266 
267 // Iterator for iterating over selected buckets within a vector of buckets
268 typedef SelectedBucketIterator<std::vector<Bucket*>::const_iterator> SelectedBucketVectorIterator;
269 //typedef boost::filter_iterator<Selector, std::vector<Bucket*>::const_iterator> SelectedBucketVectorIterator;
270 typedef std::pair<SelectedBucketVectorIterator, SelectedBucketVectorIterator> SelectedBucketVectorIteratorRange;
271 
272 // Iterator for iterating over all entities within each *selected* bucket of a vector of buckets
273 typedef TwoLevelIterator<SelectedBucketVectorIterator, BucketPtrIterator> SelectedBucketVectorEntityIterator;
274 typedef std::pair<SelectedBucketVectorEntityIterator, SelectedBucketVectorEntityIterator> SelectedBucketVectorEntityIteratorRange;
275 
276 // Iterator for iterating over all buckets in a vector of vectors of buckets
277 typedef TwoLevelIterator<std::vector<std::vector<Bucket*> >::const_iterator, std::vector<Bucket*>::const_iterator> AllBucketsIterator;
278 typedef std::pair<AllBucketsIterator, AllBucketsIterator> AllBucketsRange;
279 
280 // Iterator for iterating over all *selected* buckets in a bucket range
281 typedef SelectedBucketIterator<AllBucketsIterator> AllSelectedBucketsIterator;
282 //typedef boost::filter_iterator<Selector, AllBucketsIterator> AllSelectedBucketsIterator;
283 typedef std::pair<AllSelectedBucketsIterator, AllSelectedBucketsIterator> AllSelectedBucketsRange;
284 
285 // Iterator for iterating over all entities within each bucket of a bucket range
286 typedef TwoLevelIterator<AllBucketsIterator, BucketPtrIterator> BucketRangeEntityIterator;
287 typedef std::pair<BucketRangeEntityIterator, BucketRangeEntityIterator> BucketRangeEntityIteratorRange;
288 
289 // Iterator for iterating over all *selected* entities withing a bucket range
290 typedef TwoLevelIterator<AllSelectedBucketsIterator, BucketPtrIterator> SelectedBucketRangeEntityIterator;
291 typedef std::pair<SelectedBucketRangeEntityIterator, SelectedBucketRangeEntityIterator> SelectedBucketRangeEntityIteratorRange;
292 
293 //
294 // API - Convert collections into ranges. For internal use only. Clients should use
295 // GetBuckets.hpp, GetEntities.hpp or their BulkData object.
296 //
297 
298 // Get a range allowing you to iterate over all entities withing a collection of buckets
299 BucketVectorEntityIteratorRange get_entity_range(const std::vector<Bucket*>& buckets);
300 
301 // Get a range allowing you to iterate over all *selected* entities withing a collection of buckets
302 SelectedBucketVectorEntityIteratorRange get_entity_range(const std::vector<Bucket*>& buckets, const Selector& selector);
303 
304 // Get a range allowing you to iterate over all buckets within a collection of collections of buckets
305 AllBucketsRange get_bucket_range(const std::vector<std::vector<Bucket*> >& buckets);
306 
307 // Get a range allowing you to iterate over a single collection of buckets within a collection of collections of buckets;
308 // the single collection is specified by the itr argument.
309 AllBucketsRange get_bucket_range(const std::vector<std::vector<Bucket*> >& buckets,
310  std::vector<std::vector<Bucket*> >::const_iterator itr);
311 
312 // Get a range allowing you to iterate over all *selected* buckets within a collection of collections of buckets
313 AllSelectedBucketsRange get_selected_bucket_range(const AllBucketsRange& bucket_range, const Selector& selector);
314 
315 // Get a range allowing you iterate over selected buckets in a vector
316 SelectedBucketVectorIteratorRange get_selected_bucket_range(const std::vector<Bucket*>& buckets, const Selector& selector);
317 
318 // Get a range allowing you to iterate over all *selected* buckets within a collection of collections of buckets
319 SelectedBucketRangeEntityIteratorRange get_selected_bucket_entity_range(const AllBucketsRange& bucket_range, const Selector& selector);
320 
321 } //namespace mesh
322 } //namespace stk_classic
323 
324 #endif
OutputIterator copy(InputIterator first, InputIterator last, OutputIterator result)
Sierra Toolkit.