]> git.ipfire.org Git - thirdparty/gcc.git/blob - libstdc++-v3/include/ext/pb_ds/detail/pat_trie_/pat_trie_base.hpp
pat_trie_base.hpp: Avoid -Wall warning.
[thirdparty/gcc.git] / libstdc++-v3 / include / ext / pb_ds / detail / pat_trie_ / pat_trie_base.hpp
1 // -*- C++ -*-
2
3 // Copyright (C) 2005, 2006, 2009, 2011 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.
51 struct pat_trie_base
52 {
53 /// Three types of nodes.
54 enum node_type
55 {
56 i_node,
57 leaf_node,
58 head_node
59 };
60
61 /// Metadata base primary template.
62 template<typename Metadata, typename _Alloc>
63 struct _Metadata
64 {
65 typedef Metadata metadata_type;
66 typedef _Alloc allocator_type;
67 typedef typename _Alloc::template rebind<Metadata> __rebind_m;
68 typedef typename __rebind_m::other::const_reference const_reference;
69
70 const_reference
71 get_metadata() const
72 { return m_metadata; }
73
74 metadata_type m_metadata;
75 };
76
77 /// Specialization for null metadata.
78 template<typename _Alloc>
79 struct _Metadata<null_type, _Alloc>
80 {
81 typedef null_type metadata_type;
82 typedef _Alloc allocator_type;
83 };
84
85
86 /// Node base.
87 template<typename _ATraits, typename Metadata>
88 struct _Node_base
89 : public Metadata
90 {
91 private:
92 typedef typename Metadata::allocator_type _Alloc;
93
94 public:
95 typedef _Alloc allocator_type;
96 typedef _ATraits access_traits;
97 typedef typename _ATraits::type_traits type_traits;
98 typedef typename _Alloc::template rebind<_Node_base> __rebind_n;
99 typedef typename __rebind_n::other::pointer node_pointer;
100
101 node_pointer m_p_parent;
102 const node_type m_type;
103
104 _Node_base(node_type type) : m_type(type)
105 { }
106
107 typedef typename _Alloc::template rebind<_ATraits> __rebind_at;
108 typedef typename __rebind_at::other::const_pointer a_const_pointer;
109 typedef typename _ATraits::const_iterator a_const_iterator;
110
111 #ifdef _GLIBCXX_DEBUG
112 typedef std::pair<a_const_iterator, a_const_iterator> node_debug_info;
113
114 void
115 assert_valid(a_const_pointer p_traits,
116 const char* __file, int __line) const
117 { assert_valid_imp(p_traits, __file, __line); }
118
119 virtual node_debug_info
120 assert_valid_imp(a_const_pointer, const char*, int) const = 0;
121 #endif
122 };
123
124
125 /// Head node for PATRICIA tree.
126 template<typename _ATraits, typename Metadata>
127 struct _Head
128 : public _Node_base<_ATraits, Metadata>
129 {
130 typedef _Node_base<_ATraits, Metadata> base_type;
131 typedef typename base_type::type_traits type_traits;
132 typedef typename base_type::node_pointer node_pointer;
133
134 node_pointer m_p_min;
135 node_pointer m_p_max;
136
137 _Head() : base_type(head_node) { }
138
139 #ifdef _GLIBCXX_DEBUG
140 typedef typename base_type::node_debug_info node_debug_info;
141 typedef typename base_type::a_const_pointer a_const_pointer;
142
143 virtual node_debug_info
144 assert_valid_imp(a_const_pointer, const char* __file, int __line) const
145 {
146 _GLIBCXX_DEBUG_VERIFY_AT(false,
147 _M_message("Assertion from %1;:%2;")
148 ._M_string(__FILE__)._M_integer(__LINE__),
149 __file, __line);
150 return node_debug_info();
151 }
152 #endif
153 };
154
155
156 /// Leaf node for PATRICIA tree.
157 template<typename _ATraits, typename Metadata>
158 struct _Leaf
159 : public _Node_base<_ATraits, Metadata>
160 {
161 typedef _Node_base<_ATraits, Metadata> base_type;
162 typedef typename base_type::type_traits type_traits;
163 typedef typename type_traits::value_type value_type;
164 typedef typename type_traits::reference reference;
165 typedef typename type_traits::const_reference const_reference;
166
167 private:
168 value_type m_value;
169
170 _Leaf(const _Leaf&);
171
172 public:
173 _Leaf(const_reference other)
174 : base_type(leaf_node), m_value(other) { }
175
176 reference
177 value()
178 { return m_value; }
179
180 const_reference
181 value() const
182 { return m_value; }
183
184 #ifdef _GLIBCXX_DEBUG
185 typedef typename base_type::node_debug_info node_debug_info;
186 typedef typename base_type::a_const_pointer a_const_pointer;
187
188 virtual node_debug_info
189 assert_valid_imp(a_const_pointer p_traits,
190 const char* __file, int __line) const
191 {
192 PB_DS_DEBUG_VERIFY(base_type::m_type == leaf_node);
193 node_debug_info ret;
194 const_reference r_val = value();
195 return std::make_pair(p_traits->begin(p_traits->extract_key(r_val)),
196 p_traits->end(p_traits->extract_key(r_val)));
197 }
198
199 virtual
200 ~_Leaf() { }
201 #endif
202 };
203
204
205 /// Internal node type, PATRICIA tree.
206 template<typename _ATraits, typename Metadata>
207 struct _Inode
208 : public _Node_base<_ATraits, Metadata>
209 {
210 typedef _Node_base<_ATraits, Metadata> base_type;
211 typedef typename base_type::type_traits type_traits;
212 typedef typename base_type::access_traits access_traits;
213 typedef typename type_traits::value_type value_type;
214 typedef typename base_type::allocator_type _Alloc;
215 typedef _Alloc allocator_type;
216 typedef typename _Alloc::size_type size_type;
217
218 private:
219 typedef typename base_type::a_const_pointer a_const_pointer;
220 typedef typename base_type::a_const_iterator a_const_iterator;
221
222 typedef typename base_type::node_pointer node_pointer;
223 typedef typename _Alloc::template rebind<base_type> __rebind_n;
224 typedef typename __rebind_n::other::const_pointer node_const_pointer;
225
226 typedef _Leaf<_ATraits, Metadata> leaf;
227 typedef typename _Alloc::template rebind<leaf>::other __rebind_l;
228 typedef typename __rebind_l::pointer leaf_pointer;
229 typedef typename __rebind_l::const_pointer leaf_const_pointer;
230
231 typedef typename _Alloc::template rebind<_Inode>::other __rebind_in;
232 typedef typename __rebind_in::pointer inode_pointer;
233 typedef typename __rebind_in::const_pointer inode_const_pointer;
234
235 inline size_type
236 get_pref_pos(a_const_iterator, a_const_iterator, a_const_pointer) const;
237
238 public:
239 typedef typename _Alloc::template rebind<node_pointer>::other __rebind_np;
240 typedef typename __rebind_np::pointer node_pointer_pointer;
241 typedef typename __rebind_np::reference node_pointer_reference;
242
243 enum
244 {
245 arr_size = _ATraits::max_size + 1
246 };
247 PB_DS_STATIC_ASSERT(min_arr_size, arr_size >= 2);
248
249
250 /// Constant child iterator.
251 struct const_iterator
252 {
253 node_pointer_pointer m_p_p_cur;
254 node_pointer_pointer m_p_p_end;
255
256 typedef std::forward_iterator_tag iterator_category;
257 typedef typename _Alloc::difference_type difference_type;
258 typedef node_pointer value_type;
259 typedef node_pointer_pointer pointer;
260 typedef node_pointer_reference reference;
261
262 const_iterator(node_pointer_pointer p_p_cur = 0,
263 node_pointer_pointer p_p_end = 0)
264 : m_p_p_cur(p_p_cur), m_p_p_end(p_p_end)
265 { }
266
267 bool
268 operator==(const const_iterator& other) const
269 { return m_p_p_cur == other.m_p_p_cur; }
270
271 bool
272 operator!=(const const_iterator& other) const
273 { return m_p_p_cur != other.m_p_p_cur; }
274
275 const_iterator&
276 operator++()
277 {
278 do
279 ++m_p_p_cur;
280 while (m_p_p_cur != m_p_p_end && *m_p_p_cur == 0);
281 return *this;
282 }
283
284 const_iterator
285 operator++(int)
286 {
287 const_iterator ret_it(*this);
288 operator++();
289 return ret_it;
290 }
291
292 const node_pointer_pointer
293 operator->() const
294 {
295 _GLIBCXX_DEBUG_ONLY(assert_referencible();)
296 return m_p_p_cur;
297 }
298
299 node_const_pointer
300 operator*() const
301 {
302 _GLIBCXX_DEBUG_ONLY(assert_referencible();)
303 return *m_p_p_cur;
304 }
305
306 protected:
307 #ifdef _GLIBCXX_DEBUG
308 void
309 assert_referencible() const
310 { _GLIBCXX_DEBUG_ASSERT(m_p_p_cur != m_p_p_end && *m_p_p_cur != 0); }
311 #endif
312 };
313
314
315 /// Child iterator.
316 struct iterator : public const_iterator
317 {
318 public:
319 typedef std::forward_iterator_tag iterator_category;
320 typedef typename _Alloc::difference_type difference_type;
321 typedef node_pointer value_type;
322 typedef node_pointer_pointer pointer;
323 typedef node_pointer_reference reference;
324
325 inline
326 iterator(node_pointer_pointer p_p_cur = 0,
327 node_pointer_pointer p_p_end = 0)
328 : const_iterator(p_p_cur, p_p_end) { }
329
330 bool
331 operator==(const iterator& other) const
332 { return const_iterator::m_p_p_cur == other.m_p_p_cur; }
333
334 bool
335 operator!=(const iterator& other) const
336 { return const_iterator::m_p_p_cur != other.m_p_p_cur; }
337
338 iterator&
339 operator++()
340 {
341 const_iterator::operator++();
342 return *this;
343 }
344
345 iterator
346 operator++(int)
347 {
348 iterator ret_it(*this);
349 operator++();
350 return ret_it;
351 }
352
353 node_pointer_pointer
354 operator->()
355 {
356 _GLIBCXX_DEBUG_ONLY(const_iterator::assert_referencible();)
357 return const_iterator::m_p_p_cur;
358 }
359
360 node_pointer
361 operator*()
362 {
363 _GLIBCXX_DEBUG_ONLY(const_iterator::assert_referencible();)
364 return *const_iterator::m_p_p_cur;
365 }
366 };
367
368
369 _Inode(size_type, const a_const_iterator);
370
371 void
372 update_prefixes(a_const_pointer);
373
374 const_iterator
375 begin() const;
376
377 iterator
378 begin();
379
380 const_iterator
381 end() const;
382
383 iterator
384 end();
385
386 inline node_pointer
387 get_child_node(a_const_iterator, a_const_iterator, a_const_pointer);
388
389 inline node_const_pointer
390 get_child_node(a_const_iterator, a_const_iterator, a_const_pointer) const;
391
392 inline iterator
393 get_child_it(a_const_iterator, a_const_iterator, a_const_pointer);
394
395 inline node_pointer
396 get_lower_bound_child_node(a_const_iterator, a_const_iterator,
397 size_type, a_const_pointer);
398
399 inline node_pointer
400 add_child(node_pointer, a_const_iterator, a_const_iterator,
401 a_const_pointer);
402
403 inline node_const_pointer
404 get_join_child(node_const_pointer, a_const_pointer) const;
405
406 inline node_pointer
407 get_join_child(node_pointer, a_const_pointer);
408
409 void
410 remove_child(node_pointer);
411
412 void
413 remove_child(iterator);
414
415 void
416 replace_child(node_pointer, a_const_iterator, a_const_iterator,
417 a_const_pointer);
418
419 inline a_const_iterator
420 pref_b_it() const;
421
422 inline a_const_iterator
423 pref_e_it() const;
424
425 bool
426 should_be_mine(a_const_iterator, a_const_iterator, size_type,
427 a_const_pointer) const;
428
429 leaf_pointer
430 leftmost_descendant();
431
432 leaf_const_pointer
433 leftmost_descendant() const;
434
435 leaf_pointer
436 rightmost_descendant();
437
438 leaf_const_pointer
439 rightmost_descendant() const;
440
441 #ifdef _GLIBCXX_DEBUG
442 typedef typename base_type::node_debug_info node_debug_info;
443
444 virtual node_debug_info
445 assert_valid_imp(a_const_pointer, const char*, int) const;
446 #endif
447
448 size_type
449 get_e_ind() const
450 { return m_e_ind; }
451
452 private:
453 _Inode(const _Inode&);
454
455 size_type
456 get_begin_pos() const;
457
458 static __rebind_l s_leaf_alloc;
459 static __rebind_in s_inode_alloc;
460
461 const size_type m_e_ind;
462 a_const_iterator m_pref_b_it;
463 a_const_iterator m_pref_e_it;
464 node_pointer m_a_p_children[arr_size];
465 };
466
467 #define PB_DS_CONST_IT_C_DEC \
468 _CIter<Node, Leaf, Head, Inode, Is_Forward_Iterator>
469
470 #define PB_DS_CONST_ODIR_IT_C_DEC \
471 _CIter<Node, Leaf, Head, Inode, !Is_Forward_Iterator>
472
473 #define PB_DS_IT_C_DEC \
474 _Iter<Node, Leaf, Head, Inode, Is_Forward_Iterator>
475
476 #define PB_DS_ODIR_IT_C_DEC \
477 _Iter<Node, Leaf, Head, Inode, !Is_Forward_Iterator>
478
479
480 /// Const iterator.
481 template<typename Node, typename Leaf, typename Head, typename Inode,
482 bool Is_Forward_Iterator>
483 class _CIter
484 {
485 public:
486 // These types are all the same for the first four template arguments.
487 typedef typename Node::allocator_type allocator_type;
488 typedef typename Node::type_traits type_traits;
489
490 typedef std::bidirectional_iterator_tag iterator_category;
491 typedef typename allocator_type::difference_type difference_type;
492 typedef typename type_traits::value_type value_type;
493 typedef typename type_traits::pointer pointer;
494 typedef typename type_traits::reference reference;
495 typedef typename type_traits::const_pointer const_pointer;
496 typedef typename type_traits::const_reference const_reference;
497
498 typedef allocator_type _Alloc;
499 typedef typename _Alloc::template rebind<Node> __rebind_n;
500 typedef typename __rebind_n::other::pointer node_pointer;
501 typedef typename _Alloc::template rebind<Leaf> __rebind_l;
502 typedef typename __rebind_l::other::pointer leaf_pointer;
503 typedef typename __rebind_l::other::const_pointer leaf_const_pointer;
504 typedef typename _Alloc::template rebind<Head> __rebind_h;
505 typedef typename __rebind_h::other::pointer head_pointer;
506
507 typedef typename _Alloc::template rebind<Inode> __rebind_in;
508 typedef typename __rebind_in::other::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:
713 typedef _CIter<Node, Leaf, Head, Inode, Is_Forward_Iterator>
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>
810 class _Node_citer
811 {
812 protected:
813 typedef typename _Alloc::template rebind<Node> __rebind_n;
814 typedef typename __rebind_n::other::pointer node_pointer;
815
816 typedef typename _Alloc::template rebind<Leaf> __rebind_l;
817 typedef typename __rebind_l::other::pointer leaf_pointer;
818 typedef typename __rebind_l::other::const_pointer leaf_const_pointer;
819
820 typedef typename _Alloc::template rebind<Inode> __rebind_in;
821 typedef typename __rebind_in::other::pointer inode_pointer;
822 typedef typename __rebind_in::other::const_pointer inode_const_pointer;
823
824 typedef typename Node::a_const_pointer a_const_pointer;
825 typedef typename Node::a_const_iterator a_const_iterator;
826
827 private:
828 a_const_iterator
829 pref_begin() const
830 {
831 if (m_p_nd->m_type == leaf_node)
832 {
833 leaf_const_pointer lcp = static_cast<leaf_const_pointer>(m_p_nd);
834 return m_p_traits->begin(m_p_traits->extract_key(lcp->value()));
835 }
836 _GLIBCXX_DEBUG_ASSERT(m_p_nd->m_type == i_node);
837 return static_cast<inode_const_pointer>(m_p_nd)->pref_b_it();
838 }
839
840 a_const_iterator
841 pref_end() const
842 {
843 if (m_p_nd->m_type == leaf_node)
844 {
845 leaf_const_pointer lcp = static_cast<leaf_const_pointer>(m_p_nd);
846 return m_p_traits->end(m_p_traits->extract_key(lcp->value()));
847 }
848 _GLIBCXX_DEBUG_ASSERT(m_p_nd->m_type == i_node);
849 return static_cast<inode_const_pointer>(m_p_nd)->pref_e_it();
850 }
851
852 public:
853 typedef trivial_iterator_tag iterator_category;
854 typedef trivial_iterator_difference_type difference_type;
855 typedef typename _Alloc::size_type size_type;
856
857 typedef _CIterator value_type;
858 typedef value_type reference;
859 typedef value_type const_reference;
860
861 /// Metadata type.
862 typedef typename Node::metadata_type metadata_type;
863
864 /// Const metadata reference type.
865 typedef typename _Alloc::template rebind<metadata_type> __rebind_m;
866 typedef typename __rebind_m::other __rebind_ma;
867 typedef typename __rebind_ma::const_reference metadata_const_reference;
868
869 inline
870 _Node_citer(node_pointer p_nd = 0, a_const_pointer p_traits = 0)
871 : m_p_nd(const_cast<node_pointer>(p_nd)), m_p_traits(p_traits)
872 { }
873
874 /// Subtree valid prefix.
875 std::pair<a_const_iterator, a_const_iterator>
876 valid_prefix() const
877 { return std::make_pair(pref_begin(), pref_end()); }
878
879 /// Const access; returns the __const iterator* associated with
880 /// the current leaf.
881 const_reference
882 operator*() const
883 {
884 _GLIBCXX_DEBUG_ASSERT(num_children() == 0);
885 return _CIterator(m_p_nd);
886 }
887
888 /// Metadata access.
889 metadata_const_reference
890 get_metadata() const
891 { return m_p_nd->get_metadata(); }
892
893 /// Returns the number of children in the corresponding node.
894 size_type
895 num_children() const
896 {
897 if (m_p_nd->m_type == leaf_node)
898 return 0;
899 _GLIBCXX_DEBUG_ASSERT(m_p_nd->m_type == i_node);
900 inode_pointer inp = static_cast<inode_pointer>(m_p_nd);
901 return std::distance(inp->begin(), inp->end());
902 }
903
904 /// Returns a __const node __iterator to the corresponding node's
905 /// i-th child.
906 _Node_citer
907 get_child(size_type i) const
908 {
909 _GLIBCXX_DEBUG_ASSERT(m_p_nd->m_type == i_node);
910 inode_pointer inp = static_cast<inode_pointer>(m_p_nd);
911 typename Inode::iterator it = inp->begin();
912 std::advance(it, i);
913 return _Node_citer(*it, m_p_traits);
914 }
915
916 /// Compares content 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 /// Compares content (negatively) to a different iterator object.
922 bool
923 operator!=(const _Node_citer& other) const
924 { return m_p_nd != other.m_p_nd; }
925
926 node_pointer m_p_nd;
927 a_const_pointer m_p_traits;
928 };
929
930
931 /// Node iterator.
932 template<typename Node,
933 typename Leaf,
934 typename Head,
935 typename Inode,
936 typename _CIterator,
937 typename Iterator,
938 typename _Alloc>
939 class _Node_iter
940 : public _Node_citer<Node, Leaf, Head, Inode, _CIterator, Iterator, _Alloc>
941 {
942 private:
943 typedef _Node_citer<Node, Leaf, Head, Inode,
944 _CIterator, Iterator, _Alloc> base_type;
945 typedef typename _Alloc::template rebind<Node> __rebind_n;
946 typedef typename __rebind_n::other::pointer node_pointer;
947 typedef typename base_type::inode_pointer inode_pointer;
948 typedef typename base_type::a_const_pointer a_const_pointer;
949 typedef Iterator iterator;
950
951 public:
952 typedef typename base_type::size_type size_type;
953
954 typedef Iterator value_type;
955 typedef value_type reference;
956 typedef value_type const_reference;
957
958 _Node_iter(node_pointer p_nd = 0, a_const_pointer p_traits = 0)
959 : base_type(p_nd, p_traits)
960 { }
961
962 /// Access; returns the iterator* associated with the current leaf.
963 reference
964 operator*() const
965 {
966 _GLIBCXX_DEBUG_ASSERT(base_type::num_children() == 0);
967 return iterator(base_type::m_p_nd);
968 }
969
970 /// Returns a node __iterator to the corresponding node's i-th child.
971 _Node_iter
972 get_child(size_type i) const
973 {
974 _GLIBCXX_DEBUG_ASSERT(base_type::m_p_nd->m_type == i_node);
975
976 typename Inode::iterator it =
977 static_cast<inode_pointer>(base_type::m_p_nd)->begin();
978
979 std::advance(it, i);
980 return _Node_iter(*it, base_type::m_p_traits);
981 }
982 };
983 };
984
985
986 #define PB_DS_CLASS_T_DEC \
987 template<typename _ATraits, typename Metadata>
988
989 #define PB_DS_CLASS_C_DEC \
990 pat_trie_base::_Inode<_ATraits, Metadata>
991
992 PB_DS_CLASS_T_DEC
993 typename PB_DS_CLASS_C_DEC::__rebind_l
994 PB_DS_CLASS_C_DEC::s_leaf_alloc;
995
996 PB_DS_CLASS_T_DEC
997 typename PB_DS_CLASS_C_DEC::__rebind_in
998 PB_DS_CLASS_C_DEC::s_inode_alloc;
999
1000 PB_DS_CLASS_T_DEC
1001 inline typename PB_DS_CLASS_C_DEC::size_type
1002 PB_DS_CLASS_C_DEC::
1003 get_pref_pos(a_const_iterator b_it, a_const_iterator e_it,
1004 a_const_pointer p_traits) const
1005 {
1006 if (static_cast<std::size_t>(std::distance(b_it, e_it)) <= m_e_ind)
1007 return 0;
1008 std::advance(b_it, m_e_ind);
1009 return 1 + p_traits->e_pos(*b_it);
1010 }
1011
1012 PB_DS_CLASS_T_DEC
1013 PB_DS_CLASS_C_DEC::
1014 _Inode(size_type len, const a_const_iterator it)
1015 : base_type(i_node), m_e_ind(len), m_pref_b_it(it), m_pref_e_it(it)
1016 {
1017 std::advance(m_pref_e_it, m_e_ind);
1018 std::fill(m_a_p_children, m_a_p_children + arr_size,
1019 static_cast<node_pointer>(0));
1020 }
1021
1022 PB_DS_CLASS_T_DEC
1023 void
1024 PB_DS_CLASS_C_DEC::
1025 update_prefixes(a_const_pointer p_traits)
1026 {
1027 node_pointer p_first = *begin();
1028 if (p_first->m_type == leaf_node)
1029 {
1030 leaf_const_pointer p = static_cast<leaf_const_pointer>(p_first);
1031 m_pref_b_it = p_traits->begin(access_traits::extract_key(p->value()));
1032 }
1033 else
1034 {
1035 inode_pointer p = static_cast<inode_pointer>(p_first);
1036 _GLIBCXX_DEBUG_ASSERT(p_first->m_type == i_node);
1037 m_pref_b_it = p->pref_b_it();
1038 }
1039 m_pref_e_it = m_pref_b_it;
1040 std::advance(m_pref_e_it, m_e_ind);
1041 }
1042
1043 PB_DS_CLASS_T_DEC
1044 typename PB_DS_CLASS_C_DEC::const_iterator
1045 PB_DS_CLASS_C_DEC::
1046 begin() const
1047 {
1048 typedef node_pointer_pointer pointer_type;
1049 pointer_type p = const_cast<pointer_type>(m_a_p_children);
1050 return const_iterator(p + get_begin_pos(), p + arr_size);
1051 }
1052
1053 PB_DS_CLASS_T_DEC
1054 typename PB_DS_CLASS_C_DEC::iterator
1055 PB_DS_CLASS_C_DEC::
1056 begin()
1057 {
1058 return iterator(m_a_p_children + get_begin_pos(),
1059 m_a_p_children + arr_size);
1060 }
1061
1062 PB_DS_CLASS_T_DEC
1063 typename PB_DS_CLASS_C_DEC::const_iterator
1064 PB_DS_CLASS_C_DEC::
1065 end() const
1066 {
1067 typedef node_pointer_pointer pointer_type;
1068 pointer_type p = const_cast<pointer_type>(m_a_p_children) + arr_size;
1069 return const_iterator(p, p);
1070 }
1071
1072 PB_DS_CLASS_T_DEC
1073 typename PB_DS_CLASS_C_DEC::iterator
1074 PB_DS_CLASS_C_DEC::
1075 end()
1076 { return iterator(m_a_p_children + arr_size, m_a_p_children + arr_size); }
1077
1078 PB_DS_CLASS_T_DEC
1079 inline typename PB_DS_CLASS_C_DEC::node_pointer
1080 PB_DS_CLASS_C_DEC::
1081 get_child_node(a_const_iterator b_it, a_const_iterator e_it,
1082 a_const_pointer p_traits)
1083 {
1084 const size_type i = get_pref_pos(b_it, e_it, p_traits);
1085 _GLIBCXX_DEBUG_ASSERT(i < arr_size);
1086 return m_a_p_children[i];
1087 }
1088
1089 PB_DS_CLASS_T_DEC
1090 inline typename PB_DS_CLASS_C_DEC::iterator
1091 PB_DS_CLASS_C_DEC::
1092 get_child_it(a_const_iterator b_it, a_const_iterator e_it,
1093 a_const_pointer p_traits)
1094 {
1095 const size_type i = get_pref_pos(b_it, e_it, p_traits);
1096 _GLIBCXX_DEBUG_ASSERT(i < arr_size);
1097 _GLIBCXX_DEBUG_ASSERT(m_a_p_children[i] != 0);
1098 return iterator(m_a_p_children + i, m_a_p_children + i);
1099 }
1100
1101 PB_DS_CLASS_T_DEC
1102 inline typename PB_DS_CLASS_C_DEC::node_const_pointer
1103 PB_DS_CLASS_C_DEC::
1104 get_child_node(a_const_iterator b_it, a_const_iterator e_it,
1105 a_const_pointer p_traits) const
1106 { return const_cast<node_pointer>(get_child_node(b_it, e_it, p_traits)); }
1107
1108 PB_DS_CLASS_T_DEC
1109 typename PB_DS_CLASS_C_DEC::node_pointer
1110 PB_DS_CLASS_C_DEC::
1111 get_lower_bound_child_node(a_const_iterator b_it, a_const_iterator e_it,
1112 size_type checked_ind,
1113 a_const_pointer p_traits)
1114 {
1115 if (!should_be_mine(b_it, e_it, checked_ind, p_traits))
1116 {
1117 if (p_traits->cmp_prefixes(b_it, e_it, m_pref_b_it,
1118 m_pref_e_it, true))
1119 return leftmost_descendant();
1120 return rightmost_descendant();
1121 }
1122
1123 size_type i = get_pref_pos(b_it, e_it, p_traits);
1124 _GLIBCXX_DEBUG_ASSERT(i < arr_size);
1125
1126 if (m_a_p_children[i] != 0)
1127 return m_a_p_children[i];
1128
1129 while (++i < arr_size)
1130 if (m_a_p_children[i] != 0)
1131 {
1132 const node_type& __nt = m_a_p_children[i]->m_type;
1133 node_pointer ret = m_a_p_children[i];
1134
1135 if (__nt == leaf_node)
1136 return ret;
1137
1138 _GLIBCXX_DEBUG_ASSERT(__nt == i_node);
1139 inode_pointer inp = static_cast<inode_pointer>(ret);
1140 return inp->leftmost_descendant();
1141 }
1142
1143 return rightmost_descendant();
1144 }
1145
1146 PB_DS_CLASS_T_DEC
1147 inline typename PB_DS_CLASS_C_DEC::node_pointer
1148 PB_DS_CLASS_C_DEC::
1149 add_child(node_pointer p_nd, a_const_iterator b_it, a_const_iterator e_it,
1150 a_const_pointer p_traits)
1151 {
1152 const size_type i = get_pref_pos(b_it, e_it, p_traits);
1153 _GLIBCXX_DEBUG_ASSERT(i < arr_size);
1154 if (m_a_p_children[i] == 0)
1155 {
1156 m_a_p_children[i] = p_nd;
1157 p_nd->m_p_parent = this;
1158 return p_nd;
1159 }
1160 return m_a_p_children[i];
1161 }
1162
1163 PB_DS_CLASS_T_DEC
1164 typename PB_DS_CLASS_C_DEC::node_const_pointer
1165 PB_DS_CLASS_C_DEC::
1166 get_join_child(node_const_pointer p_nd,
1167 a_const_pointer p_tr) const
1168 {
1169 node_pointer p = const_cast<node_pointer>(p_nd);
1170 return const_cast<inode_pointer>(this)->get_join_child(p, p_tr);
1171 }
1172
1173 PB_DS_CLASS_T_DEC
1174 typename PB_DS_CLASS_C_DEC::node_pointer
1175 PB_DS_CLASS_C_DEC::
1176 get_join_child(node_pointer p_nd, a_const_pointer p_traits)
1177 {
1178 size_type i;
1179 a_const_iterator b_it;
1180 a_const_iterator e_it;
1181 if (p_nd->m_type == leaf_node)
1182 {
1183 leaf_const_pointer p = static_cast<leaf_const_pointer>(p_nd);
1184
1185 typedef typename type_traits::key_const_reference kcr;
1186 kcr r_key = access_traits::extract_key(p->value());
1187 b_it = p_traits->begin(r_key);
1188 e_it = p_traits->end(r_key);
1189 }
1190 else
1191 {
1192 b_it = static_cast<inode_pointer>(p_nd)->pref_b_it();
1193 e_it = static_cast<inode_pointer>(p_nd)->pref_e_it();
1194 }
1195 i = get_pref_pos(b_it, e_it, p_traits);
1196 _GLIBCXX_DEBUG_ASSERT(i < arr_size);
1197 return m_a_p_children[i];
1198 }
1199
1200 PB_DS_CLASS_T_DEC
1201 void
1202 PB_DS_CLASS_C_DEC::
1203 remove_child(node_pointer p_nd)
1204 {
1205 size_type i = 0;
1206 for (; i < arr_size; ++i)
1207 if (m_a_p_children[i] == p_nd)
1208 {
1209 m_a_p_children[i] = 0;
1210 return;
1211 }
1212 _GLIBCXX_DEBUG_ASSERT(i != arr_size);
1213 }
1214
1215 PB_DS_CLASS_T_DEC
1216 void
1217 PB_DS_CLASS_C_DEC::
1218 remove_child(iterator it)
1219 { *it.m_p_p_cur = 0; }
1220
1221 PB_DS_CLASS_T_DEC
1222 void
1223 PB_DS_CLASS_C_DEC::
1224 replace_child(node_pointer p_nd, a_const_iterator b_it,
1225 a_const_iterator e_it,
1226 a_const_pointer p_traits)
1227 {
1228 const size_type i = get_pref_pos(b_it, e_it, p_traits);
1229 _GLIBCXX_DEBUG_ASSERT(i < arr_size);
1230 m_a_p_children[i] = p_nd;
1231 p_nd->m_p_parent = this;
1232 }
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_b_it() const
1238 { return m_pref_b_it; }
1239
1240 PB_DS_CLASS_T_DEC
1241 inline typename PB_DS_CLASS_C_DEC::a_const_iterator
1242 PB_DS_CLASS_C_DEC::
1243 pref_e_it() const
1244 { return m_pref_e_it; }
1245
1246 PB_DS_CLASS_T_DEC
1247 bool
1248 PB_DS_CLASS_C_DEC::
1249 should_be_mine(a_const_iterator b_it, a_const_iterator e_it,
1250 size_type checked_ind,
1251 a_const_pointer p_traits) const
1252 {
1253 if (m_e_ind == 0)
1254 return true;
1255
1256 const size_type num_es = std::distance(b_it, e_it);
1257 if (num_es < m_e_ind)
1258 return false;
1259
1260 a_const_iterator key_b_it = b_it;
1261 std::advance(key_b_it, checked_ind);
1262 a_const_iterator key_e_it = b_it;
1263 std::advance(key_e_it, m_e_ind);
1264
1265 a_const_iterator value_b_it = m_pref_b_it;
1266 std::advance(value_b_it, checked_ind);
1267 a_const_iterator value_e_it = m_pref_b_it;
1268 std::advance(value_e_it, m_e_ind);
1269
1270 return p_traits->equal_prefixes(key_b_it, key_e_it, value_b_it,
1271 value_e_it);
1272 }
1273
1274 PB_DS_CLASS_T_DEC
1275 typename PB_DS_CLASS_C_DEC::leaf_pointer
1276 PB_DS_CLASS_C_DEC::
1277 leftmost_descendant()
1278 {
1279 node_pointer p_pot = *begin();
1280 if (p_pot->m_type == leaf_node)
1281 return (static_cast<leaf_pointer>(p_pot));
1282 _GLIBCXX_DEBUG_ASSERT(p_pot->m_type == i_node);
1283 return static_cast<inode_pointer>(p_pot)->leftmost_descendant();
1284 }
1285
1286 PB_DS_CLASS_T_DEC
1287 typename PB_DS_CLASS_C_DEC::leaf_const_pointer
1288 PB_DS_CLASS_C_DEC::
1289 leftmost_descendant() const
1290 { return const_cast<inode_pointer>(this)->leftmost_descendant(); }
1291
1292 PB_DS_CLASS_T_DEC
1293 typename PB_DS_CLASS_C_DEC::leaf_pointer
1294 PB_DS_CLASS_C_DEC::
1295 rightmost_descendant()
1296 {
1297 const size_type num_children = std::distance(begin(), end());
1298 _GLIBCXX_DEBUG_ASSERT(num_children >= 2);
1299
1300 iterator it = begin();
1301 std::advance(it, num_children - 1);
1302 node_pointer p_pot =* it;
1303 if (p_pot->m_type == leaf_node)
1304 return static_cast<leaf_pointer>(p_pot);
1305 _GLIBCXX_DEBUG_ASSERT(p_pot->m_type == i_node);
1306 return static_cast<inode_pointer>(p_pot)->rightmost_descendant();
1307 }
1308
1309 PB_DS_CLASS_T_DEC
1310 typename PB_DS_CLASS_C_DEC::leaf_const_pointer
1311 PB_DS_CLASS_C_DEC::
1312 rightmost_descendant() const
1313 { return const_cast<inode_pointer>(this)->rightmost_descendant(); }
1314
1315 PB_DS_CLASS_T_DEC
1316 typename PB_DS_CLASS_C_DEC::size_type
1317 PB_DS_CLASS_C_DEC::
1318 get_begin_pos() const
1319 {
1320 size_type i = 0;
1321 for (; i < arr_size && m_a_p_children[i] == 0; ++i)
1322 ;
1323 return i;
1324 }
1325
1326 #ifdef _GLIBCXX_DEBUG
1327 PB_DS_CLASS_T_DEC
1328 typename PB_DS_CLASS_C_DEC::node_debug_info
1329 PB_DS_CLASS_C_DEC::
1330 assert_valid_imp(a_const_pointer p_traits,
1331 const char* __file, int __line) const
1332 {
1333 PB_DS_DEBUG_VERIFY(base_type::m_type == i_node);
1334 PB_DS_DEBUG_VERIFY(static_cast<size_type>(std::distance(pref_b_it(), pref_e_it())) == m_e_ind);
1335 PB_DS_DEBUG_VERIFY(std::distance(begin(), end()) >= 2);
1336
1337 for (typename _Inode::const_iterator it = begin(); it != end(); ++it)
1338 {
1339 node_const_pointer p_nd = *it;
1340 PB_DS_DEBUG_VERIFY(p_nd->m_p_parent == this);
1341 node_debug_info child_ret = p_nd->assert_valid_imp(p_traits,
1342 __file, __line);
1343
1344 PB_DS_DEBUG_VERIFY(static_cast<size_type>(std::distance(child_ret.first, child_ret.second)) >= m_e_ind);
1345 PB_DS_DEBUG_VERIFY(should_be_mine(child_ret.first, child_ret.second, 0, p_traits));
1346 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));
1347 }
1348 return std::make_pair(pref_b_it(), pref_e_it());
1349 }
1350 #endif
1351
1352 #undef PB_DS_CLASS_T_DEC
1353 #undef PB_DS_CLASS_C_DEC
1354 } // namespace detail
1355 } // namespace __gnu_pbds
1356
1357 #endif