mdds
soa/iterator.hpp
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
3  *
4  * Copyright (c) 2021 Kohei Yoshida
5  *
6  * Permission is hereby granted, free of charge, to any person
7  * obtaining a copy of this software and associated documentation
8  * files (the "Software"), to deal in the Software without
9  * restriction, including without limitation the rights to use,
10  * copy, modify, merge, publish, distribute, sublicense, and/or sell
11  * copies of the Software, and to permit persons to whom the
12  * Software is furnished to do so, subject to the following
13  * conditions:
14  *
15  * The above copyright notice and this permission notice shall be
16  * included in all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25  * OTHER DEALINGS IN THE SOFTWARE.
26  *
27  ************************************************************************/
28 
29 #ifndef INCLUDED_MDDS_MULTI_TYPE_VECTOR_DIR_SOA_ITERATOR_HPP
30 #define INCLUDED_MDDS_MULTI_TYPE_VECTOR_DIR_SOA_ITERATOR_HPP
31 
32 #include "../iterator_node.hpp"
33 
34 #include <ostream>
35 
36 namespace mdds { namespace mtv { namespace soa { namespace detail {
37 
54 template<typename _Trait>
56 {
57 protected:
58  using parent_type = typename _Trait::parent;
59  using positions_type = typename _Trait::positions_type;
60  using sizes_type = typename _Trait::sizes_type;
61  using element_blocks_type = typename _Trait::element_blocks_type;
62  using size_type = typename _Trait::parent::size_type;
63 
65 
66  using positions_iterator_type = typename _Trait::positions_iterator_type;
67  using sizes_iterator_type = typename _Trait::sizes_iterator_type;
68  using element_blocks_iterator_type = typename _Trait::element_blocks_iterator_type;
69 
75  {
76  positions_iterator_type position_iterator;
77  sizes_iterator_type size_iterator;
78  element_blocks_iterator_type element_block_iterator;
79 
80  void inc()
81  {
82  ++position_iterator;
83  ++size_iterator;
84  ++element_block_iterator;
85  }
86 
87  void dec()
88  {
89  --position_iterator;
90  --size_iterator;
91  --element_block_iterator;
92  }
93 
94  bool operator==(const grouped_iterator_type& other) const
95  {
96  return position_iterator == other.position_iterator &&
97  size_iterator == other.size_iterator &&
98  element_block_iterator == other.element_block_iterator;
99  }
100 
101  bool operator!=(const grouped_iterator_type& other) const
102  {
103  return !operator==(other);
104  }
105 
106  grouped_iterator_type() = default;
107 
109  const positions_iterator_type& itr_pos,
110  const sizes_iterator_type& itr_size,
111  const element_blocks_iterator_type& itr_elem_blocks) :
112  position_iterator(itr_pos),
113  size_iterator(itr_size),
114  element_block_iterator(itr_elem_blocks)
115  {
116  }
117  };
118 
119  node m_cur_node;
120  grouped_iterator_type m_pos;
121  grouped_iterator_type m_end;
122 
123  iterator_updater() : m_cur_node(0) {}
124 
126  const grouped_iterator_type& pos, const grouped_iterator_type& end, size_type block_index) :
127  m_cur_node(block_index),
128  m_pos(pos),
129  m_end(end)
130  {
131  if (m_pos != m_end)
132  update_node();
133  }
134 
135  iterator_updater(
136  const positions_iterator_type& positions_pos,
137  const sizes_iterator_type& sizes_pos,
138  const element_blocks_iterator_type& eb_pos,
139  const positions_iterator_type& positions_end,
140  const sizes_iterator_type& sizes_end,
141  const element_blocks_iterator_type& eb_end,
142  size_type block_index) :
143  iterator_updater(
144  { positions_pos, sizes_pos, eb_pos },
145  { positions_end, sizes_end, eb_end },
146  block_index
147  )
148  {
149  }
150 
151  iterator_updater(const iterator_updater& other) :
152  m_cur_node(other.m_cur_node),
153  m_pos(other.m_pos),
154  m_end(other.m_end)
155  {
156  }
157 
158  void update_node()
159  {
160 #ifdef MDDS_MULTI_TYPE_VECTOR_DEBUG
161  if (m_pos == m_end)
162  throw general_error("Current node position should never equal the end position during node update.");
163 #endif
164 
165  m_cur_node.position = *m_pos.position_iterator;
166  m_cur_node.size = *m_pos.size_iterator;
167  m_cur_node.data = *m_pos.element_block_iterator;
168 
169  if (m_cur_node.data)
170  m_cur_node.type = mdds::mtv::get_block_type(*m_cur_node.data);
171  else
172  m_cur_node.type = mdds::mtv::element_type_empty;
173  }
174 
175  node* inc()
176  {
177  m_pos.inc();
178  if (m_pos == m_end)
179  return nullptr;
180 
181  update_node();
182  return &m_cur_node;
183  }
184 
185  node* dec()
186  {
187  m_pos.dec();
188  update_node();
189  return &m_cur_node;
190  }
191 
192  void _print_state(std::ostream& os) const
193  {
194  os << "block-index=" << m_cur_node.__private_data.block_index
195  << "; position=" << m_cur_node.position
196  << "; size=" << m_cur_node.size
197  << "; type=" << m_cur_node.type
198  << "; data=" << m_cur_node.data;
199  }
200 
201 public:
202  bool operator== (const iterator_updater& other) const
203  {
204  if (m_pos != m_end && other.m_pos != other.m_end)
205  {
206  // TODO: Set hard-coded values to the current node for the end
207  // position nodes to remove this if block.
208  if (m_cur_node != other.m_cur_node)
209  return false;
210  }
211  return m_pos == other.m_pos && m_end == other.m_end;
212  }
213 
214  bool operator!= (const iterator_updater& other) const
215  {
216  return !operator==(other);
217  }
218 
219  iterator_updater& operator= (const iterator_updater& other)
220  {
221  m_cur_node = other.m_cur_node;
222  m_pos = other.m_pos;
223  m_end = other.m_end;
224  return *this;
225  }
226 
227  void swap(iterator_updater& other)
228  {
229  m_cur_node.swap(other.m_cur_node);
230  std::swap(m_pos, other.m_pos);
231  std::swap(m_end, other.m_end);
232  }
233 
234  const node& get_node() const { return m_cur_node; }
235  const grouped_iterator_type& get_pos() const { return m_pos; }
236  const grouped_iterator_type& get_end() const { return m_end; }
237 };
238 
239 template<typename _Trait>
240 class iterator_base : public iterator_updater<_Trait>
241 {
242  using node_update_func = typename _Trait::private_data_update;
244 
245  using grouped_iterator_type = typename updater::grouped_iterator_type;
246  using size_type = typename updater::size_type;
247 
248  using updater::inc;
249  using updater::dec;
250  using updater::m_cur_node;
251 
252 public:
253 
254  using updater::get_pos;
255  using updater::get_end;
256 
257  // iterator traits
258  using value_type = typename updater::node;
259  using pointer = value_type*;
260  using reference = value_type&;
261  using difference_type = ptrdiff_t;
262  using iterator_category = std::bidirectional_iterator_tag;
263 
264 public:
265  iterator_base() {}
267  const grouped_iterator_type& pos, const grouped_iterator_type& end, size_type block_index) :
268  updater(pos, end, block_index) {}
269 
270  value_type& operator*()
271  {
272  return m_cur_node;
273  }
274 
275  const value_type& operator*() const
276  {
277  return m_cur_node;
278  }
279 
280  value_type* operator->()
281  {
282  return &m_cur_node;
283  }
284 
285  const value_type* operator->() const
286  {
287  return &m_cur_node;
288  }
289 
290  iterator_base& operator++()
291  {
292  node_update_func::inc(m_cur_node);
293  inc();
294  return *this;
295  }
296 
297  iterator_base& operator--()
298  {
299  dec();
300  node_update_func::dec(m_cur_node);
301  return *this;
302  }
303 
304  void _print_state(std::ostream& os) const
305  {
306  os << "{iterator: ";
307  updater::_print_state(os);
308  os << "}";
309  }
310 };
311 
312 template<typename _Trait, typename _NonConstItrBase>
313 class const_iterator_base : public iterator_updater<_Trait>
314 {
315  using node_update_func = typename _Trait::private_data_update;
317 
318  using grouped_iterator_type = typename updater::grouped_iterator_type;
319  using size_type = typename updater::size_type;
320 
321  using updater::inc;
322  using updater::dec;
323  using updater::m_cur_node;
324 
325 public:
326 
327  using updater::get_pos;
328  using updater::get_end;
329 
330  using iterator_base = _NonConstItrBase;
331 
332  // iterator traits
333  using value_type = typename updater::node;
334  using pointer = value_type*;
335  using reference = value_type&;
336  using difference_type = ptrdiff_t;
337  using iterator_category = std::bidirectional_iterator_tag;
338 
339 public:
342  const grouped_iterator_type& pos, const grouped_iterator_type& end, size_type block_index) :
343  updater(pos, end, block_index) {}
344 
348  const_iterator_base(const iterator_base& other) :
349  updater(
350  other.get_pos().position_iterator,
351  other.get_pos().size_iterator,
352  other.get_pos().element_block_iterator,
353  other.get_end().position_iterator,
354  other.get_end().size_iterator,
355  other.get_end().element_block_iterator,
356  other.get_node().__private_data.block_index) {}
357 
358  const value_type& operator*() const
359  {
360  return m_cur_node;
361  }
362 
363  const value_type* operator->() const
364  {
365  return &m_cur_node;
366  }
367 
368  const_iterator_base& operator++()
369  {
370  node_update_func::inc(m_cur_node);
371  inc();
372  return *this;
373  }
374 
375  const_iterator_base& operator--()
376  {
377  dec();
378  node_update_func::dec(m_cur_node);
379  return *this;
380  }
381 
382  bool operator== (const const_iterator_base& other) const
383  {
384  return updater::operator==(other);
385  }
386 
387  bool operator!= (const const_iterator_base& other) const
388  {
389  return updater::operator!=(other);
390  }
391 
392  void _print_state(std::ostream& os) const
393  {
394  os << "(const-iterator: ";
395  updater::_print_state(os);
396  os << ")";
397  }
398 };
399 
400 template<typename _Trait>
401 std::ostream& operator<< (std::ostream& os, const iterator_base<_Trait>& it)
402 {
403  it._print_state(os);
404  return os;
405 }
406 
407 template<typename _Trait, typename _NonConstItrBase>
408 std::ostream& operator<< (std::ostream& os, const const_iterator_base<_Trait, _NonConstItrBase>& it)
409 {
410  it._print_state(os);
411  return os;
412 }
413 
414 }}}}
415 
416 
417 #endif
418 
419 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
420 
Definition: soa/iterator.hpp:314
const_iterator_base(const iterator_base &other)
Definition: soa/iterator.hpp:348
Definition: soa/iterator.hpp:241
Definition: soa/iterator.hpp:56