mdds
trie_map_itr.hpp
1 /*************************************************************************
2  *
3  * Copyright (c) 2016 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_TRIE_MAP_ITR_HPP
29 #define INCLUDED_MDDS_TRIE_MAP_ITR_HPP
30 
31 #include <utility>
32 #include <cassert>
33 #include <iostream>
34 #ifdef MDDS_TRIE_MAP_DEBUG
35 #include <sstream>
36 #endif
37 
38 #include "mdds/global.hpp"
39 
40 namespace mdds { namespace trie { namespace detail {
41 
42 enum class iterator_type
43 {
48  normal,
54  end,
60  empty
61 };
62 
63 enum empty_iterator_type { empty_iterator };
64 
65 template<typename _TrieType>
67 
68 template<typename _TrieType>
70 {
71  typedef _TrieType trie_type;
72  friend trie_type;
74 
75  typedef typename trie_type::node_stack_type node_stack_type;
76 
77  typedef typename trie_type::trie_node trie_node;
78  typedef typename trie_type::key_trait_type key_trait_type;
79  typedef typename key_trait_type::key_type key_type;
80  typedef typename key_trait_type::key_buffer_type key_buffer_type;
81  typedef typename key_trait_type::key_unit_type key_unit_type;
82 
83 public:
84  // iterator traits
85  typedef typename trie_type::key_value_type value_type;
86  typedef value_type* pointer;
87  typedef value_type& reference;
88  typedef std::ptrdiff_t difference_type;
89  typedef std::bidirectional_iterator_tag iterator_category;
90 
91 private:
92  node_stack_type m_node_stack;
93  key_buffer_type m_buffer;
94  value_type m_current_value;
95  iterator_type m_type;
96 
97  static const trie_node* push_child_node_to_stack(
98  node_stack_type& node_stack, key_buffer_type& buf,
99  const typename trie_node::children_type::const_iterator& child_pos)
100  {
101  using ktt = key_trait_type;
102 
103  const trie_node* node = &child_pos->second;
104  ktt::push_back(buf, child_pos->first);
105  node_stack.emplace_back(node, node->children.begin());
106 
107  return node;
108  }
109 
114  static const trie_node* descend_to_previus_leaf_node(
115  node_stack_type& node_stack, key_buffer_type& buf)
116  {
117  using ktt = key_trait_type;
118 
119  const trie_node* cur_node = nullptr;
120 
121  do
122  {
123  // Keep moving down on the right-most child nodes until the
124  // leaf node is reached.
125 
126  auto& si = node_stack.back();
127 
128  --si.child_pos;
129  ktt::push_back(buf, si.child_pos->first);
130  cur_node = &si.child_pos->second;
131  node_stack.emplace_back(cur_node, cur_node->children.end());
132  }
133  while (!cur_node->children.empty());
134 
135  return cur_node;
136  }
137 
138  iterator_base(empty_iterator_type) : m_type(iterator_type::empty) {}
139 public:
140 
141  iterator_base() : m_type(iterator_type::normal) {}
142 
143  iterator_base(node_stack_type&& node_stack, key_buffer_type&& buf, iterator_type type) :
144  m_node_stack(std::move(node_stack)),
145  m_buffer(std::move(buf)),
146  m_current_value(key_trait_type::to_key(m_buffer), m_node_stack.back().node->value),
147  m_type(type)
148  {}
149 
150  bool operator== (const iterator_base& other) const
151  {
152  if (m_type != other.m_type)
153  return false;
154 
155  if (m_type == iterator_type::empty)
156  return true;
157 
158  return m_node_stack.back() == other.m_node_stack.back();
159  }
160 
161  bool operator!= (const iterator_base& other) const
162  {
163  return !operator==(other);
164  }
165 
166  const value_type& operator*()
167  {
168  return m_current_value;
169  }
170 
171  const value_type* operator->()
172  {
173  return &m_current_value;
174  }
175 
176  iterator_base& operator++()
177  {
178  using ktt = key_trait_type;
179 
180  const trie_node* cur_node = m_node_stack.back().node;
181 
182  do
183  {
184  if (cur_node->children.empty())
185  {
186  // Current node is a leaf node. Keep moving up the stack until we
187  // reach a parent node with unvisited children.
188 
189  while (true)
190  {
191  if (m_node_stack.size() == 1)
192  {
193 #ifdef MDDS_TRIE_MAP_DEBUG
194  if (m_type == iterator_type::end)
195  {
196  std::ostringstream os;
197  os << "iterator_base::operator++#" << __LINE__
198  << ": moving past the end position!";
199  throw general_error(os.str());
200  }
201 #endif
202  // We've reached the end position. Bail out.
203  m_type = iterator_type::end;
204  return *this;
205  }
206 
207  // Move up one parent and see if it has an unvisited child node.
208  ktt::pop_back(m_buffer);
209  m_node_stack.pop_back();
210  auto& si = m_node_stack.back();
211  ++si.child_pos;
212 
213  if (si.child_pos != si.node->children.end())
214  {
215  // Move down to this unvisited child node.
216  cur_node = push_child_node_to_stack(m_node_stack, m_buffer, si.child_pos);
217  break;
218  }
219  }
220  }
221  else
222  {
223  // Current node has child nodes. Follow the first child node.
224  auto child_pos = cur_node->children.begin();
225  cur_node = push_child_node_to_stack(m_node_stack, m_buffer, child_pos);
226  }
227  }
228  while (!cur_node->has_value);
229 
230  m_current_value = value_type(ktt::to_key(m_buffer), cur_node->value);
231  return *this;
232  }
233 
234  iterator_base operator++(int)
235  {
236  iterator_base tmp(*this);
237  operator++();
238  return tmp;
239  }
240 
241  iterator_base& operator--()
242  {
243  using ktt = key_trait_type;
244  const trie_node* cur_node = m_node_stack.back().node;
245 
246  if (m_type == iterator_type::end && cur_node->has_value)
247  {
248  assert(m_node_stack.size() == 1);
249  m_type = iterator_type::normal;
250  }
251  else if (m_node_stack.size() == 1)
252  {
253  // This is the end position aka root node. Move down to the
254  // right-most leaf node.
255  auto& si = m_node_stack.back();
256  assert(si.child_pos == cur_node->children.end());
257  cur_node = descend_to_previus_leaf_node(m_node_stack, m_buffer);
258  m_type = iterator_type::normal;
259  }
260  else if (cur_node->children.empty())
261  {
262  // This is a leaf node. Keep going up until it finds a parent
263  // node with unvisited child nodes on the left side, then descend
264  // on that path all the way to its leaf.
265 
266  do
267  {
268  // Go up one node.
269 
270  ktt::pop_back(m_buffer);
271  m_node_stack.pop_back();
272  auto& si = m_node_stack.back();
273  cur_node = si.node;
274 
275  if (si.child_pos != cur_node->children.begin())
276  {
277  // Left and down.
278  cur_node = descend_to_previus_leaf_node(m_node_stack, m_buffer);
279  assert(cur_node->has_value);
280  }
281  }
282  while (!cur_node->has_value);
283  }
284  else
285  {
286  // Non-leaf node with value. Keep going up until either the root
287  // node or another node with value is reached.
288 
289  assert(cur_node->has_value);
290  assert(m_node_stack.back().child_pos == cur_node->children.begin());
291 
292  do
293  {
294  // Go up.
295  ktt::pop_back(m_buffer);
296  m_node_stack.pop_back();
297  auto& si = m_node_stack.back();
298  cur_node = si.node;
299 
300  if (m_node_stack.size() == 1)
301  {
302  // Root node reached. Left and down.
303  cur_node = descend_to_previus_leaf_node(m_node_stack, m_buffer);
304  assert(cur_node->has_value);
305  }
306  }
307  while (!cur_node->has_value);
308  }
309 
310  assert(cur_node->has_value);
311  m_current_value = value_type(ktt::to_key(m_buffer), cur_node->value);
312  return *this;
313  }
314 
315  iterator_base operator--(int)
316  {
317  iterator_base tmp(*this);
318  operator--();
319  return tmp;
320  }
321 };
322 
323 template<typename _TrieType>
324 class search_results
325 {
326  typedef _TrieType trie_type;
327  friend trie_type;
328  typedef typename trie_type::node_stack_type node_stack_type;
329 
330  typedef typename trie_type::trie_node trie_node;
331  typedef typename trie_type::key_trait_type key_trait_type;
332  typedef typename key_trait_type::key_type key_type;
333  typedef typename key_trait_type::key_buffer_type key_buffer_type;
334  typedef typename key_trait_type::key_unit_type key_unit_type;
335 
336  const trie_node* m_node;
337  key_buffer_type m_buffer;
338  node_stack_type m_node_stack;
339 
340  search_results(const trie_node* node, key_buffer_type&& buf) :
341  m_node(node), m_buffer(buf) {}
342 
343 public:
344  typedef iterator_base<trie_type> const_iterator;
345 
346  const_iterator begin() const
347  {
348  if (!m_node)
349  // empty results.
350  return const_iterator(empty_iterator);
351 
352  // Push the root node.
353  key_buffer_type buf(m_buffer);
354  node_stack_type node_stack;
355  node_stack.emplace_back(m_node, m_node->children.begin());
356 
357  while (!node_stack.back().node->has_value)
358  {
359  // There should always be at least one value node along the
360  // left-most branch.
361 
362  auto it = node_stack.back().child_pos;
363  const_iterator::push_child_node_to_stack(node_stack, buf, it);
364  }
365 
366  return const_iterator(
367  std::move(node_stack), std::move(buf), iterator_type::normal);
368  }
369 
370  const_iterator end() const
371  {
372  if (!m_node)
373  // empty results.
374  return const_iterator(empty_iterator);
375 
376  node_stack_type node_stack;
377  node_stack.emplace_back(m_node, m_node->children.end());
378  return const_iterator(
379  std::move(node_stack), key_buffer_type(m_buffer), iterator_type::end);
380  }
381 };
382 
383 template<typename _TrieType>
385 
386 template<typename _TrieType>
388 {
389  typedef _TrieType trie_type;
390  friend trie_type;
392 
393  typedef typename trie_type::stack_item stack_item;
394  typedef typename trie_type::node_stack_type node_stack_type;
395 
396  typedef typename trie_type::key_trait_type key_trait_type;
397  typedef typename key_trait_type::key_type key_type;
398  typedef typename key_trait_type::key_buffer_type key_buffer_type;
399  typedef typename key_trait_type::key_unit_type key_unit_type;
400 
401 public:
402  // iterator traits
403  typedef typename trie_type::key_value_type value_type;
404  typedef value_type* pointer;
405  typedef value_type& reference;
406  typedef std::ptrdiff_t difference_type;
407  typedef std::bidirectional_iterator_tag iterator_category;
408 
409 private:
410  node_stack_type m_node_stack;
411  key_buffer_type m_buffer;
412  value_type m_current_value;
413  iterator_type m_type;
414 
419  static void push_child_node_to_stack(
420  node_stack_type& node_stack, key_buffer_type& buf, const uintptr_t* child_pos)
421  {
422  using ktt = key_trait_type;
423 
424  const uintptr_t* node_pos = node_stack.back().node_pos;
425 
426  key_unit_type c = static_cast<key_unit_type>(*child_pos);
427  ktt::push_back(buf, c);
428  ++child_pos;
429  size_t offset = static_cast<size_t>(*child_pos);
430  node_pos -= offset; // Jump to the head of the child node.
431  const uintptr_t* p = node_pos;
432  ++p;
433  size_t index_size = *p;
434  ++p;
435  child_pos = p;
436  const uintptr_t* child_end = child_pos + index_size;
437 
438  // Push it onto the stack.
439  node_stack.emplace_back(node_pos, child_pos, child_end);
440  }
441 
442  static const void descend_to_previus_leaf_node(
443  node_stack_type& node_stack, key_buffer_type& buf)
444  {
445  using ktt = key_trait_type;
446 
447  const uintptr_t* node_pos = nullptr;
448  size_t index_size = 0;
449 
450  do
451  {
452  // Keep moving down on the right-most child nodes until the
453  // leaf node is reached.
454 
455  stack_item* si = &node_stack.back();
456  node_pos = si->node_pos;
457  --si->child_pos;
458  size_t offset = *si->child_pos;
459  --si->child_pos;
460  key_unit_type c = *si->child_pos;
461  node_pos -= offset; // Jump to the head of the child node.
462  ktt::push_back(buf, c);
463 
464  const uintptr_t* p = node_pos;
465  ++p;
466  index_size = *p;
467  ++p;
468  const uintptr_t* child_pos = p;
469  const uintptr_t* child_end = child_pos + index_size;
470  node_stack.emplace_back(node_pos, child_end, child_end);
471  }
472  while (index_size);
473  }
474 
475  packed_iterator_base(empty_iterator_type) : m_type(iterator_type::empty) {}
476 
477 public:
478  packed_iterator_base() : m_type(iterator_type::normal) {}
479 
480  packed_iterator_base(node_stack_type&& node_stack, key_buffer_type&& buf, const typename trie_type::value_type& v) :
481  m_node_stack(std::move(node_stack)),
482  m_buffer(std::move(buf)),
483  m_current_value(key_trait_type::to_key(m_buffer), v),
484  m_type(iterator_type::normal) {}
485 
486  packed_iterator_base(node_stack_type&& node_stack, key_buffer_type&& buf) :
487  m_node_stack(std::move(node_stack)),
488  m_buffer(std::move(buf)),
489  m_type(iterator_type::end) {}
490 
491  bool operator== (const packed_iterator_base& other) const
492  {
493  if (m_type != other.m_type)
494  return false;
495 
496  if (m_type == iterator_type::empty)
497  return true;
498 
499  return m_node_stack.back() == other.m_node_stack.back();
500  }
501 
502  bool operator!= (const packed_iterator_base& other) const
503  {
504  return !operator==(other);
505  }
506 
507  const value_type& operator*()
508  {
509  return m_current_value;
510  }
511 
512  const value_type* operator->()
513  {
514  return &m_current_value;
515  }
516 
517  packed_iterator_base& operator++()
518  {
519  using ktt = key_trait_type;
520 
521  stack_item* si = &m_node_stack.back();
522  const typename trie_type::value_type* pv = nullptr;
523  size_t index_size = *(si->node_pos+1);
524 
525  do
526  {
527  if (!index_size)
528  {
529  // Current node is a leaf node. Keep moving up the stack until we
530  // reach a parent node with unvisited children.
531 
532  while (true)
533  {
534  if (m_node_stack.size() == 1)
535  {
536 #ifdef MDDS_TRIE_MAP_DEBUG
537  if (m_type == iterator_type::end)
538  {
539  std::ostringstream os;
540  os << "packed_iterator_base::operator++#"
541  << __LINE__ << ": moving past the end position!";
542  throw general_error(os.str());
543  }
544 #endif
545  // We've reached the end position. Bail out.
546  m_type = iterator_type::end;
547  return *this;
548  }
549 
550  // Move up one parent and see if it has an unvisited child node.
551  ktt::pop_back(m_buffer);
552  m_node_stack.pop_back();
553  si = &m_node_stack.back();
554  std::advance(si->child_pos, 2);
555 
556  if (si->child_pos != si->child_end)
557  {
558  // Move down to this unvisited child node.
559  push_child_node_to_stack(m_node_stack, m_buffer, si->child_pos);
560  break;
561  }
562  }
563  }
564  else
565  {
566  // Current node has child nodes. Follow the first child node.
567  push_child_node_to_stack(m_node_stack, m_buffer, si->child_pos);
568  }
569 
570  si = &m_node_stack.back();
571  pv = reinterpret_cast<const typename trie_type::value_type*>(*si->node_pos);
572  index_size = *(si->node_pos+1);
573  }
574  while (!pv);
575 
576  assert(pv);
577  m_current_value = value_type(ktt::to_key(m_buffer), *pv);
578 
579  return *this;
580  }
581 
582  packed_iterator_base operator++(int)
583  {
584  packed_iterator_base tmp(*this);
585  operator++();
586  return tmp;
587  }
588 
589  packed_iterator_base& operator--()
590  {
591  using ktt = key_trait_type;
592 
593  stack_item* si = &m_node_stack.back();
594  const typename trie_type::value_type* pv =
595  reinterpret_cast<const typename trie_type::value_type*>(*si->node_pos);
596  size_t index_size = *(si->node_pos+1); // index size for child nodes.
597 
598  if (m_type == iterator_type::end && pv)
599  {
600  assert(m_node_stack.size() == 1);
601  m_type = iterator_type::normal;
602  }
603  else if (m_node_stack.size() == 1)
604  {
605  // This is the end position aka root node. Move down to the
606  // right-most leaf node.
607  assert(si->child_pos == si->child_end);
608  descend_to_previus_leaf_node(m_node_stack, m_buffer);
609  si = &m_node_stack.back();
610  pv = reinterpret_cast<const typename trie_type::value_type*>(*si->node_pos);
611  m_type = iterator_type::normal;
612  }
613  else if (!index_size)
614  {
615  // This is a leaf node. Keep going up until it finds a parent
616  // node with unvisited child nodes on the left side, then descend
617  // on that path all the way to its leaf.
618 
619  do
620  {
621  // Go up one node.
622 
623  ktt::pop_back(m_buffer);
624  m_node_stack.pop_back();
625  si = &m_node_stack.back();
626  const uintptr_t* p = si->node_pos;
627  pv = reinterpret_cast<const typename trie_type::value_type*>(*p);
628  ++p;
629  index_size = *p;
630  ++p;
631  const uintptr_t* first_child = p;
632 
633  if (si->child_pos != first_child)
634  {
635  // Left and down.
636  descend_to_previus_leaf_node(m_node_stack, m_buffer);
637  si = &m_node_stack.back();
638  p = si->node_pos;
639  pv = reinterpret_cast<const typename trie_type::value_type*>(*p);
640  assert(pv);
641  }
642  }
643  while (!pv);
644  }
645  else
646  {
647  // Non-leaf node with value. Keep going up until either the root
648  // node or another node with value is reached.
649 
650  assert(*si->node_pos); // this node should have a value.
651  assert(si->child_pos == (si->node_pos+2));
652 
653  do
654  {
655  // Go up.
656  ktt::pop_back(m_buffer);
657  m_node_stack.pop_back();
658  si = &m_node_stack.back();
659  pv = reinterpret_cast<const typename trie_type::value_type*>(*si->node_pos);
660 
661  if (m_node_stack.size() == 1)
662  {
663  // Root node reached.
664  descend_to_previus_leaf_node(m_node_stack, m_buffer);
665  si = &m_node_stack.back();
666  pv = reinterpret_cast<const typename trie_type::value_type*>(*si->node_pos);
667  assert(pv);
668  }
669  }
670  while (!pv);
671  }
672 
673  assert(pv);
674  m_current_value = value_type(ktt::to_key(m_buffer), *pv);
675 
676  return *this;
677  }
678 
679  packed_iterator_base operator--(int)
680  {
681  packed_iterator_base tmp(*this);
682  operator--();
683  return tmp;
684  }
685 };
686 
687 template<typename _TrieType>
689 {
690  typedef _TrieType trie_type;
691  friend trie_type;
692  typedef typename trie_type::node_stack_type node_stack_type;
693 
694  typedef typename trie_type::key_trait_type key_trait_type;
695  typedef typename key_trait_type::key_type key_type;
696  typedef typename key_trait_type::key_buffer_type key_buffer_type;
697  typedef typename key_trait_type::key_unit_type key_unit_type;
698 
699  const uintptr_t* m_node;
700  key_buffer_type m_buffer;
701 
702  packed_search_results(const uintptr_t* node, key_buffer_type&& buf) :
703  m_node(node), m_buffer(std::move(buf)) {}
704 
705  node_stack_type get_root_node() const
706  {
707  const uintptr_t* p = m_node;
708  ++p;
709  size_t index_size = *p;
710  ++p;
711  const uintptr_t* child_pos = p;
712  const uintptr_t* child_end = child_pos + index_size;
713 
714  // Push this child node onto the stack.
715  node_stack_type node_stack;
716  node_stack.emplace_back(m_node, child_pos, child_end);
717  return node_stack;
718  }
719 
720  void swap(packed_search_results& other)
721  {
722  std::swap(m_node, other.m_node);
723  std::swap(m_buffer, other.m_buffer);
724  }
725 
726 public:
727  typedef packed_iterator_base<trie_type> const_iterator;
728 
729  packed_search_results() : m_node(nullptr) {}
730 
732  m_node(other.m_node), m_buffer(other.m_buffer) {}
733 
735  m_node(other.m_node), m_buffer(std::move(other.m_buffer))
736  {
737  other.m_node = nullptr;
738  }
739 
741  {
742  packed_search_results tmp(std::move(other));
743  swap(tmp);
744  return *this;
745  }
746 
747  const_iterator begin() const
748  {
749  if (!m_node)
750  // empty results.
751  return const_iterator(empty_iterator);
752 
753  // Push the root node.
754  key_buffer_type buf(m_buffer);
755  node_stack_type node_stack = get_root_node();
756 
757  while (!node_stack.back().has_value())
758  {
759  // There should always be at least one value node along the
760  // left-most branch.
761 
762  const_iterator::push_child_node_to_stack(node_stack, buf, node_stack.back().child_pos);
763  }
764 
765  return const_iterator(
766  std::move(node_stack), std::move(buf), *node_stack.back().get_value());
767  }
768 
769  const_iterator end() const
770  {
771  if (!m_node)
772  // empty results.
773  return const_iterator(empty_iterator);
774 
775  node_stack_type node_stack = get_root_node();
776  auto& si = node_stack.back();
777  si.child_pos = si.child_end;
778  return const_iterator(std::move(node_stack), key_buffer_type(m_buffer));
779  }
780 };
781 
782 }}}
783 
784 #endif
Definition: trie_map_itr.hpp:387
Definition: trie_map_itr.hpp:69
Definition: trie_map_itr.hpp:66
Definition: global.hpp:58
Definition: flat_segment_tree.hpp:46
Definition: trie_map_itr.hpp:384