mdds
iterator.hpp
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 
3 // SPDX-FileCopyrightText: 2021 - 2025 Kohei Yoshida
4 //
5 // SPDX-License-Identifier: MIT
6 
7 #pragma once
8 
9 #include "../iterator_node.hpp"
10 
11 #include <ostream>
12 
13 namespace mdds { namespace mtv { namespace soa { namespace detail {
14 
31 template<typename Traits>
33 {
34 protected:
35  using parent_type = typename Traits::parent;
36  using positions_type = typename Traits::positions_type;
37  using sizes_type = typename Traits::sizes_type;
38  using element_blocks_type = typename Traits::element_blocks_type;
39  using size_type = typename Traits::parent::size_type;
40 
42 
43  using positions_iterator_type = typename Traits::positions_iterator_type;
44  using sizes_iterator_type = typename Traits::sizes_iterator_type;
45  using element_blocks_iterator_type = typename Traits::element_blocks_iterator_type;
46 
52  {
53  positions_iterator_type position_iterator;
54  sizes_iterator_type size_iterator;
55  element_blocks_iterator_type element_block_iterator;
56 
57  void inc()
58  {
59  ++position_iterator;
60  ++size_iterator;
61  ++element_block_iterator;
62  }
63 
64  void dec()
65  {
66  --position_iterator;
67  --size_iterator;
68  --element_block_iterator;
69  }
70 
71  bool operator==(const grouped_iterator_type& other) const
72  {
73  return position_iterator == other.position_iterator && size_iterator == other.size_iterator &&
74  element_block_iterator == other.element_block_iterator;
75  }
76 
77  bool operator!=(const grouped_iterator_type& other) const
78  {
79  return !operator==(other);
80  }
81 
82  grouped_iterator_type() = default;
83 
85  const positions_iterator_type& itr_pos, const sizes_iterator_type& itr_size,
86  const element_blocks_iterator_type& itr_elem_blocks)
87  : position_iterator(itr_pos), size_iterator(itr_size), element_block_iterator(itr_elem_blocks)
88  {}
89  };
90 
91  node m_cur_node;
94 
95  iterator_updater() : m_cur_node(nullptr, 0)
96  {}
97 
99  const grouped_iterator_type& pos, const grouped_iterator_type& end, const parent_type* parent,
100  size_type block_index)
101  : m_cur_node(parent, block_index), m_pos(pos), m_end(end)
102  {
103  if (m_pos != m_end)
104  update_node();
105  }
106 
107  iterator_updater(
108  const positions_iterator_type& positions_pos, const sizes_iterator_type& sizes_pos,
109  const element_blocks_iterator_type& eb_pos, const positions_iterator_type& positions_end,
110  const sizes_iterator_type& sizes_end, const element_blocks_iterator_type& eb_end, const parent_type* parent,
111  size_type block_index)
112  : iterator_updater({positions_pos, sizes_pos, eb_pos}, {positions_end, sizes_end, eb_end}, parent, block_index)
113  {}
114 
115  iterator_updater(const iterator_updater& other)
116  : m_cur_node(other.m_cur_node), m_pos(other.m_pos), m_end(other.m_end)
117  {}
118 
119  void update_node()
120  {
121 #ifdef MDDS_MULTI_TYPE_VECTOR_DEBUG
122  if (m_pos == m_end)
123  throw general_error("Current node position should never equal the end position during node update.");
124 #endif
125 
126  m_cur_node.position = *m_pos.position_iterator;
127  m_cur_node.size = *m_pos.size_iterator;
128  m_cur_node.data = *m_pos.element_block_iterator;
129 
130  if (m_cur_node.data)
131  m_cur_node.type = mdds::mtv::get_block_type(*m_cur_node.data);
132  else
133  m_cur_node.type = mdds::mtv::element_type_empty;
134  }
135 
136  node* inc()
137  {
138  m_pos.inc();
139  if (m_pos == m_end)
140  return nullptr;
141 
142  update_node();
143  return &m_cur_node;
144  }
145 
146  node* dec()
147  {
148  m_pos.dec();
149  update_node();
150  return &m_cur_node;
151  }
152 
153  void _print_state(std::ostream& os) const
154  {
155  auto prev_flags = os.flags();
156  os << "parent=" << std::hex << m_cur_node.__private_data.parent
157  << "; block-index=" << m_cur_node.__private_data.block_index << "; position=" << m_cur_node.position
158  << "; size=" << m_cur_node.size << "; type=" << m_cur_node.type << "; data=" << m_cur_node.data;
159  os.flags(prev_flags);
160  }
161 
162 public:
163  bool operator==(const iterator_updater& other) const
164  {
165  if (m_pos != m_end && other.m_pos != other.m_end)
166  {
167  // TODO: Set hard-coded values to the current node for the end
168  // position nodes to remove this if block.
169  if (m_cur_node != other.m_cur_node)
170  return false;
171  }
172  return m_pos == other.m_pos && m_end == other.m_end;
173  }
174 
175  bool operator!=(const iterator_updater& other) const
176  {
177  return !operator==(other);
178  }
179 
180  iterator_updater& operator=(const iterator_updater& other)
181  {
182  m_cur_node = other.m_cur_node;
183  m_pos = other.m_pos;
184  m_end = other.m_end;
185  return *this;
186  }
187 
188  void swap(iterator_updater& other)
189  {
190  m_cur_node.swap(other.m_cur_node);
191  std::swap(m_pos, other.m_pos);
192  std::swap(m_end, other.m_end);
193  }
194 
195  const node& get_node() const
196  {
197  return m_cur_node;
198  }
199  const grouped_iterator_type& get_pos() const
200  {
201  return m_pos;
202  }
203  const grouped_iterator_type& get_end() const
204  {
205  return m_end;
206  }
207 };
208 
209 template<typename Traits>
210 class iterator_base : public iterator_updater<Traits>
211 {
212  using parent_type = typename Traits::parent;
213  using node_update_func = typename Traits::private_data_update;
215 
216  using grouped_iterator_type = typename updater::grouped_iterator_type;
217  using size_type = typename updater::size_type;
218 
219  using updater::dec;
220  using updater::inc;
221  using updater::m_cur_node;
222 
223 public:
224  using updater::get_end;
225  using updater::get_pos;
226 
227  // iterator traits
228  using value_type = typename updater::node;
229  using pointer = value_type*;
230  using reference = value_type&;
231  using difference_type = ptrdiff_t;
232  using iterator_category = std::bidirectional_iterator_tag;
233 
234 public:
235  iterator_base()
236  {}
238  const grouped_iterator_type& pos, const grouped_iterator_type& end, const parent_type* parent,
239  size_type block_index)
240  : updater(pos, end, parent, block_index)
241  {}
242 
243  value_type& operator*()
244  {
245  return m_cur_node;
246  }
247 
248  const value_type& operator*() const
249  {
250  return m_cur_node;
251  }
252 
253  value_type* operator->()
254  {
255  return &m_cur_node;
256  }
257 
258  const value_type* operator->() const
259  {
260  return &m_cur_node;
261  }
262 
263  iterator_base& operator++()
264  {
265  node_update_func::inc(m_cur_node);
266  inc();
267  return *this;
268  }
269 
270  iterator_base& operator--()
271  {
272  dec();
273  node_update_func::dec(m_cur_node);
274  return *this;
275  }
276 
277  void _print_state(std::ostream& os) const
278  {
279  os << "{iterator: ";
280  updater::_print_state(os);
281  os << "}";
282  }
283 };
284 
285 template<typename Traits, typename NonConstItrBase>
286 class const_iterator_base : public iterator_updater<Traits>
287 {
288  using parent_type = typename Traits::parent;
289  using node_update_func = typename Traits::private_data_update;
291 
292  using grouped_iterator_type = typename updater::grouped_iterator_type;
293  using size_type = typename updater::size_type;
294 
295  using updater::dec;
296  using updater::inc;
297  using updater::m_cur_node;
298 
299 public:
300  using updater::get_end;
301  using updater::get_pos;
302 
303  using iterator_base = NonConstItrBase;
304 
305  // iterator traits
306  using value_type = typename updater::node;
307  using pointer = value_type*;
308  using reference = value_type&;
309  using difference_type = ptrdiff_t;
310  using iterator_category = std::bidirectional_iterator_tag;
311 
312 public:
314  {}
316  const grouped_iterator_type& pos, const grouped_iterator_type& end, const parent_type* parent,
317  size_type block_index)
318  : updater(pos, end, parent, block_index)
319  {}
320 
324  const_iterator_base(const iterator_base& other)
325  : updater(
326  other.get_pos().position_iterator, other.get_pos().size_iterator, other.get_pos().element_block_iterator,
327  other.get_end().position_iterator, other.get_end().size_iterator, other.get_end().element_block_iterator,
328  other.get_node().__private_data.parent, other.get_node().__private_data.block_index)
329  {}
330 
331  const value_type& operator*() const
332  {
333  return m_cur_node;
334  }
335 
336  const value_type* operator->() const
337  {
338  return &m_cur_node;
339  }
340 
341  const_iterator_base& operator++()
342  {
343  node_update_func::inc(m_cur_node);
344  inc();
345  return *this;
346  }
347 
348  const_iterator_base& operator--()
349  {
350  dec();
351  node_update_func::dec(m_cur_node);
352  return *this;
353  }
354 
355  bool operator==(const const_iterator_base& other) const
356  {
357  return updater::operator==(other);
358  }
359 
360  bool operator!=(const const_iterator_base& other) const
361  {
362  return updater::operator!=(other);
363  }
364 
365  void _print_state(std::ostream& os) const
366  {
367  os << "(const-iterator: ";
368  updater::_print_state(os);
369  os << ")";
370  }
371 };
372 
373 template<typename Traits>
374 std::ostream& operator<<(std::ostream& os, const iterator_base<Traits>& it)
375 {
376  it._print_state(os);
377  return os;
378 }
379 
380 template<typename Traits, typename NonConstItrBase>
381 std::ostream& operator<<(std::ostream& os, const const_iterator_base<Traits, NonConstItrBase>& it)
382 {
383  it._print_state(os);
384  return os;
385 }
386 
387 }}}} // namespace mdds::mtv::soa::detail
388 
389 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Definition: iterator.hpp:210
Definition: cref_wrapper.hpp:12
const_iterator_base(const iterator_base &other)
Definition: iterator.hpp:324
Definition: iterator.hpp:32