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 && size_iterator == other.size_iterator &&
97  element_block_iterator == other.element_block_iterator;
98  }
99 
100  bool operator!=(const grouped_iterator_type& other) const
101  {
102  return !operator==(other);
103  }
104 
105  grouped_iterator_type() = default;
106 
108  const positions_iterator_type& itr_pos, const sizes_iterator_type& itr_size,
109  const element_blocks_iterator_type& itr_elem_blocks)
110  : position_iterator(itr_pos), size_iterator(itr_size), element_block_iterator(itr_elem_blocks)
111  {}
112  };
113 
114  node m_cur_node;
115  grouped_iterator_type m_pos;
116  grouped_iterator_type m_end;
117 
118  iterator_updater() : m_cur_node(nullptr, 0)
119  {}
120 
122  const grouped_iterator_type& pos, const grouped_iterator_type& end, const parent_type* parent,
123  size_type block_index)
124  : m_cur_node(parent, block_index), m_pos(pos), m_end(end)
125  {
126  if (m_pos != m_end)
127  update_node();
128  }
129 
130  iterator_updater(
131  const positions_iterator_type& positions_pos, const sizes_iterator_type& sizes_pos,
132  const element_blocks_iterator_type& eb_pos, const positions_iterator_type& positions_end,
133  const sizes_iterator_type& sizes_end, const element_blocks_iterator_type& eb_end, const parent_type* parent,
134  size_type block_index)
135  : iterator_updater({positions_pos, sizes_pos, eb_pos}, {positions_end, sizes_end, eb_end}, parent, block_index)
136  {}
137 
138  iterator_updater(const iterator_updater& other)
139  : m_cur_node(other.m_cur_node), m_pos(other.m_pos), m_end(other.m_end)
140  {}
141 
142  void update_node()
143  {
144 #ifdef MDDS_MULTI_TYPE_VECTOR_DEBUG
145  if (m_pos == m_end)
146  throw general_error("Current node position should never equal the end position during node update.");
147 #endif
148 
149  m_cur_node.position = *m_pos.position_iterator;
150  m_cur_node.size = *m_pos.size_iterator;
151  m_cur_node.data = *m_pos.element_block_iterator;
152 
153  if (m_cur_node.data)
154  m_cur_node.type = mdds::mtv::get_block_type(*m_cur_node.data);
155  else
156  m_cur_node.type = mdds::mtv::element_type_empty;
157  }
158 
159  node* inc()
160  {
161  m_pos.inc();
162  if (m_pos == m_end)
163  return nullptr;
164 
165  update_node();
166  return &m_cur_node;
167  }
168 
169  node* dec()
170  {
171  m_pos.dec();
172  update_node();
173  return &m_cur_node;
174  }
175 
176  void _print_state(std::ostream& os) const
177  {
178  auto prev_flags = os.flags();
179  os << "parent=" << std::hex << m_cur_node.__private_data.parent
180  << "; block-index=" << m_cur_node.__private_data.block_index << "; position=" << m_cur_node.position
181  << "; size=" << m_cur_node.size << "; type=" << m_cur_node.type << "; data=" << m_cur_node.data;
182  os.flags(prev_flags);
183  }
184 
185 public:
186  bool operator==(const iterator_updater& other) const
187  {
188  if (m_pos != m_end && other.m_pos != other.m_end)
189  {
190  // TODO: Set hard-coded values to the current node for the end
191  // position nodes to remove this if block.
192  if (m_cur_node != other.m_cur_node)
193  return false;
194  }
195  return m_pos == other.m_pos && m_end == other.m_end;
196  }
197 
198  bool operator!=(const iterator_updater& other) const
199  {
200  return !operator==(other);
201  }
202 
203  iterator_updater& operator=(const iterator_updater& other)
204  {
205  m_cur_node = other.m_cur_node;
206  m_pos = other.m_pos;
207  m_end = other.m_end;
208  return *this;
209  }
210 
211  void swap(iterator_updater& other)
212  {
213  m_cur_node.swap(other.m_cur_node);
214  std::swap(m_pos, other.m_pos);
215  std::swap(m_end, other.m_end);
216  }
217 
218  const node& get_node() const
219  {
220  return m_cur_node;
221  }
222  const grouped_iterator_type& get_pos() const
223  {
224  return m_pos;
225  }
226  const grouped_iterator_type& get_end() const
227  {
228  return m_end;
229  }
230 };
231 
232 template<typename Trait>
233 class iterator_base : public iterator_updater<Trait>
234 {
235  using parent_type = typename Trait::parent;
236  using node_update_func = typename Trait::private_data_update;
238 
239  using grouped_iterator_type = typename updater::grouped_iterator_type;
240  using size_type = typename updater::size_type;
241 
242  using updater::dec;
243  using updater::inc;
244  using updater::m_cur_node;
245 
246 public:
247  using updater::get_end;
248  using updater::get_pos;
249 
250  // iterator traits
251  using value_type = typename updater::node;
252  using pointer = value_type*;
253  using reference = value_type&;
254  using difference_type = ptrdiff_t;
255  using iterator_category = std::bidirectional_iterator_tag;
256 
257 public:
258  iterator_base()
259  {}
261  const grouped_iterator_type& pos, const grouped_iterator_type& end, const parent_type* parent,
262  size_type block_index)
263  : updater(pos, end, parent, block_index)
264  {}
265 
266  value_type& operator*()
267  {
268  return m_cur_node;
269  }
270 
271  const value_type& operator*() const
272  {
273  return m_cur_node;
274  }
275 
276  value_type* operator->()
277  {
278  return &m_cur_node;
279  }
280 
281  const value_type* operator->() const
282  {
283  return &m_cur_node;
284  }
285 
286  iterator_base& operator++()
287  {
288  node_update_func::inc(m_cur_node);
289  inc();
290  return *this;
291  }
292 
293  iterator_base& operator--()
294  {
295  dec();
296  node_update_func::dec(m_cur_node);
297  return *this;
298  }
299 
300  void _print_state(std::ostream& os) const
301  {
302  os << "{iterator: ";
303  updater::_print_state(os);
304  os << "}";
305  }
306 };
307 
308 template<typename Trait, typename NonConstItrBase>
310 {
311  using parent_type = typename Trait::parent;
312  using node_update_func = typename Trait::private_data_update;
314 
315  using grouped_iterator_type = typename updater::grouped_iterator_type;
316  using size_type = typename updater::size_type;
317 
318  using updater::dec;
319  using updater::inc;
320  using updater::m_cur_node;
321 
322 public:
323  using updater::get_end;
324  using updater::get_pos;
325 
326  using iterator_base = NonConstItrBase;
327 
328  // iterator traits
329  using value_type = typename updater::node;
330  using pointer = value_type*;
331  using reference = value_type&;
332  using difference_type = ptrdiff_t;
333  using iterator_category = std::bidirectional_iterator_tag;
334 
335 public:
337  {}
339  const grouped_iterator_type& pos, const grouped_iterator_type& end, const parent_type* parent,
340  size_type block_index)
341  : updater(pos, end, parent, block_index)
342  {}
343 
347  const_iterator_base(const iterator_base& other)
348  : updater(
349  other.get_pos().position_iterator, other.get_pos().size_iterator, other.get_pos().element_block_iterator,
350  other.get_end().position_iterator, other.get_end().size_iterator, other.get_end().element_block_iterator,
351  other.get_node().__private_data.parent, other.get_node().__private_data.block_index)
352  {}
353 
354  const value_type& operator*() const
355  {
356  return m_cur_node;
357  }
358 
359  const value_type* operator->() const
360  {
361  return &m_cur_node;
362  }
363 
364  const_iterator_base& operator++()
365  {
366  node_update_func::inc(m_cur_node);
367  inc();
368  return *this;
369  }
370 
371  const_iterator_base& operator--()
372  {
373  dec();
374  node_update_func::dec(m_cur_node);
375  return *this;
376  }
377 
378  bool operator==(const const_iterator_base& other) const
379  {
380  return updater::operator==(other);
381  }
382 
383  bool operator!=(const const_iterator_base& other) const
384  {
385  return updater::operator!=(other);
386  }
387 
388  void _print_state(std::ostream& os) const
389  {
390  os << "(const-iterator: ";
391  updater::_print_state(os);
392  os << ")";
393  }
394 };
395 
396 template<typename Trait>
397 std::ostream& operator<<(std::ostream& os, const iterator_base<Trait>& it)
398 {
399  it._print_state(os);
400  return os;
401 }
402 
403 template<typename Trait, typename NonConstItrBase>
404 std::ostream& operator<<(std::ostream& os, const const_iterator_base<Trait, NonConstItrBase>& it)
405 {
406  it._print_state(os);
407  return os;
408 }
409 
410 }}}} // namespace mdds::mtv::soa::detail
411 
412 #endif
413 
414 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Definition: soa/iterator.hpp:310
const_iterator_base(const iterator_base &other)
Definition: soa/iterator.hpp:347
Definition: soa/iterator.hpp:234
Definition: soa/iterator.hpp:56