1 // Debugging list implementation -*- C++ -*- 2 3 // Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 4 // Free Software Foundation, Inc. 5 // 6 // This file is part of the GNU ISO C++ Library. This library is free 7 // software; you can redistribute it and/or modify it under the 8 // terms of the GNU General Public License as published by the 9 // Free Software Foundation; either version 3, or (at your option) 10 // any later version. 11 12 // This library is distributed in the hope that it will be useful, 13 // but WITHOUT ANY WARRANTY; without even the implied warranty of 14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 // GNU General Public License for more details. 16 17 // Under Section 7 of GPL version 3, you are granted additional 18 // permissions described in the GCC Runtime Library Exception, version 19 // 3.1, as published by the Free Software Foundation. 20 21 // You should have received a copy of the GNU General Public License and 22 // a copy of the GCC Runtime Library Exception along with this program; 23 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 24 // <http://www.gnu.org/licenses/>. 25 26 /** @file debug/list 27 * This file is a GNU debug extension to the Standard C++ Library. 28 */ 29 30 #ifndef _GLIBCXX_DEBUG_LIST 31 #define _GLIBCXX_DEBUG_LIST 1 32 33 #include <list> 34 #include <debug/safe_sequence.h> 35 #include <debug/safe_iterator.h> 36 37 namespace std _GLIBCXX_VISIBILITY(default) 38 { 39 namespace __debug 40 { 41 /// Class std::list with safety/checking/debug instrumentation. 42 template<typename _Tp, typename _Allocator = std::allocator<_Tp> > 43 class list 44 : public _GLIBCXX_STD_C::list<_Tp, _Allocator>, 45 public __gnu_debug::_Safe_sequence<list<_Tp, _Allocator> > 46 { 47 typedef _GLIBCXX_STD_C::list<_Tp, _Allocator> _Base; 48 typedef __gnu_debug::_Safe_sequence<list> _Safe_base; 49 50 typedef typename _Base::iterator _Base_iterator; 51 typedef typename _Base::const_iterator _Base_const_iterator; 52 typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal; 53 typedef __gnu_debug::_Not_equal_to<_Base_const_iterator> _Not_equal; 54 public: 55 typedef typename _Base::reference reference; 56 typedef typename _Base::const_reference const_reference; 57 58 typedef __gnu_debug::_Safe_iterator<_Base_iterator, list> 59 iterator; 60 typedef __gnu_debug::_Safe_iterator<_Base_const_iterator, list> 61 const_iterator; 62 63 typedef typename _Base::size_type size_type; 64 typedef typename _Base::difference_type difference_type; 65 66 typedef _Tp value_type; 67 typedef _Allocator allocator_type; 68 typedef typename _Base::pointer pointer; 69 typedef typename _Base::const_pointer const_pointer; 70 typedef std::reverse_iterator<iterator> reverse_iterator; 71 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 72 73 // 23.2.2.1 construct/copy/destroy: 74 explicit 75 list(const _Allocator& __a = _Allocator()) 76 : _Base(__a) { } 77 78 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 79 explicit 80 list(size_type __n) 81 : _Base(__n) { } 82 83 list(size_type __n, const _Tp& __value, 84 const _Allocator& __a = _Allocator()) 85 : _Base(__n, __value, __a) { } 86 #else 87 explicit 88 list(size_type __n, const _Tp& __value = _Tp(), 89 const _Allocator& __a = _Allocator()) 90 : _Base(__n, __value, __a) { } 91 #endif 92 93 template<class _InputIterator> 94 list(_InputIterator __first, _InputIterator __last, 95 const _Allocator& __a = _Allocator()) 96 : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first, 97 __last)), 98 __gnu_debug::__base(__last), __a) 99 { } 100 101 102 list(const list& __x) 103 : _Base(__x), _Safe_base() { } 104 105 list(const _Base& __x) 106 : _Base(__x), _Safe_base() { } 107 108 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 109 list(list&& __x) 110 : _Base(std::move(__x)), _Safe_base() 111 { this->_M_swap(__x); } 112 113 list(initializer_list<value_type> __l, 114 const allocator_type& __a = allocator_type()) 115 : _Base(__l, __a), _Safe_base() { } 116 #endif 117 118 ~list() { } 119 120 list& 121 operator=(const list& __x) 122 { 123 static_cast<_Base&>(*this) = __x; 124 this->_M_invalidate_all(); 125 return *this; 126 } 127 128 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 129 list& 130 operator=(list&& __x) 131 { 132 // NB: DR 1204. 133 // NB: DR 675. 134 clear(); 135 swap(__x); 136 return *this; 137 } 138 139 list& 140 operator=(initializer_list<value_type> __l) 141 { 142 static_cast<_Base&>(*this) = __l; 143 this->_M_invalidate_all(); 144 return *this; 145 } 146 147 void 148 assign(initializer_list<value_type> __l) 149 { 150 _Base::assign(__l); 151 this->_M_invalidate_all(); 152 } 153 #endif 154 155 template<class _InputIterator> 156 void 157 assign(_InputIterator __first, _InputIterator __last) 158 { 159 __glibcxx_check_valid_range(__first, __last); 160 _Base::assign(__gnu_debug::__base(__first), 161 __gnu_debug::__base(__last)); 162 this->_M_invalidate_all(); 163 } 164 165 void 166 assign(size_type __n, const _Tp& __t) 167 { 168 _Base::assign(__n, __t); 169 this->_M_invalidate_all(); 170 } 171 172 using _Base::get_allocator; 173 174 // iterators: 175 iterator 176 begin() 177 { return iterator(_Base::begin(), this); } 178 179 const_iterator 180 begin() const 181 { return const_iterator(_Base::begin(), this); } 182 183 iterator 184 end() 185 { return iterator(_Base::end(), this); } 186 187 const_iterator 188 end() const 189 { return const_iterator(_Base::end(), this); } 190 191 reverse_iterator 192 rbegin() 193 { return reverse_iterator(end()); } 194 195 const_reverse_iterator 196 rbegin() const 197 { return const_reverse_iterator(end()); } 198 199 reverse_iterator 200 rend() 201 { return reverse_iterator(begin()); } 202 203 const_reverse_iterator 204 rend() const 205 { return const_reverse_iterator(begin()); } 206 207 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 208 const_iterator 209 cbegin() const 210 { return const_iterator(_Base::begin(), this); } 211 212 const_iterator 213 cend() const 214 { return const_iterator(_Base::end(), this); } 215 216 const_reverse_iterator 217 crbegin() const 218 { return const_reverse_iterator(end()); } 219 220 const_reverse_iterator 221 crend() const 222 { return const_reverse_iterator(begin()); } 223 #endif 224 225 // 23.2.2.2 capacity: 226 using _Base::empty; 227 using _Base::size; 228 using _Base::max_size; 229 230 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 231 void 232 resize(size_type __sz) 233 { 234 this->_M_detach_singular(); 235 236 // if __sz < size(), invalidate all iterators in [begin+__sz, end()) 237 _Base_iterator __victim = _Base::begin(); 238 _Base_iterator __end = _Base::end(); 239 for (size_type __i = __sz; __victim != __end && __i > 0; --__i) 240 ++__victim; 241 242 for (; __victim != __end; ++__victim) 243 { 244 this->_M_invalidate_if(_Equal(__victim)); 245 } 246 247 __try 248 { 249 _Base::resize(__sz); 250 } 251 __catch(...) 252 { 253 this->_M_revalidate_singular(); 254 __throw_exception_again; 255 } 256 } 257 258 void 259 resize(size_type __sz, const _Tp& __c) 260 { 261 this->_M_detach_singular(); 262 263 // if __sz < size(), invalidate all iterators in [begin+__sz, end()) 264 _Base_iterator __victim = _Base::begin(); 265 _Base_iterator __end = _Base::end(); 266 for (size_type __i = __sz; __victim != __end && __i > 0; --__i) 267 ++__victim; 268 269 for (; __victim != __end; ++__victim) 270 { 271 this->_M_invalidate_if(_Equal(__victim)); 272 } 273 274 __try 275 { 276 _Base::resize(__sz, __c); 277 } 278 __catch(...) 279 { 280 this->_M_revalidate_singular(); 281 __throw_exception_again; 282 } 283 } 284 #else 285 void 286 resize(size_type __sz, _Tp __c = _Tp()) 287 { 288 this->_M_detach_singular(); 289 290 // if __sz < size(), invalidate all iterators in [begin+__sz, end()) 291 _Base_iterator __victim = _Base::begin(); 292 _Base_iterator __end = _Base::end(); 293 for (size_type __i = __sz; __victim != __end && __i > 0; --__i) 294 ++__victim; 295 296 for (; __victim != __end; ++__victim) 297 { 298 this->_M_invalidate_if(_Equal(__victim)); 299 } 300 301 __try 302 { 303 _Base::resize(__sz, __c); 304 } 305 __catch(...) 306 { 307 this->_M_revalidate_singular(); 308 __throw_exception_again; 309 } 310 } 311 #endif 312 313 // element access: 314 reference 315 front() 316 { 317 __glibcxx_check_nonempty(); 318 return _Base::front(); 319 } 320 321 const_reference 322 front() const 323 { 324 __glibcxx_check_nonempty(); 325 return _Base::front(); 326 } 327 328 reference 329 back() 330 { 331 __glibcxx_check_nonempty(); 332 return _Base::back(); 333 } 334 335 const_reference 336 back() const 337 { 338 __glibcxx_check_nonempty(); 339 return _Base::back(); 340 } 341 342 // 23.2.2.3 modifiers: 343 using _Base::push_front; 344 345 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 346 using _Base::emplace_front; 347 #endif 348 349 void 350 pop_front() 351 { 352 __glibcxx_check_nonempty(); 353 this->_M_invalidate_if(_Equal(_Base::begin())); 354 _Base::pop_front(); 355 } 356 357 using _Base::push_back; 358 359 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 360 using _Base::emplace_back; 361 #endif 362 363 void 364 pop_back() 365 { 366 __glibcxx_check_nonempty(); 367 this->_M_invalidate_if(_Equal(--_Base::end())); 368 _Base::pop_back(); 369 } 370 371 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 372 template<typename... _Args> 373 iterator 374 emplace(iterator __position, _Args&&... __args) 375 { 376 __glibcxx_check_insert(__position); 377 return iterator(_Base::emplace(__position.base(), 378 std::forward<_Args>(__args)...), this); 379 } 380 #endif 381 382 iterator 383 insert(iterator __position, const _Tp& __x) 384 { 385 __glibcxx_check_insert(__position); 386 return iterator(_Base::insert(__position.base(), __x), this); 387 } 388 389 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 390 iterator 391 insert(iterator __position, _Tp&& __x) 392 { return emplace(__position, std::move(__x)); } 393 394 void 395 insert(iterator __p, initializer_list<value_type> __l) 396 { 397 __glibcxx_check_insert(__p); 398 _Base::insert(__p, __l); 399 } 400 #endif 401 402 void 403 insert(iterator __position, size_type __n, const _Tp& __x) 404 { 405 __glibcxx_check_insert(__position); 406 _Base::insert(__position.base(), __n, __x); 407 } 408 409 template<class _InputIterator> 410 void 411 insert(iterator __position, _InputIterator __first, 412 _InputIterator __last) 413 { 414 __glibcxx_check_insert_range(__position, __first, __last); 415 _Base::insert(__position.base(), __gnu_debug::__base(__first), 416 __gnu_debug::__base(__last)); 417 } 418 419 private: 420 _Base_iterator 421 _M_erase(_Base_iterator __position) 422 { 423 this->_M_invalidate_if(_Equal(__position)); 424 return _Base::erase(__position); 425 } 426 public: 427 iterator 428 erase(iterator __position) 429 { 430 __glibcxx_check_erase(__position); 431 return iterator(_M_erase(__position.base()), this); 432 } 433 434 iterator 435 erase(iterator __position, iterator __last) 436 { 437 // _GLIBCXX_RESOLVE_LIB_DEFECTS 438 // 151. can't currently clear() empty container 439 __glibcxx_check_erase_range(__position, __last); 440 for (_Base_iterator __victim = __position.base(); 441 __victim != __last.base(); ++__victim) 442 { 443 _GLIBCXX_DEBUG_VERIFY(__victim != _Base::end(), 444 _M_message(__gnu_debug::__msg_valid_range) 445 ._M_iterator(__position, "position") 446 ._M_iterator(__last, "last")); 447 this->_M_invalidate_if(_Equal(__victim)); 448 } 449 return iterator(_Base::erase(__position.base(), __last.base()), this); 450 } 451 452 void 453 swap(list& __x) 454 { 455 _Base::swap(__x); 456 this->_M_swap(__x); 457 } 458 459 void 460 clear() 461 { 462 _Base::clear(); 463 this->_M_invalidate_all(); 464 } 465 466 // 23.2.2.4 list operations: 467 void 468 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 469 splice(iterator __position, list&& __x) 470 #else 471 splice(iterator __position, list& __x) 472 #endif 473 { 474 _GLIBCXX_DEBUG_VERIFY(&__x != this, 475 _M_message(__gnu_debug::__msg_self_splice) 476 ._M_sequence(*this, "this")); 477 this->_M_transfer_from_if(__x, _Not_equal(__x._M_base().end())); 478 _Base::splice(__position.base(), _GLIBCXX_MOVE(__x._M_base())); 479 } 480 481 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 482 void 483 splice(iterator __position, list& __x) 484 { splice(__position, std::move(__x)); } 485 #endif 486 487 void 488 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 489 splice(iterator __position, list&& __x, iterator __i) 490 #else 491 splice(iterator __position, list& __x, iterator __i) 492 #endif 493 { 494 __glibcxx_check_insert(__position); 495 496 // We used to perform the splice_alloc check: not anymore, redundant 497 // after implementing the relevant bits of N1599. 498 499 _GLIBCXX_DEBUG_VERIFY(__i._M_dereferenceable(), 500 _M_message(__gnu_debug::__msg_splice_bad) 501 ._M_iterator(__i, "__i")); 502 _GLIBCXX_DEBUG_VERIFY(__i._M_attached_to(&__x), 503 _M_message(__gnu_debug::__msg_splice_other) 504 ._M_iterator(__i, "__i")._M_sequence(__x, "__x")); 505 506 // _GLIBCXX_RESOLVE_LIB_DEFECTS 507 // 250. splicing invalidates iterators 508 this->_M_transfer_from_if(__x, _Equal(__i.base())); 509 _Base::splice(__position.base(), _GLIBCXX_MOVE(__x._M_base()), 510 __i.base()); 511 } 512 513 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 514 void 515 splice(iterator __position, list& __x, iterator __i) 516 { splice(__position, std::move(__x), __i); } 517 #endif 518 519 void 520 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 521 splice(iterator __position, list&& __x, iterator __first, 522 iterator __last) 523 #else 524 splice(iterator __position, list& __x, iterator __first, 525 iterator __last) 526 #endif 527 { 528 __glibcxx_check_insert(__position); 529 __glibcxx_check_valid_range(__first, __last); 530 _GLIBCXX_DEBUG_VERIFY(__first._M_attached_to(&__x), 531 _M_message(__gnu_debug::__msg_splice_other) 532 ._M_sequence(__x, "x") 533 ._M_iterator(__first, "first")); 534 535 // We used to perform the splice_alloc check: not anymore, redundant 536 // after implementing the relevant bits of N1599. 537 538 for (_Base_iterator __tmp = __first.base(); 539 __tmp != __last.base(); ++__tmp) 540 { 541 _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::end(), 542 _M_message(__gnu_debug::__msg_valid_range) 543 ._M_iterator(__first, "first") 544 ._M_iterator(__last, "last")); 545 _GLIBCXX_DEBUG_VERIFY(&__x != this || __tmp != __position, 546 _M_message(__gnu_debug::__msg_splice_overlap) 547 ._M_iterator(__tmp, "position") 548 ._M_iterator(__first, "first") 549 ._M_iterator(__last, "last")); 550 // _GLIBCXX_RESOLVE_LIB_DEFECTS 551 // 250. splicing invalidates iterators 552 this->_M_transfer_from_if(__x, _Equal(__tmp)); 553 } 554 555 _Base::splice(__position.base(), _GLIBCXX_MOVE(__x._M_base()), 556 __first.base(), __last.base()); 557 } 558 559 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 560 void 561 splice(iterator __position, list& __x, iterator __first, iterator __last) 562 { splice(__position, std::move(__x), __first, __last); } 563 #endif 564 565 void 566 remove(const _Tp& __value) 567 { 568 for (_Base_iterator __x = _Base::begin(); __x != _Base::end(); ) 569 { 570 if (*__x == __value) 571 __x = _M_erase(__x); 572 else 573 ++__x; 574 } 575 } 576 577 template<class _Predicate> 578 void 579 remove_if(_Predicate __pred) 580 { 581 for (_Base_iterator __x = _Base::begin(); __x != _Base::end(); ) 582 { 583 if (__pred(*__x)) 584 __x = _M_erase(__x); 585 else 586 ++__x; 587 } 588 } 589 590 void 591 unique() 592 { 593 _Base_iterator __first = _Base::begin(); 594 _Base_iterator __last = _Base::end(); 595 if (__first == __last) 596 return; 597 _Base_iterator __next = __first; ++__next; 598 while (__next != __last) 599 { 600 if (*__first == *__next) 601 __next = _M_erase(__next); 602 else 603 __first = __next++; 604 } 605 } 606 607 template<class _BinaryPredicate> 608 void 609 unique(_BinaryPredicate __binary_pred) 610 { 611 _Base_iterator __first = _Base::begin(); 612 _Base_iterator __last = _Base::end(); 613 if (__first == __last) 614 return; 615 _Base_iterator __next = __first; ++__next; 616 while (__next != __last) 617 { 618 if (__binary_pred(*__first, *__next)) 619 __next = _M_erase(__next); 620 else 621 __first = __next++; 622 } 623 } 624 625 void 626 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 627 merge(list&& __x) 628 #else 629 merge(list& __x) 630 #endif 631 { 632 // _GLIBCXX_RESOLVE_LIB_DEFECTS 633 // 300. list::merge() specification incomplete 634 if (this != &__x) 635 { 636 __glibcxx_check_sorted(_Base::begin(), _Base::end()); 637 __glibcxx_check_sorted(__x.begin().base(), __x.end().base()); 638 this->_M_transfer_from_if(__x, _Not_equal(__x._M_base().end())); 639 _Base::merge(_GLIBCXX_MOVE(__x._M_base())); 640 } 641 } 642 643 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 644 void 645 merge(list& __x) 646 { merge(std::move(__x)); } 647 #endif 648 649 template<class _Compare> 650 void 651 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 652 merge(list&& __x, _Compare __comp) 653 #else 654 merge(list& __x, _Compare __comp) 655 #endif 656 { 657 // _GLIBCXX_RESOLVE_LIB_DEFECTS 658 // 300. list::merge() specification incomplete 659 if (this != &__x) 660 { 661 __glibcxx_check_sorted_pred(_Base::begin(), _Base::end(), 662 __comp); 663 __glibcxx_check_sorted_pred(__x.begin().base(), __x.end().base(), 664 __comp); 665 this->_M_transfer_from_if(__x, _Not_equal(__x._M_base().end())); 666 _Base::merge(_GLIBCXX_MOVE(__x._M_base()), __comp); 667 } 668 } 669 670 #ifdef __GXX_EXPERIMENTAL_CXX0X__ 671 template<typename _Compare> 672 void 673 merge(list& __x, _Compare __comp) 674 { merge(std::move(__x), __comp); } 675 #endif 676 677 void 678 sort() { _Base::sort(); } 679 680 template<typename _StrictWeakOrdering> 681 void 682 sort(_StrictWeakOrdering __pred) { _Base::sort(__pred); } 683 684 using _Base::reverse; 685 686 _Base& 687 _M_base() { return *this; } 688 689 const _Base& 690 _M_base() const { return *this; } 691 692 private: 693 void 694 _M_invalidate_all() 695 { 696 this->_M_invalidate_if(_Not_equal(_Base::end())); 697 } 698 }; 699 700 template<typename _Tp, typename _Alloc> 701 inline bool 702 operator==(const list<_Tp, _Alloc>& __lhs, 703 const list<_Tp, _Alloc>& __rhs) 704 { return __lhs._M_base() == __rhs._M_base(); } 705 706 template<typename _Tp, typename _Alloc> 707 inline bool 708 operator!=(const list<_Tp, _Alloc>& __lhs, 709 const list<_Tp, _Alloc>& __rhs) 710 { return __lhs._M_base() != __rhs._M_base(); } 711 712 template<typename _Tp, typename _Alloc> 713 inline bool 714 operator<(const list<_Tp, _Alloc>& __lhs, 715 const list<_Tp, _Alloc>& __rhs) 716 { return __lhs._M_base() < __rhs._M_base(); } 717 718 template<typename _Tp, typename _Alloc> 719 inline bool 720 operator<=(const list<_Tp, _Alloc>& __lhs, 721 const list<_Tp, _Alloc>& __rhs) 722 { return __lhs._M_base() <= __rhs._M_base(); } 723 724 template<typename _Tp, typename _Alloc> 725 inline bool 726 operator>=(const list<_Tp, _Alloc>& __lhs, 727 const list<_Tp, _Alloc>& __rhs) 728 { return __lhs._M_base() >= __rhs._M_base(); } 729 730 template<typename _Tp, typename _Alloc> 731 inline bool 732 operator>(const list<_Tp, _Alloc>& __lhs, 733 const list<_Tp, _Alloc>& __rhs) 734 { return __lhs._M_base() > __rhs._M_base(); } 735 736 template<typename _Tp, typename _Alloc> 737 inline void 738 swap(list<_Tp, _Alloc>& __lhs, list<_Tp, _Alloc>& __rhs) 739 { __lhs.swap(__rhs); } 740 741 } // namespace __debug 742 } // namespace std 743 744 #endif 745