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
36namespace mdds { namespace mtv { namespace soa { namespace detail {
37
54template<typename Traits>
56{
57protected:
58 using parent_type = typename Traits::parent;
59 using positions_type = typename Traits::positions_type;
60 using sizes_type = typename Traits::sizes_type;
61 using element_blocks_type = typename Traits::element_blocks_type;
62 using size_type = typename Traits::parent::size_type;
63
65
66 using positions_iterator_type = typename Traits::positions_iterator_type;
67 using sizes_iterator_type = typename Traits::sizes_iterator_type;
68 using element_blocks_iterator_type = typename Traits::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;
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
185public:
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
232template<typename Traits>
233class iterator_base : public iterator_updater<Traits>
234{
235 using parent_type = typename Traits::parent;
236 using node_update_func = typename Traits::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
246public:
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
257public:
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
308template<typename Traits, typename NonConstItrBase>
310{
311 using parent_type = typename Traits::parent;
312 using node_update_func = typename Traits::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
322public:
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
335public:
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
396template<typename Traits>
397std::ostream& operator<<(std::ostream& os, const iterator_base<Traits>& it)
398{
399 it._print_state(os);
400 return os;
401}
402
403template<typename Traits, typename NonConstItrBase>
404std::ostream& operator<<(std::ostream& os, const const_iterator_base<Traits, 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