libstdc++
pat_trie_base.hpp
Go to the documentation of this file.
1 // -*- C++ -*-
2 
3 // Copyright (C) 2005-2022 Free Software Foundation, Inc.
4 //
5 // This file is part of the GNU ISO C++ Library. This library is free
6 // software; you can redistribute it and/or modify it under the terms
7 // of the GNU General Public License as published by the Free Software
8 // Foundation; either version 3, or (at your option) any later
9 // version.
10 
11 // This library is distributed in the hope that it will be useful, but
12 // WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // General Public License for more details.
15 
16 // Under Section 7 of GPL version 3, you are granted additional
17 // permissions described in the GCC Runtime Library Exception, version
18 // 3.1, as published by the Free Software Foundation.
19 
20 // You should have received a copy of the GNU General Public License and
21 // a copy of the GCC Runtime Library Exception along with this program;
22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 // <http://www.gnu.org/licenses/>.
24 
25 // Copyright (C) 2004 Ami Tavory and Vladimir Dreizin, IBM-HRL.
26 
27 // Permission to use, copy, modify, sell, and distribute this software
28 // is hereby granted without fee, provided that the above copyright
29 // notice appears in all copies, and that both that copyright notice
30 // and this permission notice appear in supporting documentation. None
31 // of the above authors, nor IBM Haifa Research Laboratories, make any
32 // representation about the suitability of this software for any
33 // purpose. It is provided "as is" without express or implied
34 // warranty.
35 
36 /**
37  * @file pat_trie_/pat_trie_base.hpp
38  * Contains the base class for a patricia tree.
39  */
40 
41 #ifndef PB_DS_PAT_TRIE_BASE
42 #define PB_DS_PAT_TRIE_BASE
43 
44 #include <debug/debug.h>
45 
46 namespace __gnu_pbds
47 {
48  namespace detail
49  {
50  /// Base type for PATRICIA trees.
52  {
53  /**
54  * @brief Three types of nodes.
55  *
56  * i_node is used by _Inode, leaf_node by _Leaf, and head_node by _Head.
57  */
58  enum node_type
59  {
60  i_node,
61  leaf_node,
62  head_node
63  };
64 
65  /// Metadata base primary template.
66  template<typename Metadata, typename _Alloc>
67  struct _Metadata
68  {
69  typedef Metadata metadata_type;
70  typedef _Alloc allocator_type;
71  typedef typename detail::rebind_traits<_Alloc, Metadata>::const_reference
72  const_reference;
73 
74  const_reference
75  get_metadata() const
76  { return m_metadata; }
77 
78  metadata_type m_metadata;
79  };
80 
81  /// Specialization for null metadata.
82  template<typename _Alloc>
83  struct _Metadata<null_type, _Alloc>
84  {
85  typedef null_type metadata_type;
86  typedef _Alloc allocator_type;
87  };
88 
89 
90  /// Node base.
91  template<typename _ATraits, typename Metadata>
92  struct _Node_base
93  : public Metadata
94  {
95  private:
96  typedef typename Metadata::allocator_type _Alloc;
97 
98  public:
99  typedef _Alloc allocator_type;
100  typedef _ATraits access_traits;
101  typedef typename _ATraits::type_traits type_traits;
103  node_pointer;
104 
105  node_pointer m_p_parent;
106  const node_type m_type;
107 
108  _Node_base(node_type type) : m_type(type)
109  { }
110 
112  a_const_pointer;
113  typedef typename _ATraits::const_iterator a_const_iterator;
114 
115 #ifdef _GLIBCXX_DEBUG
116  typedef std::pair<a_const_iterator, a_const_iterator> node_debug_info;
117 
118  void
119  assert_valid(a_const_pointer p_traits,
120  const char* __file, int __line) const
121  { assert_valid_imp(p_traits, __file, __line); }
122 
123  virtual node_debug_info
124  assert_valid_imp(a_const_pointer, const char*, int) const = 0;
125 #endif
126  };
127 
128 
129  /// Head node for PATRICIA tree.
130  template<typename _ATraits, typename Metadata>
131  struct _Head
132  : public _Node_base<_ATraits, Metadata>
133  {
135  typedef typename base_type::type_traits type_traits;
136  typedef typename base_type::node_pointer node_pointer;
137 
138  node_pointer m_p_min;
139  node_pointer m_p_max;
140 
141  _Head() : base_type(head_node) { }
142 
143 #ifdef _GLIBCXX_DEBUG
144  typedef typename base_type::node_debug_info node_debug_info;
145  typedef typename base_type::a_const_pointer a_const_pointer;
146 
147  virtual node_debug_info
148  assert_valid_imp(a_const_pointer, const char* __file, int __line) const
149  {
150  _GLIBCXX_DEBUG_VERIFY_AT(false,
151  _M_message("Assertion from %1;:%2;")
152  ._M_string(__FILE__)._M_integer(__LINE__),
153  __file, __line);
154  return node_debug_info();
155  }
156 #endif
157  };
158 
159 
160  /// Leaf node for PATRICIA tree.
161  template<typename _ATraits, typename Metadata>
162  struct _Leaf
163  : public _Node_base<_ATraits, Metadata>
164  {
166  typedef typename base_type::type_traits type_traits;
167  typedef typename type_traits::value_type value_type;
168  typedef typename type_traits::reference reference;
169  typedef typename type_traits::const_reference const_reference;
170 
171  private:
172  value_type m_value;
173 
174  _Leaf(const _Leaf&);
175 
176  public:
177  _Leaf(const_reference other)
178  : base_type(leaf_node), m_value(other) { }
179 
180  reference
181  value()
182  { return m_value; }
183 
184  const_reference
185  value() const
186  { return m_value; }
187 
188 #ifdef _GLIBCXX_DEBUG
189  typedef typename base_type::node_debug_info node_debug_info;
190  typedef typename base_type::a_const_pointer a_const_pointer;
191 
192  virtual node_debug_info
193  assert_valid_imp(a_const_pointer p_traits,
194  const char* __file, int __line) const
195  {
196  PB_DS_DEBUG_VERIFY(base_type::m_type == leaf_node);
197  node_debug_info ret;
198  const_reference r_val = value();
199  return std::make_pair(p_traits->begin(p_traits->extract_key(r_val)),
200  p_traits->end(p_traits->extract_key(r_val)));
201  }
202 
203  virtual
204  ~_Leaf() { }
205 #endif
206  };
207 
208 
209  /// Internal node type, PATRICIA tree.
210  template<typename _ATraits, typename Metadata>
211  struct _Inode
212  : public _Node_base<_ATraits, Metadata>
213  {
215  typedef typename base_type::type_traits type_traits;
216  typedef typename base_type::access_traits access_traits;
217  typedef typename type_traits::value_type value_type;
218  typedef typename base_type::allocator_type _Alloc;
219  typedef _Alloc allocator_type;
220  typedef typename _Alloc::size_type size_type;
221 
222  private:
223  typedef typename base_type::a_const_pointer a_const_pointer;
224  typedef typename base_type::a_const_iterator a_const_iterator;
225 
226  typedef typename base_type::node_pointer node_pointer;
228  node_const_pointer;
229 
232  typedef typename __rebind_l::pointer leaf_pointer;
233  typedef typename __rebind_l::const_pointer leaf_const_pointer;
234 
236  typedef typename __rebind_in::pointer inode_pointer;
237  typedef typename __rebind_in::const_pointer inode_const_pointer;
238 
239  inline size_type
240  get_pref_pos(a_const_iterator, a_const_iterator, a_const_pointer) const;
241 
242  public:
244  typedef typename __rebind_np::pointer node_pointer_pointer;
245  typedef typename __rebind_np::reference node_pointer_reference;
246 
247  enum
248  {
249  arr_size = _ATraits::max_size + 1
250  };
251  PB_DS_STATIC_ASSERT(min_arr_size, arr_size >= 2);
252 
253 
254  /// Constant child iterator.
256  {
257  node_pointer_pointer m_p_p_cur;
258  node_pointer_pointer m_p_p_end;
259 
261  typedef typename _Alloc::difference_type difference_type;
262  typedef node_pointer value_type;
263  typedef node_pointer_pointer pointer;
264  typedef node_pointer_reference reference;
265 
266  const_iterator(node_pointer_pointer p_p_cur = 0,
267  node_pointer_pointer p_p_end = 0)
268  : m_p_p_cur(p_p_cur), m_p_p_end(p_p_end)
269  { }
270 
271  bool
272  operator==(const const_iterator& other) const
273  { return m_p_p_cur == other.m_p_p_cur; }
274 
275  bool
276  operator!=(const const_iterator& other) const
277  { return m_p_p_cur != other.m_p_p_cur; }
278 
280  operator++()
281  {
282  do
283  ++m_p_p_cur;
284  while (m_p_p_cur != m_p_p_end && *m_p_p_cur == 0);
285  return *this;
286  }
287 
289  operator++(int)
290  {
291  const_iterator ret_it(*this);
292  operator++();
293  return ret_it;
294  }
295 
296  const node_pointer_pointer
297  operator->() const
298  {
299  _GLIBCXX_DEBUG_ONLY(assert_referencible();)
300  return m_p_p_cur;
301  }
302 
303  node_const_pointer
304  operator*() const
305  {
306  _GLIBCXX_DEBUG_ONLY(assert_referencible();)
307  return *m_p_p_cur;
308  }
309 
310  protected:
311 #ifdef _GLIBCXX_DEBUG
312  void
313  assert_referencible() const
314  { _GLIBCXX_DEBUG_ASSERT(m_p_p_cur != m_p_p_end && *m_p_p_cur != 0); }
315 #endif
316  };
317 
318 
319  /// Child iterator.
320  struct iterator : public const_iterator
321  {
322  public:
324  typedef typename _Alloc::difference_type difference_type;
325  typedef node_pointer value_type;
326  typedef node_pointer_pointer pointer;
327  typedef node_pointer_reference reference;
328 
329  inline
330  iterator(node_pointer_pointer p_p_cur = 0,
331  node_pointer_pointer p_p_end = 0)
332  : const_iterator(p_p_cur, p_p_end) { }
333 
334  bool
335  operator==(const iterator& other) const
336  { return const_iterator::m_p_p_cur == other.m_p_p_cur; }
337 
338  bool
339  operator!=(const iterator& other) const
340  { return const_iterator::m_p_p_cur != other.m_p_p_cur; }
341 
342  iterator&
343  operator++()
344  {
345  const_iterator::operator++();
346  return *this;
347  }
348 
349  iterator
350  operator++(int)
351  {
352  iterator ret_it(*this);
353  operator++();
354  return ret_it;
355  }
356 
357  node_pointer_pointer
358  operator->()
359  {
360  _GLIBCXX_DEBUG_ONLY(const_iterator::assert_referencible();)
361  return const_iterator::m_p_p_cur;
362  }
363 
364  node_pointer
365  operator*()
366  {
367  _GLIBCXX_DEBUG_ONLY(const_iterator::assert_referencible();)
368  return *const_iterator::m_p_p_cur;
369  }
370  };
371 
372 
373  _Inode(size_type, const a_const_iterator);
374 
375  void
376  update_prefixes(a_const_pointer);
377 
379  begin() const;
380 
381  iterator
382  begin();
383 
385  end() const;
386 
387  iterator
388  end();
389 
390  inline node_pointer
391  get_child_node(a_const_iterator, a_const_iterator, a_const_pointer);
392 
393  inline node_const_pointer
394  get_child_node(a_const_iterator, a_const_iterator, a_const_pointer) const;
395 
396  inline iterator
397  get_child_it(a_const_iterator, a_const_iterator, a_const_pointer);
398 
399  inline node_pointer
400  get_lower_bound_child_node(a_const_iterator, a_const_iterator,
401  size_type, a_const_pointer);
402 
403  inline node_pointer
404  add_child(node_pointer, a_const_iterator, a_const_iterator,
405  a_const_pointer);
406 
407  inline node_const_pointer
408  get_join_child(node_const_pointer, a_const_pointer) const;
409 
410  inline node_pointer
411  get_join_child(node_pointer, a_const_pointer);
412 
413  void
414  remove_child(node_pointer);
415 
416  void
417  remove_child(iterator);
418 
419  void
420  replace_child(node_pointer, a_const_iterator, a_const_iterator,
421  a_const_pointer);
422 
423  inline a_const_iterator
424  pref_b_it() const;
425 
426  inline a_const_iterator
427  pref_e_it() const;
428 
429  bool
430  should_be_mine(a_const_iterator, a_const_iterator, size_type,
431  a_const_pointer) const;
432 
433  leaf_pointer
434  leftmost_descendant();
435 
436  leaf_const_pointer
437  leftmost_descendant() const;
438 
439  leaf_pointer
440  rightmost_descendant();
441 
442  leaf_const_pointer
443  rightmost_descendant() const;
444 
445 #ifdef _GLIBCXX_DEBUG
446  typedef typename base_type::node_debug_info node_debug_info;
447 
448  virtual node_debug_info
449  assert_valid_imp(a_const_pointer, const char*, int) const;
450 #endif
451 
452  size_type
453  get_e_ind() const
454  { return m_e_ind; }
455 
456  private:
457  _Inode(const _Inode&);
458 
459  size_type
460  get_begin_pos() const;
461 
462  static __rebind_l s_leaf_alloc;
463  static __rebind_in s_inode_alloc;
464 
465  const size_type m_e_ind;
466  a_const_iterator m_pref_b_it;
467  a_const_iterator m_pref_e_it;
468  node_pointer m_a_p_children[arr_size];
469  };
470 
471 #define PB_DS_CONST_IT_C_DEC \
472  _CIter<Node, Leaf, Head, Inode, Is_Forward_Iterator>
473 
474 #define PB_DS_CONST_ODIR_IT_C_DEC \
475  _CIter<Node, Leaf, Head, Inode, !Is_Forward_Iterator>
476 
477 #define PB_DS_IT_C_DEC \
478  _Iter<Node, Leaf, Head, Inode, Is_Forward_Iterator>
479 
480 #define PB_DS_ODIR_IT_C_DEC \
481  _Iter<Node, Leaf, Head, Inode, !Is_Forward_Iterator>
482 
483 
484  /// Const iterator.
485  template<typename Node, typename Leaf, typename Head, typename Inode,
486  bool Is_Forward_Iterator>
487  class _CIter
488  {
489  public:
490  // These types are all the same for the first four template arguments.
491  typedef typename Node::allocator_type allocator_type;
492  typedef typename Node::type_traits type_traits;
493 
495  typedef typename allocator_type::difference_type difference_type;
496  typedef typename type_traits::value_type value_type;
497  typedef typename type_traits::pointer pointer;
498  typedef typename type_traits::reference reference;
499  typedef typename type_traits::const_pointer const_pointer;
500  typedef typename type_traits::const_reference const_reference;
501 
502  typedef allocator_type _Alloc;
503  typedef typename rebind_traits<_Alloc, Node>::pointer node_pointer;
504  typedef typename rebind_traits<_Alloc, Leaf>::pointer leaf_pointer;
505  typedef typename rebind_traits<_Alloc, Leaf>::const_pointer leaf_const_pointer;
506  typedef typename rebind_traits<_Alloc, Head>::pointer head_pointer;
507 
508  typedef typename rebind_traits<_Alloc, Inode>::pointer inode_pointer;
509  typedef typename Inode::iterator inode_iterator;
510 
511  node_pointer m_p_nd;
512 
513  _CIter(node_pointer p_nd = 0) : m_p_nd(p_nd)
514  { }
515 
516  _CIter(const PB_DS_CONST_ODIR_IT_C_DEC& other)
517  : m_p_nd(other.m_p_nd)
518  { }
519 
520  _CIter&
521  operator=(const _CIter& other)
522  {
523  m_p_nd = other.m_p_nd;
524  return *this;
525  }
526 
527  _CIter&
528  operator=(const PB_DS_CONST_ODIR_IT_C_DEC& other)
529  {
530  m_p_nd = other.m_p_nd;
531  return *this;
532  }
533 
534  const_pointer
535  operator->() const
536  {
537  _GLIBCXX_DEBUG_ASSERT(m_p_nd->m_type == leaf_node);
538  return &static_cast<leaf_pointer>(m_p_nd)->value();
539  }
540 
541  const_reference
542  operator*() const
543  {
544  _GLIBCXX_DEBUG_ASSERT(m_p_nd->m_type == leaf_node);
545  return static_cast<leaf_pointer>(m_p_nd)->value();
546  }
547 
548  bool
549  operator==(const _CIter& other) const
550  { return m_p_nd == other.m_p_nd; }
551 
552  bool
553  operator==(const PB_DS_CONST_ODIR_IT_C_DEC& other) const
554  { return m_p_nd == other.m_p_nd; }
555 
556  bool
557  operator!=(const _CIter& other) const
558  { return m_p_nd != other.m_p_nd; }
559 
560  bool
561  operator!=(const PB_DS_CONST_ODIR_IT_C_DEC& other) const
562  { return m_p_nd != other.m_p_nd; }
563 
564  _CIter&
565  operator++()
566  {
567  inc(integral_constant<int, Is_Forward_Iterator>());
568  return *this;
569  }
570 
571  _CIter
572  operator++(int)
573  {
574  _CIter ret_it(m_p_nd);
575  operator++();
576  return ret_it;
577  }
578 
579  _CIter&
580  operator--()
581  {
582  dec(integral_constant<int, Is_Forward_Iterator>());
583  return *this;
584  }
585 
586  _CIter
587  operator--(int)
588  {
589  _CIter ret_it(m_p_nd);
590  operator--();
591  return ret_it;
592  }
593 
594  protected:
595  void
596  inc(false_type)
597  { dec(true_type()); }
598 
599  void
600  inc(true_type)
601  {
602  if (m_p_nd->m_type == head_node)
603  {
604  m_p_nd = static_cast<head_pointer>(m_p_nd)->m_p_min;
605  return;
606  }
607 
608  node_pointer p_y = m_p_nd->m_p_parent;
609  while (p_y->m_type != head_node && get_larger_sibling(m_p_nd) == 0)
610  {
611  m_p_nd = p_y;
612  p_y = p_y->m_p_parent;
613  }
614 
615  if (p_y->m_type == head_node)
616  {
617  m_p_nd = p_y;
618  return;
619  }
620  m_p_nd = leftmost_descendant(get_larger_sibling(m_p_nd));
621  }
622 
623  void
624  dec(false_type)
625  { inc(true_type()); }
626 
627  void
628  dec(true_type)
629  {
630  if (m_p_nd->m_type == head_node)
631  {
632  m_p_nd = static_cast<head_pointer>(m_p_nd)->m_p_max;
633  return;
634  }
635 
636  node_pointer p_y = m_p_nd->m_p_parent;
637  while (p_y->m_type != head_node && get_smaller_sibling(m_p_nd) == 0)
638  {
639  m_p_nd = p_y;
640  p_y = p_y->m_p_parent;
641  }
642 
643  if (p_y->m_type == head_node)
644  {
645  m_p_nd = p_y;
646  return;
647  }
648  m_p_nd = rightmost_descendant(get_smaller_sibling(m_p_nd));
649  }
650 
651  static node_pointer
652  get_larger_sibling(node_pointer p_nd)
653  {
654  inode_pointer p_parent = static_cast<inode_pointer>(p_nd->m_p_parent);
655 
656  inode_iterator it = p_parent->begin();
657  while (*it != p_nd)
658  ++it;
659 
660  inode_iterator next_it = it;
661  ++next_it;
662  return (next_it == p_parent->end())? 0 : *next_it;
663  }
664 
665  static node_pointer
666  get_smaller_sibling(node_pointer p_nd)
667  {
668  inode_pointer p_parent = static_cast<inode_pointer>(p_nd->m_p_parent);
669 
670  inode_iterator it = p_parent->begin();
671  if (*it == p_nd)
672  return 0;
673 
674  inode_iterator prev_it;
675  do
676  {
677  prev_it = it;
678  ++it;
679  if (*it == p_nd)
680  return *prev_it;
681  }
682  while (true);
683 
684  _GLIBCXX_DEBUG_ASSERT(false);
685  return 0;
686  }
687 
688  static leaf_pointer
689  leftmost_descendant(node_pointer p_nd)
690  {
691  if (p_nd->m_type == leaf_node)
692  return static_cast<leaf_pointer>(p_nd);
693  return static_cast<inode_pointer>(p_nd)->leftmost_descendant();
694  }
695 
696  static leaf_pointer
697  rightmost_descendant(node_pointer p_nd)
698  {
699  if (p_nd->m_type == leaf_node)
700  return static_cast<leaf_pointer>(p_nd);
701  return static_cast<inode_pointer>(p_nd)->rightmost_descendant();
702  }
703  };
704 
705 
706  /// Iterator.
707  template<typename Node, typename Leaf, typename Head, typename Inode,
708  bool Is_Forward_Iterator>
709  class _Iter
710  : public _CIter<Node, Leaf, Head, Inode, Is_Forward_Iterator>
711  {
712  public:
714  base_type;
715  typedef typename base_type::allocator_type allocator_type;
716  typedef typename base_type::type_traits type_traits;
717  typedef typename type_traits::value_type value_type;
718  typedef typename type_traits::pointer pointer;
719  typedef typename type_traits::reference reference;
720 
721  typedef typename base_type::node_pointer node_pointer;
722  typedef typename base_type::leaf_pointer leaf_pointer;
723  typedef typename base_type::leaf_const_pointer leaf_const_pointer;
724  typedef typename base_type::head_pointer head_pointer;
725  typedef typename base_type::inode_pointer inode_pointer;
726 
727  _Iter(node_pointer p_nd = 0)
728  : base_type(p_nd) { }
729 
730  _Iter(const PB_DS_ODIR_IT_C_DEC& other)
731  : base_type(other.m_p_nd) { }
732 
733  _Iter&
734  operator=(const _Iter& other)
735  {
736  base_type::m_p_nd = other.m_p_nd;
737  return *this;
738  }
739 
740  _Iter&
741  operator=(const PB_DS_ODIR_IT_C_DEC& other)
742  {
743  base_type::m_p_nd = other.m_p_nd;
744  return *this;
745  }
746 
747  pointer
748  operator->() const
749  {
750  _GLIBCXX_DEBUG_ASSERT(base_type::m_p_nd->m_type == leaf_node);
751  return &static_cast<leaf_pointer>(base_type::m_p_nd)->value();
752  }
753 
754  reference
755  operator*() const
756  {
757  _GLIBCXX_DEBUG_ASSERT(base_type::m_p_nd->m_type == leaf_node);
758  return static_cast<leaf_pointer>(base_type::m_p_nd)->value();
759  }
760 
761  _Iter&
762  operator++()
763  {
764  base_type::operator++();
765  return *this;
766  }
767 
768  _Iter
769  operator++(int)
770  {
771  _Iter ret(base_type::m_p_nd);
772  operator++();
773  return ret;
774  }
775 
776  _Iter&
777  operator--()
778  {
779  base_type::operator--();
780  return *this;
781  }
782 
783  _Iter
784  operator--(int)
785  {
786  _Iter ret(base_type::m_p_nd);
787  operator--();
788  return ret;
789  }
790  };
791 
792 #undef PB_DS_CONST_ODIR_IT_C_DEC
793 #undef PB_DS_ODIR_IT_C_DEC
794 
795 
796 #define PB_DS_PAT_TRIE_NODE_CONST_ITERATOR_C_DEC \
797  _Node_citer<Node, Leaf, Head, Inode, _CIterator, Iterator, _ATraits, _Alloc>
798 
799 #define PB_DS_PAT_TRIE_NODE_ITERATOR_C_DEC \
800  _Node_iter<Node, Leaf, Head, Inode, _CIterator, Iterator, _ATraits, _Alloc>
801 
802  /// Node const iterator.
803  template<typename Node,
804  typename Leaf,
805  typename Head,
806  typename Inode,
807  typename _CIterator,
808  typename Iterator,
809  typename _Alloc>
811  {
812  protected:
813  typedef typename rebind_traits<_Alloc, Node>::pointer node_pointer;
814 
815  typedef typename rebind_traits<_Alloc, Leaf>::pointer leaf_pointer;
816  typedef typename rebind_traits<_Alloc, Leaf>::const_pointer leaf_const_pointer;
817 
818  typedef typename rebind_traits<_Alloc, Inode>::pointer inode_pointer;
819  typedef typename rebind_traits<_Alloc, Inode>::const_pointer inode_const_pointer;
820 
821  typedef typename Node::a_const_pointer a_const_pointer;
822  typedef typename Node::a_const_iterator a_const_iterator;
823 
824  private:
825  a_const_iterator
826  pref_begin() const
827  {
828  if (m_p_nd->m_type == leaf_node)
829  {
830  leaf_const_pointer lcp = static_cast<leaf_const_pointer>(m_p_nd);
831  return m_p_traits->begin(m_p_traits->extract_key(lcp->value()));
832  }
833  _GLIBCXX_DEBUG_ASSERT(m_p_nd->m_type == i_node);
834  return static_cast<inode_const_pointer>(m_p_nd)->pref_b_it();
835  }
836 
837  a_const_iterator
838  pref_end() const
839  {
840  if (m_p_nd->m_type == leaf_node)
841  {
842  leaf_const_pointer lcp = static_cast<leaf_const_pointer>(m_p_nd);
843  return m_p_traits->end(m_p_traits->extract_key(lcp->value()));
844  }
845  _GLIBCXX_DEBUG_ASSERT(m_p_nd->m_type == i_node);
846  return static_cast<inode_const_pointer>(m_p_nd)->pref_e_it();
847  }
848 
849  public:
851  typedef trivial_iterator_difference_type difference_type;
852  typedef typename _Alloc::size_type size_type;
853 
854  typedef _CIterator value_type;
855  typedef value_type reference;
856  typedef value_type const_reference;
857 
858  /// Metadata type.
859  typedef typename Node::metadata_type metadata_type;
860 
861  /// Const metadata reference type.
862  typedef typename rebind_traits<_Alloc, metadata_type>::const_reference metadata_const_reference;
863 
864  inline
865  _Node_citer(node_pointer p_nd = 0, a_const_pointer p_traits = 0)
866  : m_p_nd(const_cast<node_pointer>(p_nd)), m_p_traits(p_traits)
867  { }
868 
869  /// Subtree valid prefix.
871  valid_prefix() const
872  { return std::make_pair(pref_begin(), pref_end()); }
873 
874  /// Const access; returns the __const iterator* associated with
875  /// the current leaf.
876  const_reference
877  operator*() const
878  {
879  _GLIBCXX_DEBUG_ASSERT(num_children() == 0);
880  return _CIterator(m_p_nd);
881  }
882 
883  /// Metadata access.
885  get_metadata() const
886  { return m_p_nd->get_metadata(); }
887 
888  /// Returns the number of children in the corresponding node.
889  size_type
890  num_children() const
891  {
892  if (m_p_nd->m_type == leaf_node)
893  return 0;
894  _GLIBCXX_DEBUG_ASSERT(m_p_nd->m_type == i_node);
895  inode_pointer inp = static_cast<inode_pointer>(m_p_nd);
896  return std::distance(inp->begin(), inp->end());
897  }
898 
899  /// Returns a __const node __iterator to the corresponding node's
900  /// i-th child.
902  get_child(size_type i) const
903  {
904  _GLIBCXX_DEBUG_ASSERT(m_p_nd->m_type == i_node);
905  inode_pointer inp = static_cast<inode_pointer>(m_p_nd);
906  typename Inode::iterator it = inp->begin();
907  std::advance(it, i);
908  return _Node_citer(*it, m_p_traits);
909  }
910 
911  /// Compares content to a different iterator object.
912  bool
913  operator==(const _Node_citer& other) const
914  { return m_p_nd == other.m_p_nd; }
915 
916  /// Compares content (negatively) to a different iterator object.
917  bool
918  operator!=(const _Node_citer& other) const
919  { return m_p_nd != other.m_p_nd; }
920 
921  node_pointer m_p_nd;
922  a_const_pointer m_p_traits;
923  };
924 
925 
926  /// Node iterator.
927  template<typename Node,
928  typename Leaf,
929  typename Head,
930  typename Inode,
931  typename _CIterator,
932  typename Iterator,
933  typename _Alloc>
935  : public _Node_citer<Node, Leaf, Head, Inode, _CIterator, Iterator, _Alloc>
936  {
937  private:
938  typedef _Node_citer<Node, Leaf, Head, Inode,
939  _CIterator, Iterator, _Alloc> base_type;
940  typedef typename rebind_traits<_Alloc, Node>::pointer node_pointer;
941  typedef typename base_type::inode_pointer inode_pointer;
942  typedef typename base_type::a_const_pointer a_const_pointer;
943  typedef Iterator iterator;
944 
945  public:
946  typedef typename base_type::size_type size_type;
947 
948  typedef Iterator value_type;
949  typedef value_type reference;
950  typedef value_type const_reference;
951 
952  _Node_iter(node_pointer p_nd = 0, a_const_pointer p_traits = 0)
953  : base_type(p_nd, p_traits)
954  { }
955 
956  /// Access; returns the iterator* associated with the current leaf.
957  reference
958  operator*() const
959  {
960  _GLIBCXX_DEBUG_ASSERT(base_type::num_children() == 0);
961  return iterator(base_type::m_p_nd);
962  }
963 
964  /// Returns a node __iterator to the corresponding node's i-th child.
965  _Node_iter
966  get_child(size_type i) const
967  {
968  _GLIBCXX_DEBUG_ASSERT(base_type::m_p_nd->m_type == i_node);
969 
970  typename Inode::iterator it =
971  static_cast<inode_pointer>(base_type::m_p_nd)->begin();
972 
973  std::advance(it, i);
974  return _Node_iter(*it, base_type::m_p_traits);
975  }
976  };
977  };
978 
979 
980 #define PB_DS_CLASS_T_DEC \
981  template<typename _ATraits, typename Metadata>
982 
983 #define PB_DS_CLASS_C_DEC \
984  pat_trie_base::_Inode<_ATraits, Metadata>
985 
986  PB_DS_CLASS_T_DEC
987  typename PB_DS_CLASS_C_DEC::__rebind_l
988  PB_DS_CLASS_C_DEC::s_leaf_alloc;
989 
990  PB_DS_CLASS_T_DEC
991  typename PB_DS_CLASS_C_DEC::__rebind_in
992  PB_DS_CLASS_C_DEC::s_inode_alloc;
993 
994  PB_DS_CLASS_T_DEC
995  inline typename PB_DS_CLASS_C_DEC::size_type
996  PB_DS_CLASS_C_DEC::
997  get_pref_pos(a_const_iterator b_it, a_const_iterator e_it,
998  a_const_pointer p_traits) const
999  {
1000  if (static_cast<std::size_t>(std::distance(b_it, e_it)) <= m_e_ind)
1001  return 0;
1002  std::advance(b_it, m_e_ind);
1003  return 1 + p_traits->e_pos(*b_it);
1004  }
1005 
1006  PB_DS_CLASS_T_DEC
1007  PB_DS_CLASS_C_DEC::
1008  _Inode(size_type len, const a_const_iterator it)
1009  : base_type(i_node), m_e_ind(len), m_pref_b_it(it), m_pref_e_it(it)
1010  {
1011  std::advance(m_pref_e_it, m_e_ind);
1012  std::fill(m_a_p_children, m_a_p_children + arr_size,
1013  static_cast<node_pointer>(0));
1014  }
1015 
1016  PB_DS_CLASS_T_DEC
1017  void
1018  PB_DS_CLASS_C_DEC::
1019  update_prefixes(a_const_pointer p_traits)
1020  {
1021  node_pointer p_first = *begin();
1022  if (p_first->m_type == leaf_node)
1023  {
1024  leaf_const_pointer p = static_cast<leaf_const_pointer>(p_first);
1025  m_pref_b_it = p_traits->begin(access_traits::extract_key(p->value()));
1026  }
1027  else
1028  {
1029  inode_pointer p = static_cast<inode_pointer>(p_first);
1030  _GLIBCXX_DEBUG_ASSERT(p_first->m_type == i_node);
1031  m_pref_b_it = p->pref_b_it();
1032  }
1033  m_pref_e_it = m_pref_b_it;
1034  std::advance(m_pref_e_it, m_e_ind);
1035  }
1036 
1037  PB_DS_CLASS_T_DEC
1038  typename PB_DS_CLASS_C_DEC::const_iterator
1039  PB_DS_CLASS_C_DEC::
1040  begin() const
1041  {
1042  typedef node_pointer_pointer pointer_type;
1043  pointer_type p = const_cast<pointer_type>(m_a_p_children);
1044  return const_iterator(p + get_begin_pos(), p + arr_size);
1045  }
1046 
1047  PB_DS_CLASS_T_DEC
1048  typename PB_DS_CLASS_C_DEC::iterator
1049  PB_DS_CLASS_C_DEC::
1050  begin()
1051  {
1052  return iterator(m_a_p_children + get_begin_pos(),
1053  m_a_p_children + arr_size);
1054  }
1055 
1056  PB_DS_CLASS_T_DEC
1057  typename PB_DS_CLASS_C_DEC::const_iterator
1058  PB_DS_CLASS_C_DEC::
1059  end() const
1060  {
1061  typedef node_pointer_pointer pointer_type;
1062  pointer_type p = const_cast<pointer_type>(m_a_p_children) + arr_size;
1063  return const_iterator(p, p);
1064  }
1065 
1066  PB_DS_CLASS_T_DEC
1067  typename PB_DS_CLASS_C_DEC::iterator
1068  PB_DS_CLASS_C_DEC::
1069  end()
1070  { return iterator(m_a_p_children + arr_size, m_a_p_children + arr_size); }
1071 
1072  PB_DS_CLASS_T_DEC
1073  inline typename PB_DS_CLASS_C_DEC::node_pointer
1074  PB_DS_CLASS_C_DEC::
1075  get_child_node(a_const_iterator b_it, a_const_iterator e_it,
1076  a_const_pointer p_traits)
1077  {
1078  const size_type i = get_pref_pos(b_it, e_it, p_traits);
1079  _GLIBCXX_DEBUG_ASSERT(i < arr_size);
1080  return m_a_p_children[i];
1081  }
1082 
1083  PB_DS_CLASS_T_DEC
1084  inline typename PB_DS_CLASS_C_DEC::iterator
1085  PB_DS_CLASS_C_DEC::
1086  get_child_it(a_const_iterator b_it, a_const_iterator e_it,
1087  a_const_pointer p_traits)
1088  {
1089  const size_type i = get_pref_pos(b_it, e_it, p_traits);
1090  _GLIBCXX_DEBUG_ASSERT(i < arr_size);
1091  _GLIBCXX_DEBUG_ASSERT(m_a_p_children[i] != 0);
1092  return iterator(m_a_p_children + i, m_a_p_children + i);
1093  }
1094 
1095  PB_DS_CLASS_T_DEC
1096  inline typename PB_DS_CLASS_C_DEC::node_const_pointer
1097  PB_DS_CLASS_C_DEC::
1098  get_child_node(a_const_iterator b_it, a_const_iterator e_it,
1099  a_const_pointer p_traits) const
1100  { return const_cast<node_pointer>(get_child_node(b_it, e_it, p_traits)); }
1101 
1102  PB_DS_CLASS_T_DEC
1103  typename PB_DS_CLASS_C_DEC::node_pointer
1104  PB_DS_CLASS_C_DEC::
1105  get_lower_bound_child_node(a_const_iterator b_it, a_const_iterator e_it,
1106  size_type checked_ind,
1107  a_const_pointer p_traits)
1108  {
1109  if (!should_be_mine(b_it, e_it, checked_ind, p_traits))
1110  {
1111  if (p_traits->cmp_prefixes(b_it, e_it, m_pref_b_it,
1112  m_pref_e_it, true))
1113  return leftmost_descendant();
1114  return rightmost_descendant();
1115  }
1116 
1117  size_type i = get_pref_pos(b_it, e_it, p_traits);
1118  _GLIBCXX_DEBUG_ASSERT(i < arr_size);
1119 
1120  if (m_a_p_children[i] != 0)
1121  return m_a_p_children[i];
1122 
1123  while (++i < arr_size)
1124  if (m_a_p_children[i] != 0)
1125  {
1126  const node_type& __nt = m_a_p_children[i]->m_type;
1127  node_pointer ret = m_a_p_children[i];
1128 
1129  if (__nt == leaf_node)
1130  return ret;
1131 
1132  _GLIBCXX_DEBUG_ASSERT(__nt == i_node);
1133  inode_pointer inp = static_cast<inode_pointer>(ret);
1134  return inp->leftmost_descendant();
1135  }
1136 
1137  return rightmost_descendant();
1138  }
1139 
1140  PB_DS_CLASS_T_DEC
1141  inline typename PB_DS_CLASS_C_DEC::node_pointer
1142  PB_DS_CLASS_C_DEC::
1143  add_child(node_pointer p_nd, a_const_iterator b_it, a_const_iterator e_it,
1144  a_const_pointer p_traits)
1145  {
1146  const size_type i = get_pref_pos(b_it, e_it, p_traits);
1147  _GLIBCXX_DEBUG_ASSERT(i < arr_size);
1148  if (m_a_p_children[i] == 0)
1149  {
1150  m_a_p_children[i] = p_nd;
1151  p_nd->m_p_parent = this;
1152  return p_nd;
1153  }
1154  return m_a_p_children[i];
1155  }
1156 
1157  PB_DS_CLASS_T_DEC
1158  typename PB_DS_CLASS_C_DEC::node_const_pointer
1159  PB_DS_CLASS_C_DEC::
1160  get_join_child(node_const_pointer p_nd,
1161  a_const_pointer p_tr) const
1162  {
1163  node_pointer p = const_cast<node_pointer>(p_nd);
1164  return const_cast<inode_pointer>(this)->get_join_child(p, p_tr);
1165  }
1166 
1167  PB_DS_CLASS_T_DEC
1168  typename PB_DS_CLASS_C_DEC::node_pointer
1169  PB_DS_CLASS_C_DEC::
1170  get_join_child(node_pointer p_nd, a_const_pointer p_traits)
1171  {
1172  size_type i;
1173  a_const_iterator b_it;
1174  a_const_iterator e_it;
1175  if (p_nd->m_type == leaf_node)
1176  {
1177  leaf_const_pointer p = static_cast<leaf_const_pointer>(p_nd);
1178 
1179  typedef typename type_traits::key_const_reference kcr;
1180  kcr r_key = access_traits::extract_key(p->value());
1181  b_it = p_traits->begin(r_key);
1182  e_it = p_traits->end(r_key);
1183  }
1184  else
1185  {
1186  b_it = static_cast<inode_pointer>(p_nd)->pref_b_it();
1187  e_it = static_cast<inode_pointer>(p_nd)->pref_e_it();
1188  }
1189  i = get_pref_pos(b_it, e_it, p_traits);
1190  _GLIBCXX_DEBUG_ASSERT(i < arr_size);
1191  return m_a_p_children[i];
1192  }
1193 
1194  PB_DS_CLASS_T_DEC
1195  void
1196  PB_DS_CLASS_C_DEC::
1197  remove_child(node_pointer p_nd)
1198  {
1199  size_type i = 0;
1200  for (; i < arr_size; ++i)
1201  if (m_a_p_children[i] == p_nd)
1202  {
1203  m_a_p_children[i] = 0;
1204  return;
1205  }
1206  _GLIBCXX_DEBUG_ASSERT(i != arr_size);
1207  }
1208 
1209  PB_DS_CLASS_T_DEC
1210  void
1211  PB_DS_CLASS_C_DEC::
1212  remove_child(iterator it)
1213  { *it.m_p_p_cur = 0; }
1214 
1215  PB_DS_CLASS_T_DEC
1216  void
1217  PB_DS_CLASS_C_DEC::
1218  replace_child(node_pointer p_nd, a_const_iterator b_it,
1219  a_const_iterator e_it,
1220  a_const_pointer p_traits)
1221  {
1222  const size_type i = get_pref_pos(b_it, e_it, p_traits);
1223  _GLIBCXX_DEBUG_ASSERT(i < arr_size);
1224  m_a_p_children[i] = p_nd;
1225  p_nd->m_p_parent = this;
1226  }
1227 
1228  PB_DS_CLASS_T_DEC
1229  inline typename PB_DS_CLASS_C_DEC::a_const_iterator
1230  PB_DS_CLASS_C_DEC::
1231  pref_b_it() const
1232  { return m_pref_b_it; }
1233 
1234  PB_DS_CLASS_T_DEC
1235  inline typename PB_DS_CLASS_C_DEC::a_const_iterator
1236  PB_DS_CLASS_C_DEC::
1237  pref_e_it() const
1238  { return m_pref_e_it; }
1239 
1240  PB_DS_CLASS_T_DEC
1241  bool
1242  PB_DS_CLASS_C_DEC::
1243  should_be_mine(a_const_iterator b_it, a_const_iterator e_it,
1244  size_type checked_ind,
1245  a_const_pointer p_traits) const
1246  {
1247  if (m_e_ind == 0)
1248  return true;
1249 
1250  const size_type num_es = std::distance(b_it, e_it);
1251  if (num_es < m_e_ind)
1252  return false;
1253 
1254  a_const_iterator key_b_it = b_it;
1255  std::advance(key_b_it, checked_ind);
1256  a_const_iterator key_e_it = b_it;
1257  std::advance(key_e_it, m_e_ind);
1258 
1259  a_const_iterator value_b_it = m_pref_b_it;
1260  std::advance(value_b_it, checked_ind);
1261  a_const_iterator value_e_it = m_pref_b_it;
1262  std::advance(value_e_it, m_e_ind);
1263 
1264  return p_traits->equal_prefixes(key_b_it, key_e_it, value_b_it,
1265  value_e_it);
1266  }
1267 
1268  PB_DS_CLASS_T_DEC
1269  typename PB_DS_CLASS_C_DEC::leaf_pointer
1270  PB_DS_CLASS_C_DEC::
1271  leftmost_descendant()
1272  {
1273  node_pointer p_pot = *begin();
1274  if (p_pot->m_type == leaf_node)
1275  return (static_cast<leaf_pointer>(p_pot));
1276  _GLIBCXX_DEBUG_ASSERT(p_pot->m_type == i_node);
1277  return static_cast<inode_pointer>(p_pot)->leftmost_descendant();
1278  }
1279 
1280  PB_DS_CLASS_T_DEC
1281  typename PB_DS_CLASS_C_DEC::leaf_const_pointer
1282  PB_DS_CLASS_C_DEC::
1283  leftmost_descendant() const
1284  { return const_cast<inode_pointer>(this)->leftmost_descendant(); }
1285 
1286  PB_DS_CLASS_T_DEC
1287  typename PB_DS_CLASS_C_DEC::leaf_pointer
1288  PB_DS_CLASS_C_DEC::
1289  rightmost_descendant()
1290  {
1291  const size_type num_children = std::distance(begin(), end());
1292  _GLIBCXX_DEBUG_ASSERT(num_children >= 2);
1293 
1294  iterator it = begin();
1295  std::advance(it, num_children - 1);
1296  node_pointer p_pot =* it;
1297  if (p_pot->m_type == leaf_node)
1298  return static_cast<leaf_pointer>(p_pot);
1299  _GLIBCXX_DEBUG_ASSERT(p_pot->m_type == i_node);
1300  return static_cast<inode_pointer>(p_pot)->rightmost_descendant();
1301  }
1302 
1303  PB_DS_CLASS_T_DEC
1304  typename PB_DS_CLASS_C_DEC::leaf_const_pointer
1305  PB_DS_CLASS_C_DEC::
1306  rightmost_descendant() const
1307  { return const_cast<inode_pointer>(this)->rightmost_descendant(); }
1308 
1309  PB_DS_CLASS_T_DEC
1310  typename PB_DS_CLASS_C_DEC::size_type
1311  PB_DS_CLASS_C_DEC::
1312  get_begin_pos() const
1313  {
1314  size_type i = 0;
1315  for (; i < arr_size && m_a_p_children[i] == 0; ++i)
1316  ;
1317  return i;
1318  }
1319 
1320 #ifdef _GLIBCXX_DEBUG
1321  PB_DS_CLASS_T_DEC
1322  typename PB_DS_CLASS_C_DEC::node_debug_info
1323  PB_DS_CLASS_C_DEC::
1324  assert_valid_imp(a_const_pointer p_traits,
1325  const char* __file, int __line) const
1326  {
1327  PB_DS_DEBUG_VERIFY(base_type::m_type == i_node);
1328  PB_DS_DEBUG_VERIFY(static_cast<size_type>(std::distance(pref_b_it(), pref_e_it())) == m_e_ind);
1329  PB_DS_DEBUG_VERIFY(std::distance(begin(), end()) >= 2);
1330 
1331  for (typename _Inode::const_iterator it = begin(); it != end(); ++it)
1332  {
1333  node_const_pointer p_nd = *it;
1334  PB_DS_DEBUG_VERIFY(p_nd->m_p_parent == this);
1335  node_debug_info child_ret = p_nd->assert_valid_imp(p_traits,
1336  __file, __line);
1337 
1338  PB_DS_DEBUG_VERIFY(static_cast<size_type>(std::distance(child_ret.first, child_ret.second)) >= m_e_ind);
1339  PB_DS_DEBUG_VERIFY(should_be_mine(child_ret.first, child_ret.second, 0, p_traits));
1340  PB_DS_DEBUG_VERIFY(get_pref_pos(child_ret.first, child_ret.second, p_traits) == static_cast<size_type>(it.m_p_p_cur - m_a_p_children));
1341  }
1342  return std::make_pair(pref_b_it(), pref_e_it());
1343  }
1344 #endif
1345 
1346 #undef PB_DS_CLASS_T_DEC
1347 #undef PB_DS_CLASS_C_DEC
1348  } // namespace detail
1349 } // namespace __gnu_pbds
1350 
1351 #endif
integral_constant< bool, true > true_type
The type used as a compile-time boolean with true value.
Definition: type_traits:82
void trivial_iterator_difference_type
Prohibit moving trivial iterators.
constexpr iterator_traits< _InputIterator >::difference_type distance(_InputIterator __first, _InputIterator __last)
A generalization of pointer arithmetic.
constexpr void advance(_InputIterator &__i, _Distance __n)
A generalization of pointer arithmetic.
GNU extensions for policy-based data structures for public use.
Struct holding two objects of arbitrary type.
Definition: stl_pair.h:187
Forward iterators support a superset of input iterator operations.
Bidirectional iterators support a superset of forward iterator operations.
A trivial iterator tag. Signifies that the iterators has none of std::iterators's movement abilities.
Represents no type, or absence of type, for template tricks.
Consistent API for accessing allocator-related types.
Base type for PATRICIA trees.
Metadata base primary template.
Internal node type, PATRICIA tree.
std::pair< a_const_iterator, a_const_iterator > valid_prefix() const
Subtree valid prefix.
bool operator!=(const _Node_citer &other) const
Compares content (negatively) to a different iterator object.
Node::metadata_type metadata_type
Metadata type.
bool operator==(const _Node_citer &other) const
Compares content to a different iterator object.
_Node_citer get_child(size_type i) const
Returns a __const node __iterator to the corresponding node's i-th child.
size_type num_children() const
Returns the number of children in the corresponding node.
const_reference operator*() const
Const access; returns the __const iterator* associated with the current leaf.
metadata_const_reference get_metadata() const
Metadata access.
rebind_traits< _Alloc, metadata_type >::const_reference metadata_const_reference
Const metadata reference type.
reference operator*() const
Access; returns the iterator* associated with the current leaf.
_Node_iter get_child(size_type i) const
Returns a node __iterator to the corresponding node's i-th child.