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