1 // -*- C++ -*- 2 3 // Copyright (C) 2005, 2006, 2009, 2011, 2012 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 /** 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 _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 865 /// Metadata type. 866 typedef typename Node::metadata_type metadata_type; 867 868 /// Const metadata reference type. 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 878 /// Subtree valid prefix. 879 std::pair<a_const_iterator, a_const_iterator> 880 valid_prefix() const 881 { return std::make_pair(pref_begin(), pref_end()); } 882 883 /// Const access; returns the __const iterator* associated with 884 /// the current leaf. 885 const_reference 886 operator*() const 887 { 888 _GLIBCXX_DEBUG_ASSERT(num_children() == 0); 889 return _CIterator(m_p_nd); 890 } 891 892 /// Metadata access. 893 metadata_const_reference 894 get_metadata() const 895 { return m_p_nd->get_metadata(); } 896 897 /// Returns the number of children in the corresponding node. 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 908 /// Returns a __const node __iterator to the corresponding node's 909 /// i-th child. 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 920 /// Compares content to a different iterator object. 921 bool 922 operator==(const _Node_citer& other) const 923 { return m_p_nd == other.m_p_nd; } 924 925 /// Compares content (negatively) to a different iterator object. 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 966 /// Access; returns the iterator* associated with the current leaf. 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 974 /// Returns a node __iterator to the corresponding node's i-th child. 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; 1325 for (; i < arr_size && m_a_p_children[i] == 0; ++i) 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 1362