]> git.ipfire.org Git - thirdparty/gcc.git/blame - libstdc++-v3/include/ext/pb_ds/detail/pat_trie_/pat_trie_base.hpp
Update copyright years.
[thirdparty/gcc.git] / libstdc++-v3 / include / ext / pb_ds / detail / pat_trie_ / pat_trie_base.hpp
CommitLineData
a345e45d
BK
1// -*- C++ -*-
2
a5544970 3// Copyright (C) 2005-2019 Free Software Foundation, Inc.
a345e45d
BK
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
46namespace __gnu_pbds
47{
48 namespace detail
49 {
50 /// Base type for PATRICIA trees.
51 struct pat_trie_base
52 {
b234b0ca
BK
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 */
a345e45d
BK
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 _Alloc::template rebind<Metadata> __rebind_m;
72 typedef typename __rebind_m::other::const_reference 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;
102 typedef typename _Alloc::template rebind<_Node_base> __rebind_n;
103 typedef typename __rebind_n::other::pointer 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
111 typedef typename _Alloc::template rebind<_ATraits> __rebind_at;
112 typedef typename __rebind_at::other::const_pointer 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 {
134 typedef _Node_base<_ATraits, Metadata> base_type;
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 {
165 typedef _Node_base<_ATraits, Metadata> base_type;
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 {
214 typedef _Node_base<_ATraits, Metadata> base_type;
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;
227 typedef typename _Alloc::template rebind<base_type> __rebind_n;
228 typedef typename __rebind_n::other::const_pointer node_const_pointer;
229
230 typedef _Leaf<_ATraits, Metadata> leaf;
231 typedef typename _Alloc::template rebind<leaf>::other __rebind_l;
232 typedef typename __rebind_l::pointer leaf_pointer;
233 typedef typename __rebind_l::const_pointer leaf_const_pointer;
234
235 typedef typename _Alloc::template rebind<_Inode>::other __rebind_in;
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:
243 typedef typename _Alloc::template rebind<node_pointer>::other __rebind_np;
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.
255 struct const_iterator
256 {
257 node_pointer_pointer m_p_p_cur;
258 node_pointer_pointer m_p_p_end;
259
260 typedef std::forward_iterator_tag iterator_category;
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
279 const_iterator&
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
288 const_iterator
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:
323 typedef std::forward_iterator_tag iterator_category;
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
378 const_iterator
379 begin() const;
380
381 iterator
382 begin();
383
384 const_iterator
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
494 typedef std::bidirectional_iterator_tag iterator_category;
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 _Alloc::template rebind<Node> __rebind_n;
504 typedef typename __rebind_n::other::pointer node_pointer;
505 typedef typename _Alloc::template rebind<Leaf> __rebind_l;
506 typedef typename __rebind_l::other::pointer leaf_pointer;
507 typedef typename __rebind_l::other::const_pointer leaf_const_pointer;
508 typedef typename _Alloc::template rebind<Head> __rebind_h;
509 typedef typename __rebind_h::other::pointer head_pointer;
510
511 typedef typename _Alloc::template rebind<Inode> __rebind_in;
512 typedef typename __rebind_in::other::pointer inode_pointer;
513 typedef typename Inode::iterator inode_iterator;
514
515 node_pointer m_p_nd;
516
517 _CIter(node_pointer p_nd = 0) : m_p_nd(p_nd)
518 { }
519
520 _CIter(const PB_DS_CONST_ODIR_IT_C_DEC& other)
521 : m_p_nd(other.m_p_nd)
522 { }
523
524 _CIter&
525 operator=(const _CIter& other)
526 {
527 m_p_nd = other.m_p_nd;
528 return *this;
529 }
530
531 _CIter&
532 operator=(const PB_DS_CONST_ODIR_IT_C_DEC& other)
533 {
534 m_p_nd = other.m_p_nd;
535 return *this;
536 }
537
538 const_pointer
539 operator->() const
540 {
541 _GLIBCXX_DEBUG_ASSERT(m_p_nd->m_type == leaf_node);
542 return &static_cast<leaf_pointer>(m_p_nd)->value();
543 }
544
545 const_reference
546 operator*() const
547 {
548 _GLIBCXX_DEBUG_ASSERT(m_p_nd->m_type == leaf_node);
549 return static_cast<leaf_pointer>(m_p_nd)->value();
550 }
551
552 bool
553 operator==(const _CIter& other) const
554 { return m_p_nd == other.m_p_nd; }
555
556 bool
557 operator==(const PB_DS_CONST_ODIR_IT_C_DEC& other) const
558 { return m_p_nd == other.m_p_nd; }
559
560 bool
561 operator!=(const _CIter& other) const
562 { return m_p_nd != other.m_p_nd; }
563
564 bool
565 operator!=(const PB_DS_CONST_ODIR_IT_C_DEC& other) const
566 { return m_p_nd != other.m_p_nd; }
567
568 _CIter&
569 operator++()
570 {
571 inc(integral_constant<int, Is_Forward_Iterator>());
572 return *this;
573 }
574
575 _CIter
576 operator++(int)
577 {
578 _CIter ret_it(m_p_nd);
579 operator++();
580 return ret_it;
581 }
582
583 _CIter&
584 operator--()
585 {
586 dec(integral_constant<int, Is_Forward_Iterator>());
587 return *this;
588 }
589
590 _CIter
591 operator--(int)
592 {
593 _CIter ret_it(m_p_nd);
594 operator--();
595 return ret_it;
596 }
597
598 protected:
599 void
600 inc(false_type)
601 { dec(true_type()); }
602
603 void
604 inc(true_type)
605 {
606 if (m_p_nd->m_type == head_node)
607 {
608 m_p_nd = static_cast<head_pointer>(m_p_nd)->m_p_min;
609 return;
610 }
611
612 node_pointer p_y = m_p_nd->m_p_parent;
613 while (p_y->m_type != head_node && get_larger_sibling(m_p_nd) == 0)
614 {
615 m_p_nd = p_y;
616 p_y = p_y->m_p_parent;
617 }
618
619 if (p_y->m_type == head_node)
620 {
621 m_p_nd = p_y;
622 return;
623 }
624 m_p_nd = leftmost_descendant(get_larger_sibling(m_p_nd));
625 }
626
627 void
628 dec(false_type)
629 { inc(true_type()); }
630
631 void
632 dec(true_type)
633 {
634 if (m_p_nd->m_type == head_node)
635 {
636 m_p_nd = static_cast<head_pointer>(m_p_nd)->m_p_max;
637 return;
638 }
639
640 node_pointer p_y = m_p_nd->m_p_parent;
641 while (p_y->m_type != head_node && get_smaller_sibling(m_p_nd) == 0)
642 {
643 m_p_nd = p_y;
644 p_y = p_y->m_p_parent;
645 }
646
647 if (p_y->m_type == head_node)
648 {
649 m_p_nd = p_y;
650 return;
651 }
652 m_p_nd = rightmost_descendant(get_smaller_sibling(m_p_nd));
653 }
654
655 static node_pointer
656 get_larger_sibling(node_pointer p_nd)
657 {
658 inode_pointer p_parent = static_cast<inode_pointer>(p_nd->m_p_parent);
659
660 inode_iterator it = p_parent->begin();
661 while (*it != p_nd)
662 ++it;
663
664 inode_iterator next_it = it;
665 ++next_it;
666 return (next_it == p_parent->end())? 0 : *next_it;
667 }
668
669 static node_pointer
670 get_smaller_sibling(node_pointer p_nd)
671 {
672 inode_pointer p_parent = static_cast<inode_pointer>(p_nd->m_p_parent);
673
674 inode_iterator it = p_parent->begin();
675 if (*it == p_nd)
676 return 0;
677
678 inode_iterator prev_it;
679 do
680 {
681 prev_it = it;
682 ++it;
683 if (*it == p_nd)
684 return *prev_it;
685 }
686 while (true);
687
688 _GLIBCXX_DEBUG_ASSERT(false);
689 return 0;
690 }
691
692 static leaf_pointer
693 leftmost_descendant(node_pointer p_nd)
694 {
695 if (p_nd->m_type == leaf_node)
696 return static_cast<leaf_pointer>(p_nd);
697 return static_cast<inode_pointer>(p_nd)->leftmost_descendant();
698 }
699
700 static leaf_pointer
701 rightmost_descendant(node_pointer p_nd)
702 {
703 if (p_nd->m_type == leaf_node)
704 return static_cast<leaf_pointer>(p_nd);
705 return static_cast<inode_pointer>(p_nd)->rightmost_descendant();
706 }
707 };
708
709
710 /// Iterator.
711 template<typename Node, typename Leaf, typename Head, typename Inode,
712 bool Is_Forward_Iterator>
713 class _Iter
714 : public _CIter<Node, Leaf, Head, Inode, Is_Forward_Iterator>
715 {
716 public:
717 typedef _CIter<Node, Leaf, Head, Inode, Is_Forward_Iterator>
718 base_type;
719 typedef typename base_type::allocator_type allocator_type;
720 typedef typename base_type::type_traits type_traits;
721 typedef typename type_traits::value_type value_type;
722 typedef typename type_traits::pointer pointer;
723 typedef typename type_traits::reference reference;
724
725 typedef typename base_type::node_pointer node_pointer;
726 typedef typename base_type::leaf_pointer leaf_pointer;
727 typedef typename base_type::leaf_const_pointer leaf_const_pointer;
728 typedef typename base_type::head_pointer head_pointer;
729 typedef typename base_type::inode_pointer inode_pointer;
730
731 _Iter(node_pointer p_nd = 0)
732 : base_type(p_nd) { }
733
734 _Iter(const PB_DS_ODIR_IT_C_DEC& other)
735 : base_type(other.m_p_nd) { }
736
737 _Iter&
738 operator=(const _Iter& other)
739 {
740 base_type::m_p_nd = other.m_p_nd;
741 return *this;
742 }
743
744 _Iter&
745 operator=(const PB_DS_ODIR_IT_C_DEC& other)
746 {
747 base_type::m_p_nd = other.m_p_nd;
748 return *this;
749 }
750
751 pointer
752 operator->() const
753 {
754 _GLIBCXX_DEBUG_ASSERT(base_type::m_p_nd->m_type == leaf_node);
755 return &static_cast<leaf_pointer>(base_type::m_p_nd)->value();
756 }
757
758 reference
759 operator*() const
760 {
761 _GLIBCXX_DEBUG_ASSERT(base_type::m_p_nd->m_type == leaf_node);
762 return static_cast<leaf_pointer>(base_type::m_p_nd)->value();
763 }
764
765 _Iter&
766 operator++()
767 {
768 base_type::operator++();
769 return *this;
770 }
771
772 _Iter
773 operator++(int)
774 {
775 _Iter ret(base_type::m_p_nd);
776 operator++();
777 return ret;
778 }
779
780 _Iter&
781 operator--()
782 {
783 base_type::operator--();
784 return *this;
785 }
786
787 _Iter
788 operator--(int)
789 {
790 _Iter ret(base_type::m_p_nd);
791 operator--();
792 return ret;
793 }
794 };
795
796#undef PB_DS_CONST_ODIR_IT_C_DEC
797#undef PB_DS_ODIR_IT_C_DEC
798
799
800#define PB_DS_PAT_TRIE_NODE_CONST_ITERATOR_C_DEC \
801 _Node_citer<Node, Leaf, Head, Inode, _CIterator, Iterator, _ATraits, _Alloc>
802
803#define PB_DS_PAT_TRIE_NODE_ITERATOR_C_DEC \
804 _Node_iter<Node, Leaf, Head, Inode, _CIterator, Iterator, _ATraits, _Alloc>
805
806 /// Node const iterator.
807 template<typename Node,
808 typename Leaf,
809 typename Head,
810 typename Inode,
811 typename _CIterator,
812 typename Iterator,
813 typename _Alloc>
814 class _Node_citer
815 {
816 protected:
817 typedef typename _Alloc::template rebind<Node> __rebind_n;
818 typedef typename __rebind_n::other::pointer node_pointer;
819
820 typedef typename _Alloc::template rebind<Leaf> __rebind_l;
821 typedef typename __rebind_l::other::pointer leaf_pointer;
822 typedef typename __rebind_l::other::const_pointer leaf_const_pointer;
823
824 typedef typename _Alloc::template rebind<Inode> __rebind_in;
825 typedef typename __rebind_in::other::pointer inode_pointer;
826 typedef typename __rebind_in::other::const_pointer inode_const_pointer;
827
828 typedef typename Node::a_const_pointer a_const_pointer;
829 typedef typename Node::a_const_iterator a_const_iterator;
830
831 private:
832 a_const_iterator
833 pref_begin() const
834 {
835 if (m_p_nd->m_type == leaf_node)
836 {
837 leaf_const_pointer lcp = static_cast<leaf_const_pointer>(m_p_nd);
838 return m_p_traits->begin(m_p_traits->extract_key(lcp->value()));
839 }
840 _GLIBCXX_DEBUG_ASSERT(m_p_nd->m_type == i_node);
841 return static_cast<inode_const_pointer>(m_p_nd)->pref_b_it();
842 }
843
844 a_const_iterator
845 pref_end() const
846 {
847 if (m_p_nd->m_type == leaf_node)
848 {
849 leaf_const_pointer lcp = static_cast<leaf_const_pointer>(m_p_nd);
850 return m_p_traits->end(m_p_traits->extract_key(lcp->value()));
851 }
852 _GLIBCXX_DEBUG_ASSERT(m_p_nd->m_type == i_node);
853 return static_cast<inode_const_pointer>(m_p_nd)->pref_e_it();
854 }
855
856 public:
857 typedef trivial_iterator_tag iterator_category;
858 typedef trivial_iterator_difference_type difference_type;
859 typedef typename _Alloc::size_type size_type;
860
861 typedef _CIterator value_type;
862 typedef value_type reference;
863 typedef value_type const_reference;
864
30a96b3b 865 /// Metadata type.
a345e45d
BK
866 typedef typename Node::metadata_type metadata_type;
867
30a96b3b 868 /// Const metadata reference type.
a345e45d
BK
869 typedef typename _Alloc::template rebind<metadata_type> __rebind_m;
870 typedef typename __rebind_m::other __rebind_ma;
871 typedef typename __rebind_ma::const_reference metadata_const_reference;
872
873 inline
874 _Node_citer(node_pointer p_nd = 0, a_const_pointer p_traits = 0)
875 : m_p_nd(const_cast<node_pointer>(p_nd)), m_p_traits(p_traits)
876 { }
877
30a96b3b 878 /// Subtree valid prefix.
a345e45d
BK
879 std::pair<a_const_iterator, a_const_iterator>
880 valid_prefix() const
881 { return std::make_pair(pref_begin(), pref_end()); }
882
30a96b3b
BK
883 /// Const access; returns the __const iterator* associated with
884 /// the current leaf.
a345e45d
BK
885 const_reference
886 operator*() const
887 {
888 _GLIBCXX_DEBUG_ASSERT(num_children() == 0);
889 return _CIterator(m_p_nd);
890 }
891
30a96b3b 892 /// Metadata access.
a345e45d
BK
893 metadata_const_reference
894 get_metadata() const
895 { return m_p_nd->get_metadata(); }
896
30a96b3b 897 /// Returns the number of children in the corresponding node.
a345e45d
BK
898 size_type
899 num_children() const
900 {
901 if (m_p_nd->m_type == leaf_node)
902 return 0;
903 _GLIBCXX_DEBUG_ASSERT(m_p_nd->m_type == i_node);
904 inode_pointer inp = static_cast<inode_pointer>(m_p_nd);
905 return std::distance(inp->begin(), inp->end());
906 }
907
30a96b3b
BK
908 /// Returns a __const node __iterator to the corresponding node's
909 /// i-th child.
a345e45d
BK
910 _Node_citer
911 get_child(size_type i) const
912 {
913 _GLIBCXX_DEBUG_ASSERT(m_p_nd->m_type == i_node);
914 inode_pointer inp = static_cast<inode_pointer>(m_p_nd);
915 typename Inode::iterator it = inp->begin();
916 std::advance(it, i);
917 return _Node_citer(*it, m_p_traits);
918 }
919
30a96b3b 920 /// Compares content to a different iterator object.
a345e45d
BK
921 bool
922 operator==(const _Node_citer& other) const
923 { return m_p_nd == other.m_p_nd; }
924
30a96b3b 925 /// Compares content (negatively) to a different iterator object.
a345e45d
BK
926 bool
927 operator!=(const _Node_citer& other) const
928 { return m_p_nd != other.m_p_nd; }
929
930 node_pointer m_p_nd;
931 a_const_pointer m_p_traits;
932 };
933
934
935 /// Node iterator.
936 template<typename Node,
937 typename Leaf,
938 typename Head,
939 typename Inode,
940 typename _CIterator,
941 typename Iterator,
942 typename _Alloc>
943 class _Node_iter
944 : public _Node_citer<Node, Leaf, Head, Inode, _CIterator, Iterator, _Alloc>
945 {
946 private:
947 typedef _Node_citer<Node, Leaf, Head, Inode,
948 _CIterator, Iterator, _Alloc> base_type;
949 typedef typename _Alloc::template rebind<Node> __rebind_n;
950 typedef typename __rebind_n::other::pointer node_pointer;
951 typedef typename base_type::inode_pointer inode_pointer;
952 typedef typename base_type::a_const_pointer a_const_pointer;
953 typedef Iterator iterator;
954
955 public:
956 typedef typename base_type::size_type size_type;
957
958 typedef Iterator value_type;
959 typedef value_type reference;
960 typedef value_type const_reference;
961
962 _Node_iter(node_pointer p_nd = 0, a_const_pointer p_traits = 0)
963 : base_type(p_nd, p_traits)
964 { }
965
30a96b3b 966 /// Access; returns the iterator* associated with the current leaf.
a345e45d
BK
967 reference
968 operator*() const
969 {
970 _GLIBCXX_DEBUG_ASSERT(base_type::num_children() == 0);
971 return iterator(base_type::m_p_nd);
972 }
973
30a96b3b 974 /// Returns a node __iterator to the corresponding node's i-th child.
a345e45d
BK
975 _Node_iter
976 get_child(size_type i) const
977 {
978 _GLIBCXX_DEBUG_ASSERT(base_type::m_p_nd->m_type == i_node);
979
980 typename Inode::iterator it =
981 static_cast<inode_pointer>(base_type::m_p_nd)->begin();
982
983 std::advance(it, i);
984 return _Node_iter(*it, base_type::m_p_traits);
985 }
986 };
987 };
988
989
990#define PB_DS_CLASS_T_DEC \
991 template<typename _ATraits, typename Metadata>
992
993#define PB_DS_CLASS_C_DEC \
994 pat_trie_base::_Inode<_ATraits, Metadata>
995
996 PB_DS_CLASS_T_DEC
997 typename PB_DS_CLASS_C_DEC::__rebind_l
998 PB_DS_CLASS_C_DEC::s_leaf_alloc;
999
1000 PB_DS_CLASS_T_DEC
1001 typename PB_DS_CLASS_C_DEC::__rebind_in
1002 PB_DS_CLASS_C_DEC::s_inode_alloc;
1003
1004 PB_DS_CLASS_T_DEC
1005 inline typename PB_DS_CLASS_C_DEC::size_type
1006 PB_DS_CLASS_C_DEC::
1007 get_pref_pos(a_const_iterator b_it, a_const_iterator e_it,
1008 a_const_pointer p_traits) const
1009 {
1010 if (static_cast<std::size_t>(std::distance(b_it, e_it)) <= m_e_ind)
1011 return 0;
1012 std::advance(b_it, m_e_ind);
1013 return 1 + p_traits->e_pos(*b_it);
1014 }
1015
1016 PB_DS_CLASS_T_DEC
1017 PB_DS_CLASS_C_DEC::
1018 _Inode(size_type len, const a_const_iterator it)
1019 : base_type(i_node), m_e_ind(len), m_pref_b_it(it), m_pref_e_it(it)
1020 {
1021 std::advance(m_pref_e_it, m_e_ind);
1022 std::fill(m_a_p_children, m_a_p_children + arr_size,
1023 static_cast<node_pointer>(0));
1024 }
1025
1026 PB_DS_CLASS_T_DEC
1027 void
1028 PB_DS_CLASS_C_DEC::
1029 update_prefixes(a_const_pointer p_traits)
1030 {
1031 node_pointer p_first = *begin();
1032 if (p_first->m_type == leaf_node)
1033 {
1034 leaf_const_pointer p = static_cast<leaf_const_pointer>(p_first);
1035 m_pref_b_it = p_traits->begin(access_traits::extract_key(p->value()));
1036 }
1037 else
1038 {
1039 inode_pointer p = static_cast<inode_pointer>(p_first);
1040 _GLIBCXX_DEBUG_ASSERT(p_first->m_type == i_node);
1041 m_pref_b_it = p->pref_b_it();
1042 }
1043 m_pref_e_it = m_pref_b_it;
1044 std::advance(m_pref_e_it, m_e_ind);
1045 }
1046
1047 PB_DS_CLASS_T_DEC
1048 typename PB_DS_CLASS_C_DEC::const_iterator
1049 PB_DS_CLASS_C_DEC::
1050 begin() const
1051 {
1052 typedef node_pointer_pointer pointer_type;
1053 pointer_type p = const_cast<pointer_type>(m_a_p_children);
1054 return const_iterator(p + get_begin_pos(), p + arr_size);
1055 }
1056
1057 PB_DS_CLASS_T_DEC
1058 typename PB_DS_CLASS_C_DEC::iterator
1059 PB_DS_CLASS_C_DEC::
1060 begin()
1061 {
1062 return iterator(m_a_p_children + get_begin_pos(),
1063 m_a_p_children + arr_size);
1064 }
1065
1066 PB_DS_CLASS_T_DEC
1067 typename PB_DS_CLASS_C_DEC::const_iterator
1068 PB_DS_CLASS_C_DEC::
1069 end() const
1070 {
1071 typedef node_pointer_pointer pointer_type;
1072 pointer_type p = const_cast<pointer_type>(m_a_p_children) + arr_size;
1073 return const_iterator(p, p);
1074 }
1075
1076 PB_DS_CLASS_T_DEC
1077 typename PB_DS_CLASS_C_DEC::iterator
1078 PB_DS_CLASS_C_DEC::
1079 end()
1080 { return iterator(m_a_p_children + arr_size, m_a_p_children + arr_size); }
1081
1082 PB_DS_CLASS_T_DEC
1083 inline typename PB_DS_CLASS_C_DEC::node_pointer
1084 PB_DS_CLASS_C_DEC::
1085 get_child_node(a_const_iterator b_it, a_const_iterator e_it,
1086 a_const_pointer p_traits)
1087 {
1088 const size_type i = get_pref_pos(b_it, e_it, p_traits);
1089 _GLIBCXX_DEBUG_ASSERT(i < arr_size);
1090 return m_a_p_children[i];
1091 }
1092
1093 PB_DS_CLASS_T_DEC
1094 inline typename PB_DS_CLASS_C_DEC::iterator
1095 PB_DS_CLASS_C_DEC::
1096 get_child_it(a_const_iterator b_it, a_const_iterator e_it,
1097 a_const_pointer p_traits)
1098 {
1099 const size_type i = get_pref_pos(b_it, e_it, p_traits);
1100 _GLIBCXX_DEBUG_ASSERT(i < arr_size);
1101 _GLIBCXX_DEBUG_ASSERT(m_a_p_children[i] != 0);
1102 return iterator(m_a_p_children + i, m_a_p_children + i);
1103 }
1104
1105 PB_DS_CLASS_T_DEC
1106 inline typename PB_DS_CLASS_C_DEC::node_const_pointer
1107 PB_DS_CLASS_C_DEC::
1108 get_child_node(a_const_iterator b_it, a_const_iterator e_it,
1109 a_const_pointer p_traits) const
1110 { return const_cast<node_pointer>(get_child_node(b_it, e_it, p_traits)); }
1111
1112 PB_DS_CLASS_T_DEC
1113 typename PB_DS_CLASS_C_DEC::node_pointer
1114 PB_DS_CLASS_C_DEC::
1115 get_lower_bound_child_node(a_const_iterator b_it, a_const_iterator e_it,
1116 size_type checked_ind,
1117 a_const_pointer p_traits)
1118 {
1119 if (!should_be_mine(b_it, e_it, checked_ind, p_traits))
1120 {
1121 if (p_traits->cmp_prefixes(b_it, e_it, m_pref_b_it,
1122 m_pref_e_it, true))
1123 return leftmost_descendant();
1124 return rightmost_descendant();
1125 }
1126
1127 size_type i = get_pref_pos(b_it, e_it, p_traits);
1128 _GLIBCXX_DEBUG_ASSERT(i < arr_size);
1129
1130 if (m_a_p_children[i] != 0)
1131 return m_a_p_children[i];
1132
1133 while (++i < arr_size)
1134 if (m_a_p_children[i] != 0)
1135 {
1136 const node_type& __nt = m_a_p_children[i]->m_type;
1137 node_pointer ret = m_a_p_children[i];
1138
1139 if (__nt == leaf_node)
1140 return ret;
1141
1142 _GLIBCXX_DEBUG_ASSERT(__nt == i_node);
1143 inode_pointer inp = static_cast<inode_pointer>(ret);
1144 return inp->leftmost_descendant();
1145 }
1146
1147 return rightmost_descendant();
1148 }
1149
1150 PB_DS_CLASS_T_DEC
1151 inline typename PB_DS_CLASS_C_DEC::node_pointer
1152 PB_DS_CLASS_C_DEC::
1153 add_child(node_pointer p_nd, a_const_iterator b_it, a_const_iterator e_it,
1154 a_const_pointer p_traits)
1155 {
1156 const size_type i = get_pref_pos(b_it, e_it, p_traits);
1157 _GLIBCXX_DEBUG_ASSERT(i < arr_size);
1158 if (m_a_p_children[i] == 0)
1159 {
1160 m_a_p_children[i] = p_nd;
1161 p_nd->m_p_parent = this;
1162 return p_nd;
1163 }
1164 return m_a_p_children[i];
1165 }
1166
1167 PB_DS_CLASS_T_DEC
1168 typename PB_DS_CLASS_C_DEC::node_const_pointer
1169 PB_DS_CLASS_C_DEC::
1170 get_join_child(node_const_pointer p_nd,
1171 a_const_pointer p_tr) const
1172 {
1173 node_pointer p = const_cast<node_pointer>(p_nd);
1174 return const_cast<inode_pointer>(this)->get_join_child(p, p_tr);
1175 }
1176
1177 PB_DS_CLASS_T_DEC
1178 typename PB_DS_CLASS_C_DEC::node_pointer
1179 PB_DS_CLASS_C_DEC::
1180 get_join_child(node_pointer p_nd, a_const_pointer p_traits)
1181 {
1182 size_type i;
1183 a_const_iterator b_it;
1184 a_const_iterator e_it;
1185 if (p_nd->m_type == leaf_node)
1186 {
1187 leaf_const_pointer p = static_cast<leaf_const_pointer>(p_nd);
1188
1189 typedef typename type_traits::key_const_reference kcr;
1190 kcr r_key = access_traits::extract_key(p->value());
1191 b_it = p_traits->begin(r_key);
1192 e_it = p_traits->end(r_key);
1193 }
1194 else
1195 {
1196 b_it = static_cast<inode_pointer>(p_nd)->pref_b_it();
1197 e_it = static_cast<inode_pointer>(p_nd)->pref_e_it();
1198 }
1199 i = get_pref_pos(b_it, e_it, p_traits);
1200 _GLIBCXX_DEBUG_ASSERT(i < arr_size);
1201 return m_a_p_children[i];
1202 }
1203
1204 PB_DS_CLASS_T_DEC
1205 void
1206 PB_DS_CLASS_C_DEC::
1207 remove_child(node_pointer p_nd)
1208 {
1209 size_type i = 0;
1210 for (; i < arr_size; ++i)
1211 if (m_a_p_children[i] == p_nd)
1212 {
1213 m_a_p_children[i] = 0;
1214 return;
1215 }
1216 _GLIBCXX_DEBUG_ASSERT(i != arr_size);
1217 }
1218
1219 PB_DS_CLASS_T_DEC
1220 void
1221 PB_DS_CLASS_C_DEC::
1222 remove_child(iterator it)
1223 { *it.m_p_p_cur = 0; }
1224
1225 PB_DS_CLASS_T_DEC
1226 void
1227 PB_DS_CLASS_C_DEC::
1228 replace_child(node_pointer p_nd, a_const_iterator b_it,
1229 a_const_iterator e_it,
1230 a_const_pointer p_traits)
1231 {
1232 const size_type i = get_pref_pos(b_it, e_it, p_traits);
1233 _GLIBCXX_DEBUG_ASSERT(i < arr_size);
1234 m_a_p_children[i] = p_nd;
1235 p_nd->m_p_parent = this;
1236 }
1237
1238 PB_DS_CLASS_T_DEC
1239 inline typename PB_DS_CLASS_C_DEC::a_const_iterator
1240 PB_DS_CLASS_C_DEC::
1241 pref_b_it() const
1242 { return m_pref_b_it; }
1243
1244 PB_DS_CLASS_T_DEC
1245 inline typename PB_DS_CLASS_C_DEC::a_const_iterator
1246 PB_DS_CLASS_C_DEC::
1247 pref_e_it() const
1248 { return m_pref_e_it; }
1249
1250 PB_DS_CLASS_T_DEC
1251 bool
1252 PB_DS_CLASS_C_DEC::
1253 should_be_mine(a_const_iterator b_it, a_const_iterator e_it,
1254 size_type checked_ind,
1255 a_const_pointer p_traits) const
1256 {
1257 if (m_e_ind == 0)
1258 return true;
1259
1260 const size_type num_es = std::distance(b_it, e_it);
1261 if (num_es < m_e_ind)
1262 return false;
1263
1264 a_const_iterator key_b_it = b_it;
1265 std::advance(key_b_it, checked_ind);
1266 a_const_iterator key_e_it = b_it;
1267 std::advance(key_e_it, m_e_ind);
1268
1269 a_const_iterator value_b_it = m_pref_b_it;
1270 std::advance(value_b_it, checked_ind);
1271 a_const_iterator value_e_it = m_pref_b_it;
1272 std::advance(value_e_it, m_e_ind);
1273
1274 return p_traits->equal_prefixes(key_b_it, key_e_it, value_b_it,
1275 value_e_it);
1276 }
1277
1278 PB_DS_CLASS_T_DEC
1279 typename PB_DS_CLASS_C_DEC::leaf_pointer
1280 PB_DS_CLASS_C_DEC::
1281 leftmost_descendant()
1282 {
1283 node_pointer p_pot = *begin();
1284 if (p_pot->m_type == leaf_node)
1285 return (static_cast<leaf_pointer>(p_pot));
1286 _GLIBCXX_DEBUG_ASSERT(p_pot->m_type == i_node);
1287 return static_cast<inode_pointer>(p_pot)->leftmost_descendant();
1288 }
1289
1290 PB_DS_CLASS_T_DEC
1291 typename PB_DS_CLASS_C_DEC::leaf_const_pointer
1292 PB_DS_CLASS_C_DEC::
1293 leftmost_descendant() const
1294 { return const_cast<inode_pointer>(this)->leftmost_descendant(); }
1295
1296 PB_DS_CLASS_T_DEC
1297 typename PB_DS_CLASS_C_DEC::leaf_pointer
1298 PB_DS_CLASS_C_DEC::
1299 rightmost_descendant()
1300 {
1301 const size_type num_children = std::distance(begin(), end());
1302 _GLIBCXX_DEBUG_ASSERT(num_children >= 2);
1303
1304 iterator it = begin();
1305 std::advance(it, num_children - 1);
1306 node_pointer p_pot =* it;
1307 if (p_pot->m_type == leaf_node)
1308 return static_cast<leaf_pointer>(p_pot);
1309 _GLIBCXX_DEBUG_ASSERT(p_pot->m_type == i_node);
1310 return static_cast<inode_pointer>(p_pot)->rightmost_descendant();
1311 }
1312
1313 PB_DS_CLASS_T_DEC
1314 typename PB_DS_CLASS_C_DEC::leaf_const_pointer
1315 PB_DS_CLASS_C_DEC::
1316 rightmost_descendant() const
1317 { return const_cast<inode_pointer>(this)->rightmost_descendant(); }
1318
1319 PB_DS_CLASS_T_DEC
1320 typename PB_DS_CLASS_C_DEC::size_type
1321 PB_DS_CLASS_C_DEC::
1322 get_begin_pos() const
1323 {
1324 size_type i = 0;
98656b3d 1325 for (; i < arr_size && m_a_p_children[i] == 0; ++i)
a345e45d
BK
1326 ;
1327 return i;
1328 }
1329
1330#ifdef _GLIBCXX_DEBUG
1331 PB_DS_CLASS_T_DEC
1332 typename PB_DS_CLASS_C_DEC::node_debug_info
1333 PB_DS_CLASS_C_DEC::
1334 assert_valid_imp(a_const_pointer p_traits,
1335 const char* __file, int __line) const
1336 {
1337 PB_DS_DEBUG_VERIFY(base_type::m_type == i_node);
1338 PB_DS_DEBUG_VERIFY(static_cast<size_type>(std::distance(pref_b_it(), pref_e_it())) == m_e_ind);
1339 PB_DS_DEBUG_VERIFY(std::distance(begin(), end()) >= 2);
1340
1341 for (typename _Inode::const_iterator it = begin(); it != end(); ++it)
1342 {
1343 node_const_pointer p_nd = *it;
1344 PB_DS_DEBUG_VERIFY(p_nd->m_p_parent == this);
1345 node_debug_info child_ret = p_nd->assert_valid_imp(p_traits,
1346 __file, __line);
1347
1348 PB_DS_DEBUG_VERIFY(static_cast<size_type>(std::distance(child_ret.first, child_ret.second)) >= m_e_ind);
1349 PB_DS_DEBUG_VERIFY(should_be_mine(child_ret.first, child_ret.second, 0, p_traits));
1350 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));
1351 }
1352 return std::make_pair(pref_b_it(), pref_e_it());
1353 }
1354#endif
1355
1356#undef PB_DS_CLASS_T_DEC
1357#undef PB_DS_CLASS_C_DEC
1358 } // namespace detail
1359} // namespace __gnu_pbds
1360
1361#endif