1 // Safe iterator implementation -*- C++ -*- 2 3 // Copyright (C) 2003-2021 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 7 // terms of the GNU General Public License as published by the 8 // Free Software Foundation; either version 3, or (at your option) 9 // any later version. 10 11 // This library is distributed in the hope that it will be useful, 12 // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 // GNU 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 /** @file debug/safe_iterator.h 26 * This file is a GNU debug extension to the Standard C++ Library. 27 */ 28 29 #ifndef _GLIBCXX_DEBUG_SAFE_ITERATOR_H 30 #define _GLIBCXX_DEBUG_SAFE_ITERATOR_H 1 31 32 #include <debug/assertions.h> 33 #include <debug/macros.h> 34 #include <debug/functions.h> 35 #include <debug/safe_base.h> 36 #include <bits/stl_pair.h> 37 #include <ext/type_traits.h> 38 #if __cplusplus > 201703L 39 # include <compare> 40 #endif 41 42 #define _GLIBCXX_DEBUG_VERIFY_OPERANDS(_Lhs, _Rhs, _BadMsgId, _DiffMsgId) \ 43 _GLIBCXX_DEBUG_VERIFY(!_Lhs._M_singular() && !_Rhs._M_singular() \ 44 || (_Lhs.base() == _Iterator() \ 45 && _Rhs.base() == _Iterator()), \ 46 _M_message(_BadMsgId) \ 47 ._M_iterator(_Lhs, #_Lhs) \ 48 ._M_iterator(_Rhs, #_Rhs)); \ 49 _GLIBCXX_DEBUG_VERIFY(_Lhs._M_can_compare(_Rhs), \ 50 _M_message(_DiffMsgId) \ 51 ._M_iterator(_Lhs, #_Lhs) \ 52 ._M_iterator(_Rhs, #_Rhs)) 53 54 #define _GLIBCXX_DEBUG_VERIFY_EQ_OPERANDS(_Lhs, _Rhs) \ 55 _GLIBCXX_DEBUG_VERIFY_OPERANDS(_Lhs, _Rhs, __msg_iter_compare_bad, \ 56 __msg_compare_different) 57 58 #define _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(_Lhs, _Rhs) \ 59 _GLIBCXX_DEBUG_VERIFY_OPERANDS(_Lhs, _Rhs, __msg_iter_order_bad, \ 60 __msg_order_different) 61 62 #define _GLIBCXX_DEBUG_VERIFY_DIST_OPERANDS(_Lhs, _Rhs) \ 63 _GLIBCXX_DEBUG_VERIFY_OPERANDS(_Lhs, _Rhs, __msg_distance_bad, \ 64 __msg_distance_different) 65 66 namespace __gnu_debug 67 { 68 /** Helper struct to deal with sequence offering a before_begin 69 * iterator. 70 **/ 71 template<typename _Sequence> 72 struct _BeforeBeginHelper 73 { 74 template<typename _Iterator, typename _Category> 75 static bool _S_Is_BeforeBeginHelper76 _S_Is(const _Safe_iterator<_Iterator, _Sequence, _Category>&) 77 { return false; } 78 79 template<typename _Iterator, typename _Category> 80 static bool _S_Is_Beginnest_BeforeBeginHelper81 _S_Is_Beginnest(const _Safe_iterator<_Iterator, _Sequence, _Category>& __it) 82 { return __it.base() == __it._M_get_sequence()->_M_base().begin(); } 83 }; 84 85 /** Sequence traits giving the size of a container if possible. */ 86 template<typename _Sequence> 87 struct _Sequence_traits 88 { 89 typedef _Distance_traits<typename _Sequence::iterator> _DistTraits; 90 91 static typename _DistTraits::__type _S_size_Sequence_traits92 _S_size(const _Sequence& __seq) 93 { return std::make_pair(__seq.size(), __dp_exact); } 94 }; 95 96 /** \brief Safe iterator wrapper. 97 * 98 * The class template %_Safe_iterator is a wrapper around an 99 * iterator that tracks the iterator's movement among sequences and 100 * checks that operations performed on the "safe" iterator are 101 * legal. In additional to the basic iterator operations (which are 102 * validated, and then passed to the underlying iterator), 103 * %_Safe_iterator has member functions for iterator invalidation, 104 * attaching/detaching the iterator from sequences, and querying 105 * the iterator's state. 106 * 107 * Note that _Iterator must be the first base class so that it gets 108 * initialized before the iterator is being attached to the container's list 109 * of iterators and it is being detached before _Iterator get 110 * destroyed. Otherwise it would result in a data race. 111 */ 112 template<typename _Iterator, typename _Sequence, typename _Category 113 = typename std::iterator_traits<_Iterator>::iterator_category> 114 class _Safe_iterator 115 : private _Iterator, 116 public _Safe_iterator_base 117 { 118 typedef _Iterator _Iter_base; 119 typedef _Safe_iterator_base _Safe_base; 120 121 typedef std::iterator_traits<_Iterator> _Traits; 122 123 protected: 124 typedef std::__are_same<typename _Sequence::_Base::const_iterator, 125 _Iterator> _IsConstant; 126 127 typedef typename __gnu_cxx::__conditional_type< 128 _IsConstant::__value, 129 typename _Sequence::_Base::iterator, 130 typename _Sequence::_Base::const_iterator>::__type _OtherIterator; 131 132 struct _Attach_single 133 { }; 134 _Safe_iterator(_Iterator __i,_Safe_sequence_base * __seq,_Attach_single)135 _Safe_iterator(_Iterator __i, _Safe_sequence_base* __seq, _Attach_single) 136 _GLIBCXX_NOEXCEPT 137 : _Iter_base(__i) 138 { _M_attach_single(__seq); } 139 140 public: 141 typedef _Iterator iterator_type; 142 typedef typename _Traits::iterator_category iterator_category; 143 typedef typename _Traits::value_type value_type; 144 typedef typename _Traits::difference_type difference_type; 145 typedef typename _Traits::reference reference; 146 typedef typename _Traits::pointer pointer; 147 148 #if __cplusplus > 201703L && __cpp_lib_concepts 149 using iterator_concept = std::__detail::__iter_concept<_Iterator>; 150 #endif 151 152 /// @post the iterator is singular and unattached _Safe_iterator()153 _Safe_iterator() _GLIBCXX_NOEXCEPT : _Iter_base() { } 154 155 /** 156 * @brief Safe iterator construction from an unsafe iterator and 157 * its sequence. 158 * 159 * @pre @p seq is not NULL 160 * @post this is not singular 161 */ _Safe_iterator(_Iterator __i,const _Safe_sequence_base * __seq)162 _Safe_iterator(_Iterator __i, const _Safe_sequence_base* __seq) 163 _GLIBCXX_NOEXCEPT 164 : _Iter_base(__i), _Safe_base(__seq, _S_constant()) 165 { 166 _GLIBCXX_DEBUG_VERIFY(!this->_M_singular(), 167 _M_message(__msg_init_singular) 168 ._M_iterator(*this, "this")); 169 } 170 171 /** 172 * @brief Copy construction. 173 */ _Safe_iterator(const _Safe_iterator & __x)174 _Safe_iterator(const _Safe_iterator& __x) _GLIBCXX_NOEXCEPT 175 : _Iter_base(__x.base()), _Safe_base() 176 { 177 // _GLIBCXX_RESOLVE_LIB_DEFECTS 178 // DR 408. Is vector<reverse_iterator<char*> > forbidden? 179 _GLIBCXX_DEBUG_VERIFY(!__x._M_singular() 180 || __x.base() == _Iterator(), 181 _M_message(__msg_init_copy_singular) 182 ._M_iterator(*this, "this") 183 ._M_iterator(__x, "other")); 184 _M_attach(__x._M_sequence); 185 } 186 187 #if __cplusplus >= 201103L 188 /** 189 * @brief Move construction. 190 * @post __x is singular and unattached 191 */ _Safe_iterator(_Safe_iterator && __x)192 _Safe_iterator(_Safe_iterator&& __x) noexcept 193 : _Iter_base() 194 { 195 _GLIBCXX_DEBUG_VERIFY(!__x._M_singular() 196 || __x.base() == _Iterator(), 197 _M_message(__msg_init_copy_singular) 198 ._M_iterator(*this, "this") 199 ._M_iterator(__x, "other")); 200 _Safe_sequence_base* __seq = __x._M_sequence; 201 __x._M_detach(); 202 std::swap(base(), __x.base()); 203 _M_attach(__seq); 204 } 205 #endif 206 207 /** 208 * @brief Converting constructor from a mutable iterator to a 209 * constant iterator. 210 */ 211 template<typename _MutableIterator> _Safe_iterator(const _Safe_iterator<_MutableIterator,_Sequence,typename __gnu_cxx::__enable_if<_IsConstant::__value && std::__are_same<_MutableIterator,_OtherIterator>::__value,_Category>::__type> & __x)212 _Safe_iterator( 213 const _Safe_iterator<_MutableIterator, _Sequence, 214 typename __gnu_cxx::__enable_if<_IsConstant::__value && 215 std::__are_same<_MutableIterator, _OtherIterator>::__value, 216 _Category>::__type>& __x) 217 _GLIBCXX_NOEXCEPT 218 : _Iter_base(__x.base()) 219 { 220 // _GLIBCXX_RESOLVE_LIB_DEFECTS 221 // DR 408. Is vector<reverse_iterator<char*> > forbidden? 222 _GLIBCXX_DEBUG_VERIFY(!__x._M_singular() 223 || __x.base() == _MutableIterator(), 224 _M_message(__msg_init_const_singular) 225 ._M_iterator(*this, "this") 226 ._M_iterator(__x, "other")); 227 _M_attach(__x._M_sequence); 228 } 229 230 /** 231 * @brief Copy assignment. 232 */ 233 _Safe_iterator& 234 operator=(const _Safe_iterator& __x) _GLIBCXX_NOEXCEPT 235 { 236 // _GLIBCXX_RESOLVE_LIB_DEFECTS 237 // DR 408. Is vector<reverse_iterator<char*> > forbidden? 238 _GLIBCXX_DEBUG_VERIFY(!__x._M_singular() 239 || __x.base() == _Iterator(), 240 _M_message(__msg_copy_singular) 241 ._M_iterator(*this, "this") 242 ._M_iterator(__x, "other")); 243 244 if (this->_M_sequence && this->_M_sequence == __x._M_sequence) 245 { 246 __gnu_cxx::__scoped_lock __l(this->_M_get_mutex()); 247 base() = __x.base(); 248 _M_version = __x._M_sequence->_M_version; 249 } 250 else 251 { 252 _M_detach(); 253 base() = __x.base(); 254 _M_attach(__x._M_sequence); 255 } 256 257 return *this; 258 } 259 260 #if __cplusplus >= 201103L 261 /** 262 * @brief Move assignment. 263 * @post __x is singular and unattached 264 */ 265 _Safe_iterator& 266 operator=(_Safe_iterator&& __x) noexcept 267 { 268 _GLIBCXX_DEBUG_VERIFY(!__x._M_singular() 269 || __x.base() == _Iterator(), 270 _M_message(__msg_copy_singular) 271 ._M_iterator(*this, "this") 272 ._M_iterator(__x, "other")); 273 274 if (std::__addressof(__x) == this) 275 return *this; 276 277 if (this->_M_sequence && this->_M_sequence == __x._M_sequence) 278 { 279 __gnu_cxx::__scoped_lock __l(this->_M_get_mutex()); 280 base() = __x.base(); 281 _M_version = __x._M_sequence->_M_version; 282 } 283 else 284 { 285 _M_detach(); 286 base() = __x.base(); 287 _M_attach(__x._M_sequence); 288 } 289 290 __x._M_detach(); 291 __x.base() = _Iterator(); 292 return *this; 293 } 294 #endif 295 296 /** 297 * @brief Iterator dereference. 298 * @pre iterator is dereferenceable 299 */ 300 reference 301 operator*() const _GLIBCXX_NOEXCEPT 302 { 303 _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(), 304 _M_message(__msg_bad_deref) 305 ._M_iterator(*this, "this")); 306 return *base(); 307 } 308 309 /** 310 * @brief Iterator dereference. 311 * @pre iterator is dereferenceable 312 */ 313 pointer 314 operator->() const _GLIBCXX_NOEXCEPT 315 { 316 _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(), 317 _M_message(__msg_bad_deref) 318 ._M_iterator(*this, "this")); 319 return base().operator->(); 320 } 321 322 // ------ Input iterator requirements ------ 323 /** 324 * @brief Iterator preincrement 325 * @pre iterator is incrementable 326 */ 327 _Safe_iterator& 328 operator++() _GLIBCXX_NOEXCEPT 329 { 330 _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(), 331 _M_message(__msg_bad_inc) 332 ._M_iterator(*this, "this")); 333 __gnu_cxx::__scoped_lock __l(this->_M_get_mutex()); 334 ++base(); 335 return *this; 336 } 337 338 /** 339 * @brief Iterator postincrement 340 * @pre iterator is incrementable 341 */ 342 _Safe_iterator 343 operator++(int) _GLIBCXX_NOEXCEPT 344 { 345 _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(), 346 _M_message(__msg_bad_inc) 347 ._M_iterator(*this, "this")); 348 __gnu_cxx::__scoped_lock __l(this->_M_get_mutex()); 349 return _Safe_iterator(base()++, this->_M_sequence, _Attach_single()); 350 } 351 352 // ------ Utilities ------ 353 354 /// Determine if this is a constant iterator. 355 static _GLIBCXX_CONSTEXPR bool _S_constant()356 _S_constant() 357 { return _IsConstant::__value; } 358 359 /** 360 * @brief Return the underlying iterator 361 */ 362 _Iterator& base()363 base() _GLIBCXX_NOEXCEPT { return *this; } 364 365 const _Iterator& base()366 base() const _GLIBCXX_NOEXCEPT { return *this; } 367 368 /** 369 * @brief Conversion to underlying non-debug iterator to allow 370 * better interaction with non-debug containers. 371 */ _Iterator()372 operator _Iterator() const _GLIBCXX_NOEXCEPT { return *this; } 373 374 /** Attach iterator to the given sequence. */ 375 void _M_attach(_Safe_sequence_base * __seq)376 _M_attach(_Safe_sequence_base* __seq) 377 { _Safe_base::_M_attach(__seq, _S_constant()); } 378 379 /** Likewise, but not thread-safe. */ 380 void _M_attach_single(_Safe_sequence_base * __seq)381 _M_attach_single(_Safe_sequence_base* __seq) 382 { _Safe_base::_M_attach_single(__seq, _S_constant()); } 383 384 /// Is the iterator dereferenceable? 385 bool _M_dereferenceable()386 _M_dereferenceable() const 387 { return !this->_M_singular() && !_M_is_end() && !_M_is_before_begin(); } 388 389 /// Is the iterator before a dereferenceable one? 390 bool _M_before_dereferenceable()391 _M_before_dereferenceable() const 392 { 393 if (this->_M_incrementable()) 394 { 395 _Iterator __base = base(); 396 return ++__base != _M_get_sequence()->_M_base().end(); 397 } 398 return false; 399 } 400 401 /// Is the iterator incrementable? 402 bool _M_incrementable()403 _M_incrementable() const 404 { return !this->_M_singular() && !_M_is_end(); } 405 406 // Can we advance the iterator @p __n steps (@p __n may be negative) 407 bool 408 _M_can_advance(difference_type __n, bool __strict = false) const; 409 410 // Can we advance the iterator using @p __dist in @p __way direction. 411 template<typename _Diff> 412 bool 413 _M_can_advance(const std::pair<_Diff, _Distance_precision>& __dist, 414 int __way) const; 415 416 // Is the iterator range [*this, __rhs) valid? 417 bool 418 _M_valid_range(const _Safe_iterator& __rhs, 419 std::pair<difference_type, _Distance_precision>& __dist, 420 bool __check_dereferenceable = true) const; 421 422 // The sequence this iterator references. 423 typename __gnu_cxx::__conditional_type< 424 _IsConstant::__value, const _Sequence*, _Sequence*>::__type _M_get_sequence()425 _M_get_sequence() const 426 { return static_cast<_Sequence*>(_M_sequence); } 427 428 // Get distance to __rhs. 429 typename _Distance_traits<_Iterator>::__type 430 _M_get_distance_to(const _Safe_iterator& __rhs) const; 431 432 // Get distance from sequence begin up to *this. 433 typename _Distance_traits<_Iterator>::__type 434 _M_get_distance_from_begin() const; 435 436 // Get distance from *this to sequence end. 437 typename _Distance_traits<_Iterator>::__type 438 _M_get_distance_to_end() const; 439 440 /// Is this iterator equal to the sequence's begin() iterator? 441 bool _M_is_begin()442 _M_is_begin() const 443 { return base() == _M_get_sequence()->_M_base().begin(); } 444 445 /// Is this iterator equal to the sequence's end() iterator? 446 bool _M_is_end()447 _M_is_end() const 448 { return base() == _M_get_sequence()->_M_base().end(); } 449 450 /// Is this iterator equal to the sequence's before_begin() iterator if 451 /// any? 452 bool _M_is_before_begin()453 _M_is_before_begin() const 454 { return _BeforeBeginHelper<_Sequence>::_S_Is(*this); } 455 456 /// Is this iterator equal to the sequence's before_begin() iterator if 457 /// any or begin() otherwise? 458 bool _M_is_beginnest()459 _M_is_beginnest() const 460 { return _BeforeBeginHelper<_Sequence>::_S_Is_Beginnest(*this); } 461 462 // ------ Operators ------ 463 464 typedef _Safe_iterator<_Iterator, _Sequence, iterator_category> _Self; 465 466 friend bool 467 operator==(const _Self& __lhs, const _Self& __rhs) _GLIBCXX_NOEXCEPT 468 { 469 _GLIBCXX_DEBUG_VERIFY_EQ_OPERANDS(__lhs, __rhs); 470 return __lhs.base() == __rhs.base(); 471 } 472 473 template<typename _IteR> 474 friend bool 475 operator==(const _Self& __lhs, 476 const _Safe_iterator<_IteR, _Sequence, iterator_category>& __rhs) 477 _GLIBCXX_NOEXCEPT 478 { 479 _GLIBCXX_DEBUG_VERIFY_EQ_OPERANDS(__lhs, __rhs); 480 return __lhs.base() == __rhs.base(); 481 } 482 483 #if ! __cpp_lib_three_way_comparison 484 friend bool 485 operator!=(const _Self& __lhs, const _Self& __rhs) _GLIBCXX_NOEXCEPT 486 { 487 _GLIBCXX_DEBUG_VERIFY_EQ_OPERANDS(__lhs, __rhs); 488 return __lhs.base() != __rhs.base(); 489 } 490 491 template<typename _IteR> 492 friend bool 493 operator!=(const _Self& __lhs, 494 const _Safe_iterator<_IteR, _Sequence, iterator_category>& __rhs) 495 _GLIBCXX_NOEXCEPT 496 { 497 _GLIBCXX_DEBUG_VERIFY_EQ_OPERANDS(__lhs, __rhs); 498 return __lhs.base() != __rhs.base(); 499 } 500 #endif // three-way comparison 501 }; 502 503 template<typename _Iterator, typename _Sequence> 504 class _Safe_iterator<_Iterator, _Sequence, std::bidirectional_iterator_tag> 505 : public _Safe_iterator<_Iterator, _Sequence, std::forward_iterator_tag> 506 { 507 typedef _Safe_iterator<_Iterator, _Sequence, 508 std::forward_iterator_tag> _Safe_base; 509 510 protected: 511 typedef typename _Safe_base::_OtherIterator _OtherIterator; 512 typedef typename _Safe_base::_Attach_single _Attach_single; 513 _Safe_iterator(_Iterator __i,_Safe_sequence_base * __seq,_Attach_single)514 _Safe_iterator(_Iterator __i, _Safe_sequence_base* __seq, _Attach_single) 515 _GLIBCXX_NOEXCEPT 516 : _Safe_base(__i, __seq, _Attach_single()) 517 { } 518 519 public: 520 /// @post the iterator is singular and unattached _Safe_iterator()521 _Safe_iterator() _GLIBCXX_NOEXCEPT { } 522 523 /** 524 * @brief Safe iterator construction from an unsafe iterator and 525 * its sequence. 526 * 527 * @pre @p seq is not NULL 528 * @post this is not singular 529 */ _Safe_iterator(_Iterator __i,const _Safe_sequence_base * __seq)530 _Safe_iterator(_Iterator __i, const _Safe_sequence_base* __seq) 531 _GLIBCXX_NOEXCEPT 532 : _Safe_base(__i, __seq) 533 { } 534 535 /** 536 * @brief Copy construction. 537 */ _Safe_iterator(const _Safe_iterator & __x)538 _Safe_iterator(const _Safe_iterator& __x) _GLIBCXX_NOEXCEPT 539 : _Safe_base(__x) 540 { } 541 542 #if __cplusplus >= 201103L 543 /** @brief Move construction. */ 544 _Safe_iterator(_Safe_iterator&&) = default; 545 #endif 546 547 /** 548 * @brief Converting constructor from a mutable iterator to a 549 * constant iterator. 550 */ 551 template<typename _MutableIterator> _Safe_iterator(const _Safe_iterator<_MutableIterator,_Sequence,typename __gnu_cxx::__enable_if<_Safe_base::_IsConstant::__value && std::__are_same<_MutableIterator,_OtherIterator>::__value,std::bidirectional_iterator_tag>::__type> & __x)552 _Safe_iterator( 553 const _Safe_iterator<_MutableIterator, _Sequence, 554 typename __gnu_cxx::__enable_if<_Safe_base::_IsConstant::__value && 555 std::__are_same<_MutableIterator, _OtherIterator>::__value, 556 std::bidirectional_iterator_tag>::__type>& __x) 557 _GLIBCXX_NOEXCEPT 558 : _Safe_base(__x) 559 { } 560 561 #if __cplusplus >= 201103L 562 /** @brief Copy assignment. */ 563 _Safe_iterator& 564 operator=(const _Safe_iterator&) = default; 565 566 /** @brief Move assignment. */ 567 _Safe_iterator& 568 operator=(_Safe_iterator&&) = default; 569 #else 570 /** @brief Copy assignment. */ 571 _Safe_iterator& 572 operator=(const _Safe_iterator& __x) 573 { 574 _Safe_base::operator=(__x); 575 return *this; 576 } 577 #endif 578 579 // ------ Input iterator requirements ------ 580 /** 581 * @brief Iterator preincrement 582 * @pre iterator is incrementable 583 */ 584 _Safe_iterator& 585 operator++() _GLIBCXX_NOEXCEPT 586 { 587 _Safe_base::operator++(); 588 return *this; 589 } 590 591 /** 592 * @brief Iterator postincrement 593 * @pre iterator is incrementable 594 */ 595 _Safe_iterator 596 operator++(int) _GLIBCXX_NOEXCEPT 597 { 598 _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(), 599 _M_message(__msg_bad_inc) 600 ._M_iterator(*this, "this")); 601 __gnu_cxx::__scoped_lock __l(this->_M_get_mutex()); 602 return _Safe_iterator(this->base()++, this->_M_sequence, 603 _Attach_single()); 604 } 605 606 // ------ Bidirectional iterator requirements ------ 607 /** 608 * @brief Iterator predecrement 609 * @pre iterator is decrementable 610 */ 611 _Safe_iterator& 612 operator--() _GLIBCXX_NOEXCEPT 613 { 614 _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(), 615 _M_message(__msg_bad_dec) 616 ._M_iterator(*this, "this")); 617 __gnu_cxx::__scoped_lock __l(this->_M_get_mutex()); 618 --this->base(); 619 return *this; 620 } 621 622 /** 623 * @brief Iterator postdecrement 624 * @pre iterator is decrementable 625 */ 626 _Safe_iterator 627 operator--(int) _GLIBCXX_NOEXCEPT 628 { 629 _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(), 630 _M_message(__msg_bad_dec) 631 ._M_iterator(*this, "this")); 632 __gnu_cxx::__scoped_lock __l(this->_M_get_mutex()); 633 return _Safe_iterator(this->base()--, this->_M_sequence, 634 _Attach_single()); 635 } 636 637 // ------ Utilities ------ 638 639 // Is the iterator decrementable? 640 bool _M_decrementable()641 _M_decrementable() const 642 { return !this->_M_singular() && !this->_M_is_begin(); } 643 }; 644 645 template<typename _Iterator, typename _Sequence> 646 class _Safe_iterator<_Iterator, _Sequence, std::random_access_iterator_tag> 647 : public _Safe_iterator<_Iterator, _Sequence, 648 std::bidirectional_iterator_tag> 649 { 650 typedef _Safe_iterator<_Iterator, _Sequence, 651 std::bidirectional_iterator_tag> _Safe_base; 652 typedef typename _Safe_base::_OtherIterator _OtherIterator; 653 654 typedef typename _Safe_base::_Self _Self; 655 typedef _Safe_iterator<_OtherIterator, _Sequence, 656 std::random_access_iterator_tag> _OtherSelf; 657 658 typedef typename _Safe_base::_Attach_single _Attach_single; 659 _Safe_iterator(_Iterator __i,_Safe_sequence_base * __seq,_Attach_single)660 _Safe_iterator(_Iterator __i, _Safe_sequence_base* __seq, _Attach_single) 661 _GLIBCXX_NOEXCEPT 662 : _Safe_base(__i, __seq, _Attach_single()) 663 { } 664 665 public: 666 typedef typename _Safe_base::difference_type difference_type; 667 typedef typename _Safe_base::reference reference; 668 669 /// @post the iterator is singular and unattached _Safe_iterator()670 _Safe_iterator() _GLIBCXX_NOEXCEPT { } 671 672 /** 673 * @brief Safe iterator construction from an unsafe iterator and 674 * its sequence. 675 * 676 * @pre @p seq is not NULL 677 * @post this is not singular 678 */ _Safe_iterator(_Iterator __i,const _Safe_sequence_base * __seq)679 _Safe_iterator(_Iterator __i, const _Safe_sequence_base* __seq) 680 _GLIBCXX_NOEXCEPT 681 : _Safe_base(__i, __seq) 682 { } 683 684 /** 685 * @brief Copy construction. 686 */ _Safe_iterator(const _Safe_iterator & __x)687 _Safe_iterator(const _Safe_iterator& __x) _GLIBCXX_NOEXCEPT 688 : _Safe_base(__x) 689 { } 690 691 #if __cplusplus >= 201103L 692 /** @brief Move construction. */ 693 _Safe_iterator(_Safe_iterator&&) = default; 694 #endif 695 696 /** 697 * @brief Converting constructor from a mutable iterator to a 698 * constant iterator. 699 */ 700 template<typename _MutableIterator> _Safe_iterator(const _Safe_iterator<_MutableIterator,_Sequence,typename __gnu_cxx::__enable_if<_Safe_base::_IsConstant::__value && std::__are_same<_MutableIterator,_OtherIterator>::__value,std::random_access_iterator_tag>::__type> & __x)701 _Safe_iterator( 702 const _Safe_iterator<_MutableIterator, _Sequence, 703 typename __gnu_cxx::__enable_if<_Safe_base::_IsConstant::__value && 704 std::__are_same<_MutableIterator, _OtherIterator>::__value, 705 std::random_access_iterator_tag>::__type>& __x) 706 _GLIBCXX_NOEXCEPT 707 : _Safe_base(__x) 708 { } 709 710 #if __cplusplus >= 201103L 711 /** @brief Copy assignment. */ 712 _Safe_iterator& 713 operator=(const _Safe_iterator&) = default; 714 715 /** @brief Move assignment. */ 716 _Safe_iterator& 717 operator=(_Safe_iterator&&) = default; 718 #else 719 /** @brief Copy assignment. */ 720 _Safe_iterator& 721 operator=(const _Safe_iterator& __x) 722 { 723 _Safe_base::operator=(__x); 724 return *this; 725 } 726 #endif 727 728 // Is the iterator range [*this, __rhs) valid? 729 bool 730 _M_valid_range(const _Safe_iterator& __rhs, 731 std::pair<difference_type, 732 _Distance_precision>& __dist) const; 733 734 // ------ Input iterator requirements ------ 735 /** 736 * @brief Iterator preincrement 737 * @pre iterator is incrementable 738 */ 739 _Safe_iterator& 740 operator++() _GLIBCXX_NOEXCEPT 741 { 742 _Safe_base::operator++(); 743 return *this; 744 } 745 746 /** 747 * @brief Iterator postincrement 748 * @pre iterator is incrementable 749 */ 750 _Safe_iterator 751 operator++(int) _GLIBCXX_NOEXCEPT 752 { 753 _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(), 754 _M_message(__msg_bad_inc) 755 ._M_iterator(*this, "this")); 756 __gnu_cxx::__scoped_lock __l(this->_M_get_mutex()); 757 return _Safe_iterator(this->base()++, this->_M_sequence, 758 _Attach_single()); 759 } 760 761 // ------ Bidirectional iterator requirements ------ 762 /** 763 * @brief Iterator predecrement 764 * @pre iterator is decrementable 765 */ 766 _Safe_iterator& 767 operator--() _GLIBCXX_NOEXCEPT 768 { 769 _Safe_base::operator--(); 770 return *this; 771 } 772 773 /** 774 * @brief Iterator postdecrement 775 * @pre iterator is decrementable 776 */ 777 _Safe_iterator 778 operator--(int) _GLIBCXX_NOEXCEPT 779 { 780 _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(), 781 _M_message(__msg_bad_dec) 782 ._M_iterator(*this, "this")); 783 __gnu_cxx::__scoped_lock __l(this->_M_get_mutex()); 784 return _Safe_iterator(this->base()--, this->_M_sequence, 785 _Attach_single()); 786 } 787 788 // ------ Random access iterator requirements ------ 789 reference 790 operator[](difference_type __n) const _GLIBCXX_NOEXCEPT 791 { 792 _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n) 793 && this->_M_can_advance(__n + 1), 794 _M_message(__msg_iter_subscript_oob) 795 ._M_iterator(*this)._M_integer(__n)); 796 return this->base()[__n]; 797 } 798 799 _Safe_iterator& 800 operator+=(difference_type __n) _GLIBCXX_NOEXCEPT 801 { 802 _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n), 803 _M_message(__msg_advance_oob) 804 ._M_iterator(*this)._M_integer(__n)); 805 __gnu_cxx::__scoped_lock __l(this->_M_get_mutex()); 806 this->base() += __n; 807 return *this; 808 } 809 810 _Safe_iterator& 811 operator-=(difference_type __n) _GLIBCXX_NOEXCEPT 812 { 813 _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(-__n), 814 _M_message(__msg_retreat_oob) 815 ._M_iterator(*this)._M_integer(__n)); 816 __gnu_cxx::__scoped_lock __l(this->_M_get_mutex()); 817 this->base() -= __n; 818 return *this; 819 } 820 821 #if __cpp_lib_three_way_comparison 822 friend auto 823 operator<=>(const _Self& __lhs, const _Self& __rhs) noexcept 824 { 825 _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs, __rhs); 826 return __lhs.base() <=> __rhs.base(); 827 } 828 829 friend auto 830 operator<=>(const _Self& __lhs, const _OtherSelf& __rhs) noexcept 831 { 832 _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs, __rhs); 833 return __lhs.base() <=> __rhs.base(); 834 } 835 #else 836 friend bool 837 operator<(const _Self& __lhs, const _Self& __rhs) _GLIBCXX_NOEXCEPT 838 { 839 _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs, __rhs); 840 return __lhs.base() < __rhs.base(); 841 } 842 843 friend bool 844 operator<(const _Self& __lhs, const _OtherSelf& __rhs) _GLIBCXX_NOEXCEPT 845 { 846 _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs, __rhs); 847 return __lhs.base() < __rhs.base(); 848 } 849 850 friend bool 851 operator<=(const _Self& __lhs, const _Self& __rhs) _GLIBCXX_NOEXCEPT 852 { 853 _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs, __rhs); 854 return __lhs.base() <= __rhs.base(); 855 } 856 857 friend bool 858 operator<=(const _Self& __lhs, const _OtherSelf& __rhs) _GLIBCXX_NOEXCEPT 859 { 860 _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs, __rhs); 861 return __lhs.base() <= __rhs.base(); 862 } 863 864 friend bool 865 operator>(const _Self& __lhs, const _Self& __rhs) _GLIBCXX_NOEXCEPT 866 { 867 _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs, __rhs); 868 return __lhs.base() > __rhs.base(); 869 } 870 871 friend bool 872 operator>(const _Self& __lhs, const _OtherSelf& __rhs) _GLIBCXX_NOEXCEPT 873 { 874 _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs, __rhs); 875 return __lhs.base() > __rhs.base(); 876 } 877 878 friend bool 879 operator>=(const _Self& __lhs, const _Self& __rhs) _GLIBCXX_NOEXCEPT 880 { 881 _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs, __rhs); 882 return __lhs.base() >= __rhs.base(); 883 } 884 885 friend bool 886 operator>=(const _Self& __lhs, const _OtherSelf& __rhs) _GLIBCXX_NOEXCEPT 887 { 888 _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs, __rhs); 889 return __lhs.base() >= __rhs.base(); 890 } 891 #endif // three-way comparison 892 893 // _GLIBCXX_RESOLVE_LIB_DEFECTS 894 // According to the resolution of DR179 not only the various comparison 895 // operators but also operator- must accept mixed iterator/const_iterator 896 // parameters. 897 friend difference_type 898 operator-(const _Self& __lhs, const _OtherSelf& __rhs) _GLIBCXX_NOEXCEPT 899 { 900 _GLIBCXX_DEBUG_VERIFY_DIST_OPERANDS(__lhs, __rhs); 901 return __lhs.base() - __rhs.base(); 902 } 903 904 friend difference_type 905 operator-(const _Self& __lhs, const _Self& __rhs) _GLIBCXX_NOEXCEPT 906 { 907 _GLIBCXX_DEBUG_VERIFY_DIST_OPERANDS(__lhs, __rhs); 908 return __lhs.base() - __rhs.base(); 909 } 910 911 friend _Self 912 operator+(const _Self& __x, difference_type __n) _GLIBCXX_NOEXCEPT 913 { 914 _GLIBCXX_DEBUG_VERIFY(__x._M_can_advance(__n), 915 _M_message(__msg_advance_oob) 916 ._M_iterator(__x)._M_integer(__n)); 917 return _Safe_iterator(__x.base() + __n, __x._M_sequence); 918 } 919 920 friend _Self 921 operator+(difference_type __n, const _Self& __x) _GLIBCXX_NOEXCEPT 922 { 923 _GLIBCXX_DEBUG_VERIFY(__x._M_can_advance(__n), 924 _M_message(__msg_advance_oob) 925 ._M_iterator(__x)._M_integer(__n)); 926 return _Safe_iterator(__n + __x.base(), __x._M_sequence); 927 } 928 929 friend _Self 930 operator-(const _Self& __x, difference_type __n) _GLIBCXX_NOEXCEPT 931 { 932 _GLIBCXX_DEBUG_VERIFY(__x._M_can_advance(-__n), 933 _M_message(__msg_retreat_oob) 934 ._M_iterator(__x)._M_integer(__n)); 935 return _Safe_iterator(__x.base() - __n, __x._M_sequence); 936 } 937 }; 938 939 /** Safe iterators know how to check if they form a valid range. */ 940 template<typename _Iterator, typename _Sequence, typename _Category> 941 inline bool __valid_range(const _Safe_iterator<_Iterator,_Sequence,_Category> & __first,const _Safe_iterator<_Iterator,_Sequence,_Category> & __last,typename _Distance_traits<_Iterator>::__type & __dist)942 __valid_range(const _Safe_iterator<_Iterator, _Sequence, 943 _Category>& __first, 944 const _Safe_iterator<_Iterator, _Sequence, 945 _Category>& __last, 946 typename _Distance_traits<_Iterator>::__type& __dist) 947 { return __first._M_valid_range(__last, __dist); } 948 949 template<typename _Iterator, typename _Sequence, typename _Category> 950 inline bool __valid_range(const _Safe_iterator<_Iterator,_Sequence,_Category> & __first,const _Safe_iterator<_Iterator,_Sequence,_Category> & __last)951 __valid_range(const _Safe_iterator<_Iterator, _Sequence, 952 _Category>& __first, 953 const _Safe_iterator<_Iterator, _Sequence, 954 _Category>& __last) 955 { 956 typename _Distance_traits<_Iterator>::__type __dist; 957 return __first._M_valid_range(__last, __dist); 958 } 959 960 template<typename _Iterator, typename _Sequence, typename _Category, 961 typename _Size> 962 inline bool __can_advance(const _Safe_iterator<_Iterator,_Sequence,_Category> & __it,_Size __n)963 __can_advance(const _Safe_iterator<_Iterator, _Sequence, _Category>& __it, 964 _Size __n) 965 { return __it._M_can_advance(__n); } 966 967 template<typename _Iterator, typename _Sequence, typename _Category, 968 typename _Diff> 969 inline bool __can_advance(const _Safe_iterator<_Iterator,_Sequence,_Category> & __it,const std::pair<_Diff,_Distance_precision> & __dist,int __way)970 __can_advance(const _Safe_iterator<_Iterator, _Sequence, _Category>& __it, 971 const std::pair<_Diff, _Distance_precision>& __dist, 972 int __way) 973 { return __it._M_can_advance(__dist, __way); } 974 975 template<typename _Iterator, typename _Sequence> 976 _Iterator __base(const _Safe_iterator<_Iterator,_Sequence,std::random_access_iterator_tag> & __it)977 __base(const _Safe_iterator<_Iterator, _Sequence, 978 std::random_access_iterator_tag>& __it) 979 { return __it.base(); } 980 981 #if __cplusplus < 201103L 982 template<typename _Iterator, typename _Sequence> 983 struct _Unsafe_type<_Safe_iterator<_Iterator, _Sequence> > 984 { typedef _Iterator _Type; }; 985 #endif 986 987 template<typename _Iterator, typename _Sequence> 988 inline _Iterator 989 __unsafe(const _Safe_iterator<_Iterator, _Sequence>& __it) 990 { return __it.base(); } 991 992 } // namespace __gnu_debug 993 994 #undef _GLIBCXX_DEBUG_VERIFY_DIST_OPERANDS 995 #undef _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS 996 #undef _GLIBCXX_DEBUG_VERIFY_EQ_OPERANDS 997 #undef _GLIBCXX_DEBUG_VERIFY_OPERANDS 998 999 #include <debug/safe_iterator.tcc> 1000 1001 #endif 1002