mdds
multi_type_vector_itr.hpp
1 /*************************************************************************
2  *
3  * Copyright (c) 2012-2018 Kohei Yoshida
4  *
5  * Permission is hereby granted, free of charge, to any person
6  * obtaining a copy of this software and associated documentation
7  * files (the "Software"), to deal in the Software without
8  * restriction, including without limitation the rights to use,
9  * copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following
12  * conditions:
13  *
14  * The above copyright notice and this permission notice shall be
15  * included in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
19  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24  * OTHER DEALINGS IN THE SOFTWARE.
25  *
26  ************************************************************************/
27 
28 #ifndef INCLUDED_MDDS_MULTI_TYPE_VECTOR_ITR_HPP
29 #define INCLUDED_MDDS_MULTI_TYPE_VECTOR_ITR_HPP
30 
31 #include "multi_type_vector_types.hpp"
32 
33 #include <cstddef>
34 
35 namespace mdds { namespace detail { namespace mtv {
36 
43 template<typename _SizeT, typename _ElemBlkT>
44 struct iterator_value_node
45 {
46  typedef _SizeT size_type;
47  typedef _ElemBlkT element_block_type;
48 
49  mdds::mtv::element_t type;
50  size_type position;
51  size_type size;
52  element_block_type* data;
53 
54  iterator_value_node(size_type block_index) :
55  type(mdds::mtv::element_type_empty), position(0), size(0), data(nullptr), __private_data(block_index) {}
56 
57  void swap(iterator_value_node& other)
58  {
59  std::swap(type, other.type);
60  std::swap(position, other.position);
61  std::swap(size, other.size);
62  std::swap(data, other.data);
63 
64  __private_data.swap(other.__private_data);
65  }
66 
67  struct private_data
68  {
69  size_type block_index;
70 
71  private_data() : block_index(0) {}
72  private_data(size_type _block_index) :
73  block_index(_block_index) {}
74 
75  void swap(private_data& other)
76  {
77  std::swap(block_index, other.block_index);
78  }
79  };
80  private_data __private_data;
81 
82  bool operator== (const iterator_value_node& other) const
83  {
84  return type == other.type && position == other.position && size == other.size && data == other.data &&
85  __private_data.block_index == other.__private_data.block_index;
86  }
87 
88  bool operator!= (const iterator_value_node& other) const
89  {
90  return !operator== (other);
91  }
92 };
93 
94 template<typename _NodeT>
95 struct private_data_no_update
96 {
97  typedef _NodeT node_type;
98 
99  static void inc(node_type&) {}
100  static void dec(node_type&) {}
101 };
102 
103 template<typename _NodeT>
104 struct private_data_forward_update
105 {
106  typedef _NodeT node_type;
107 
108  static void inc(node_type& nd)
109  {
110  ++nd.__private_data.block_index;
111  }
112 
113  static void dec(node_type& nd)
114  {
115  --nd.__private_data.block_index;
116  }
117 };
118 
124 template<typename _Trait>
125 class iterator_common_base
126 {
127 protected:
128  typedef typename _Trait::parent parent_type;
129  typedef typename _Trait::blocks blocks_type;
130  typedef typename _Trait::base_iterator base_iterator_type;
131 
132  typedef typename parent_type::size_type size_type;
133  typedef iterator_value_node<size_type, typename parent_type::element_block_type> node;
134 
135  iterator_common_base() : m_cur_node(0) {}
136 
137  iterator_common_base(
138  const base_iterator_type& pos, const base_iterator_type& end, size_type block_index) :
139  m_cur_node(block_index),
140  m_pos(pos),
141  m_end(end)
142  {
143  if (m_pos != m_end)
144  update_node();
145  }
146 
147  iterator_common_base(const iterator_common_base& other) :
148  m_cur_node(other.m_cur_node),
149  m_pos(other.m_pos),
150  m_end(other.m_end)
151  {
152  }
153 
154  void update_node()
155  {
156 #ifdef MDDS_MULTI_TYPE_VECTOR_DEBUG
157  if (m_pos == m_end)
158  throw general_error("Current node position should never equal the end position during node update.");
159 #endif
160  // blocks_type::value_type is a pointer to multi_type_vector::block.
161  const typename blocks_type::value_type& blk = *m_pos;
162  if (blk.mp_data)
163  m_cur_node.type = mdds::mtv::get_block_type(*blk.mp_data);
164  else
165  m_cur_node.type = mdds::mtv::element_type_empty;
166 
167  m_cur_node.position = blk.m_position;
168  m_cur_node.size = blk.m_size;
169  m_cur_node.data = blk.mp_data;
170  }
171 
172  node* inc()
173  {
174  ++m_pos;
175  if (m_pos == m_end)
176  return nullptr;
177 
178  update_node();
179  return &m_cur_node;
180  }
181 
182  node* dec()
183  {
184  --m_pos;
185  update_node();
186  return &m_cur_node;
187  }
188 
189  node m_cur_node;
190  base_iterator_type m_pos;
191  base_iterator_type m_end;
192 
193 public:
194  bool operator== (const iterator_common_base& other) const
195  {
196  if (m_pos != m_end && other.m_pos != other.m_end)
197  {
198  // TODO: Set hard-coded values to the current node for the end
199  // position nodes to remove this if block.
200  if (m_cur_node != other.m_cur_node)
201  return false;
202  }
203  return m_pos == other.m_pos && m_end == other.m_end;
204  }
205 
206  bool operator!= (const iterator_common_base& other) const
207  {
208  return !operator==(other);
209  }
210 
211  iterator_common_base& operator= (const iterator_common_base& other)
212  {
213  m_cur_node = other.m_cur_node;
214  m_pos = other.m_pos;
215  m_end = other.m_end;
216  return *this;
217  }
218 
219  void swap(iterator_common_base& other)
220  {
221  m_cur_node.swap(other.m_cur_node);
222  std::swap(m_pos, other.m_pos);
223  std::swap(m_end, other.m_end);
224  }
225 
226  const node& get_node() const { return m_cur_node; }
227  const base_iterator_type& get_pos() const { return m_pos; }
228  const base_iterator_type& get_end() const { return m_end; }
229 };
230 
231 template<typename _Trait, typename _NodeUpdateFunc>
232 class iterator_base : public iterator_common_base<_Trait>
233 {
234  typedef _Trait trait;
235  typedef _NodeUpdateFunc node_update_func;
236  typedef iterator_common_base<trait> common_base;
237 
238  typedef typename trait::base_iterator base_iterator_type;
239  typedef typename common_base::size_type size_type;
240 
241  using common_base::inc;
242  using common_base::dec;
243  using common_base::m_cur_node;
244  using common_base::m_pos;
245  using common_base::m_end;
246 
247 public:
248 
249  using common_base::get_pos;
250  using common_base::get_end;
251 
252  // iterator traits
253  typedef typename common_base::node value_type;
254  typedef value_type* pointer;
255  typedef value_type& reference;
256  typedef ptrdiff_t difference_type;
257  typedef std::bidirectional_iterator_tag iterator_category;
258 
259 public:
260  iterator_base() {}
261  iterator_base(
262  const base_iterator_type& pos, const base_iterator_type& end, size_type block_index) :
263  common_base(pos, end, block_index) {}
264 
265  value_type& operator*()
266  {
267  return m_cur_node;
268  }
269 
270  const value_type& operator*() const
271  {
272  return m_cur_node;
273  }
274 
275  value_type* operator->()
276  {
277  return &m_cur_node;
278  }
279 
280  const value_type* operator->() const
281  {
282  return &m_cur_node;
283  }
284 
285  iterator_base& operator++()
286  {
287  node_update_func::inc(m_cur_node);
288  inc();
289  return *this;
290  }
291 
292  iterator_base& operator--()
293  {
294  dec();
295  node_update_func::dec(m_cur_node);
296  return *this;
297  }
298 };
299 
300 template<typename _Trait, typename _NodeUpdateFunc, typename _NonConstItrBase>
301 class const_iterator_base : public iterator_common_base<_Trait>
302 {
303  typedef _Trait trait;
304  typedef _NodeUpdateFunc node_update_func;
306 
307  typedef typename trait::base_iterator base_iterator_type;
308  typedef typename common_base::size_type size_type;
309 
310  using common_base::inc;
311  using common_base::dec;
312  using common_base::m_cur_node;
313 
314 public:
315 
316  using common_base::get_pos;
317  using common_base::get_end;
318 
319  typedef _NonConstItrBase iterator_base;
320 
321  // iterator traits
322  typedef typename common_base::node value_type;
323  typedef value_type* pointer;
324  typedef value_type& reference;
325  typedef ptrdiff_t difference_type;
326  typedef std::bidirectional_iterator_tag iterator_category;
327 
328 public:
331  const base_iterator_type& pos, const base_iterator_type& end, size_type block_index) :
332  common_base(pos, end, block_index) {}
333 
337  const_iterator_base(const iterator_base& other) :
338  common_base(
339  other.get_pos(),
340  other.get_end(),
341  other.get_node().__private_data.block_index) {}
342 
343  const value_type& operator*() const
344  {
345  return m_cur_node;
346  }
347 
348  const value_type* operator->() const
349  {
350  return &m_cur_node;
351  }
352 
353  const_iterator_base& operator++()
354  {
355  node_update_func::inc(m_cur_node);
356  inc();
357  return *this;
358  }
359 
360  const_iterator_base& operator--()
361  {
362  dec();
363  node_update_func::dec(m_cur_node);
364  return *this;
365  }
366 
367  bool operator== (const const_iterator_base& other) const
368  {
369  return iterator_common_base<_Trait>::operator==(other);
370  }
371 
372  bool operator!= (const const_iterator_base& other) const
373  {
375  }
376 };
377 
378 }}}
379 
380 #endif
mdds::detail::mtv::iterator_value_node< size_type, typename parent_type::element_block_type >
mdds::detail::mtv::const_iterator_base
Definition: multi_type_vector_itr.hpp:372
mdds::detail::mtv::iterator_common_base
Definition: multi_type_vector_itr.hpp:196
mdds::detail::mtv::iterator_base
Definition: multi_type_vector_itr.hpp:303