mdds
Loading...
Searching...
No Matches
soa/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
13namespace mdds { namespace mtv { namespace soa { namespace detail {
14
31template<typename Traits>
32class iterator_updater
33{
34protected:
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
51 struct grouped_iterator_type
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
84 grouped_iterator_type(
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
162public:
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
209template<typename Traits>
210class iterator_base : public iterator_updater<Traits>
211{
212 using parent_type = typename Traits::parent;
213 using node_update_func = typename Traits::private_data_update;
214 using updater = iterator_updater<Traits>;
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
223public:
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
234public:
235 iterator_base()
236 {}
237 iterator_base(
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
285template<typename Traits, typename NonConstItrBase>
286class 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;
290 using updater = iterator_updater<Traits>;
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
299public:
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
312public:
313 const_iterator_base() : updater()
314 {}
315 const_iterator_base(
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
373template<typename Traits>
374std::ostream& operator<<(std::ostream& os, const iterator_base<Traits>& it)
375{
376 it._print_state(os);
377 return os;
378}
379
380template<typename Traits, typename NonConstItrBase>
381std::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 soa/iterator.hpp:287
const_iterator_base(const iterator_base &other)
Definition soa/iterator.hpp:324
Definition soa/iterator.hpp:211
Definition soa/iterator.hpp:33
Definition iterator_node.hpp:19