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