]> git.ipfire.org Git - thirdparty/gcc.git/blob - libstdc++-v3/include/debug/safe_iterator.h
bitset, [...]: Remove trailing whitespace.
[thirdparty/gcc.git] / libstdc++-v3 / include / debug / safe_iterator.h
1 // Safe iterator implementation -*- C++ -*-
2
3 // Copyright (C) 2003
4 // Free Software Foundation, Inc.
5 //
6 // This file is part of the GNU ISO C++ Library. This library is free
7 // software; you can redistribute it and/or modify it under the
8 // terms of the GNU General Public License as published by the
9 // Free Software Foundation; either version 2, or (at your option)
10 // any later version.
11
12 // This library is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
16
17 // You should have received a copy of the GNU General Public License along
18 // with this library; see the file COPYING. If not, write to the Free
19 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
20 // USA.
21
22 // As a special exception, you may use this file as part of a free software
23 // library without restriction. Specifically, if other files instantiate
24 // templates or use macros or inline functions from this file, or you compile
25 // this file and link it with other files to produce an executable, this
26 // file does not by itself cause the resulting executable to be covered by
27 // the GNU General Public License. This exception does not however
28 // invalidate any other reasons why the executable file might be covered by
29 // the GNU General Public License.
30
31 #ifndef _GLIBCXX_DEBUG_SAFE_ITERATOR_H
32 #define _GLIBCXX_DEBUG_SAFE_ITERATOR_H 1
33
34 #include <bits/stl_pair.h>
35 #include <debug/debug.h>
36 #include <debug/formatter.h>
37 #include <debug/safe_base.h>
38
39 namespace __gnu_debug
40 {
41 /** Iterators that derive from _Safe_iterator_base but that aren't
42 * _Safe_iterators can be determined singular or non-singular via
43 * _Safe_iterator_base.
44 */
45 inline bool __check_singular_aux(const _Safe_iterator_base* __x)
46 { return __x->_M_singular(); }
47
48 /** \brief Safe iterator wrapper.
49 *
50 * The class template %_Safe_iterator is a wrapper around an
51 * iterator that tracks the iterator's movement among sequences and
52 * checks that operations performed on the "safe" iterator are
53 * legal. In additional to the basic iterator operations (which are
54 * validated, and then passed to the underlying iterator),
55 * %_Safe_iterator has member functions for iterator invalidation,
56 * attaching/detaching the iterator from sequences, and querying
57 * the iterator's state.
58 */
59 template<typename _Iterator, typename _Sequence>
60 class _Safe_iterator : public _Safe_iterator_base
61 {
62 typedef _Safe_iterator _Self;
63
64 /** The precision to which we can calculate the distance between
65 * two iterators.
66 */
67 enum _Distance_precision
68 {
69 __dp_equality, //< Can compare iterator equality, only
70 __dp_sign, //< Can determine equality and ordering
71 __dp_exact //< Can determine distance precisely
72 };
73
74 /// The underlying iterator
75 _Iterator _M_current;
76
77 /// Determine if this is a constant iterator.
78 bool
79 _M_constant() const
80 {
81 typedef typename _Sequence::const_iterator const_iterator;
82 return __is_same<const_iterator, _Safe_iterator>::value;
83 }
84
85 typedef iterator_traits<_Iterator> _Traits;
86
87 public:
88 typedef typename _Traits::iterator_category iterator_category;
89 typedef typename _Traits::value_type value_type;
90 typedef typename _Traits::difference_type difference_type;
91 typedef typename _Traits::reference reference;
92 typedef typename _Traits::pointer pointer;
93
94 /// @post the iterator is singular and unattached
95 _Safe_iterator() : _M_current() { }
96
97 /**
98 * @brief Safe iterator construction from an unsafe iterator and
99 * its sequence.
100 *
101 * @pre @p seq is not NULL
102 * @post this is not singular
103 */
104 _Safe_iterator(const _Iterator& __i, const _Sequence* __seq)
105 : _Safe_iterator_base(__seq, _M_constant()), _M_current(__i)
106 {
107 _GLIBCXX_DEBUG_VERIFY(! this->_M_singular(),
108 _M_message(__msg_init_singular)
109 ._M_iterator(*this, "this"));
110 }
111
112 /**
113 * @brief Copy construction.
114 * @pre @p x is not singular
115 */
116 _Safe_iterator(const _Safe_iterator& __x)
117 : _Safe_iterator_base(__x, _M_constant()), _M_current(__x._M_current)
118 {
119 _GLIBCXX_DEBUG_VERIFY(!__x._M_singular(),
120 _M_message(__msg_init_copy_singular)
121 ._M_iterator(*this, "this")
122 ._M_iterator(__x, "other"));
123 }
124
125 /**
126 * @brief Converting constructor from a mutable iterator to a
127 * constant iterator.
128 *
129 * @pre @p x is not singular
130 */
131 template<typename _MutableIterator>
132 _Safe_iterator(const _Safe_iterator<_MutableIterator, _Sequence>& __x)
133 : _Safe_iterator_base(__x, _M_constant()), _M_current(__x.base())
134 {
135 _GLIBCXX_DEBUG_VERIFY(!__x._M_singular(),
136 _M_message(__msg_init_const_singular)
137 ._M_iterator(*this, "this")
138 ._M_iterator(__x, "other"));
139 }
140
141 /**
142 * @brief Copy assignment.
143 * @pre @p x is not singular
144 */
145 _Safe_iterator&
146 operator=(const _Safe_iterator& __x)
147 {
148 _GLIBCXX_DEBUG_VERIFY(!__x._M_singular(),
149 _M_message(__msg_copy_singular)
150 ._M_iterator(*this, "this")
151 ._M_iterator(__x, "other"));
152 _M_current = __x._M_current;
153 this->_M_attach(static_cast<_Sequence*>(__x._M_sequence));
154 return *this;
155 }
156
157 /**
158 * @brief Iterator dereference.
159 * @pre iterator is dereferenceable
160 */
161 reference
162 operator*() const
163 {
164
165 _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
166 _M_message(__msg_bad_deref)
167 ._M_iterator(*this, "this"));
168 return *_M_current;
169 }
170
171 /**
172 * @brief Iterator dereference.
173 * @pre iterator is dereferenceable
174 * @todo Make this correct w.r.t. iterators that return proxies
175 * @todo Use addressof() instead of & operator
176 */
177 pointer
178 operator->() const
179 {
180 _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
181 _M_message(__msg_bad_deref)
182 ._M_iterator(*this, "this"));
183 return &*_M_current;
184 }
185
186 // ------ Input iterator requirements ------
187 /**
188 * @brief Iterator preincrement
189 * @pre iterator is incrementable
190 */
191 _Safe_iterator&
192 operator++()
193 {
194 _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
195 _M_message(__msg_bad_inc)
196 ._M_iterator(*this, "this"));
197 ++_M_current;
198 return *this;
199 }
200
201 /**
202 * @brief Iterator postincrement
203 * @pre iterator is incrementable
204 */
205 _Safe_iterator
206 operator++(int)
207 {
208 _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
209 _M_message(__msg_bad_inc)
210 ._M_iterator(*this, "this"));
211 _Safe_iterator __tmp(*this);
212 ++_M_current;
213 return __tmp;
214 }
215
216 // ------ Bidirectional iterator requirements ------
217 /**
218 * @brief Iterator predecrement
219 * @pre iterator is decrementable
220 */
221 _Safe_iterator&
222 operator--()
223 {
224 _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
225 _M_message(__msg_bad_dec)
226 ._M_iterator(*this, "this"));
227 --_M_current;
228 return *this;
229 }
230
231 /**
232 * @brief Iterator postdecrement
233 * @pre iterator is decrementable
234 */
235 _Safe_iterator
236 operator--(int)
237 {
238 _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
239 _M_message(__msg_bad_dec)
240 ._M_iterator(*this, "this"));
241 _Safe_iterator __tmp(*this);
242 --_M_current;
243 return __tmp;
244 }
245
246 // ------ Random access iterator requirements ------
247 reference
248 operator[](const difference_type& __n) const
249 {
250 _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n)
251 && this->_M_can_advance(__n+1),
252 _M_message(__msg_iter_subscript_oob)
253 ._M_iterator(*this)._M_integer(__n));
254
255 return _M_current[__n];
256 }
257
258 _Safe_iterator&
259 operator+=(const difference_type& __n)
260 {
261 _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n),
262 _M_message(__msg_advance_oob)
263 ._M_iterator(*this)._M_integer(__n));
264 _M_current += __n;
265 return *this;
266 }
267
268 _Safe_iterator
269 operator+(const difference_type& __n) const
270 {
271 _Safe_iterator __tmp(*this);
272 __tmp += __n;
273 return __tmp;
274 }
275
276 _Safe_iterator&
277 operator-=(const difference_type& __n)
278 {
279 _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(-__n),
280 _M_message(__msg_retreat_oob)
281 ._M_iterator(*this)._M_integer(__n));
282 _M_current += -__n;
283 return *this;
284 }
285
286 _Safe_iterator
287 operator-(const difference_type& __n) const
288 {
289 _Safe_iterator __tmp(*this);
290 __tmp -= __n;
291 return __tmp;
292 }
293
294 // ------ Utilities ------
295 /**
296 * @brief Return the underlying iterator
297 */
298 _Iterator
299 base() const { return _M_current; }
300
301 /**
302 * @brief Conversion to underlying non-debug iterator to allow
303 * better interaction with non-debug containers.
304 */
305 operator _Iterator() const { return _M_current; }
306
307 /** Attach iterator to the given sequence. */
308 void
309 _M_attach(const _Sequence* __seq)
310 {
311 _Safe_iterator_base::_M_attach(const_cast<_Sequence*>(__seq),
312 _M_constant());
313 }
314
315 /** Invalidate the iterator, making it singular. */
316 void
317 _M_invalidate();
318
319 /// Is the iterator dereferenceable?
320 bool
321 _M_dereferenceable() const
322 { return !this->_M_singular() && !_M_is_end(); }
323
324 /// Is the iterator incrementable?
325 bool
326 _M_incrementable() const { return this->_M_dereferenceable(); }
327
328 // Is the iterator decrementable?
329 bool
330 _M_decrementable() const { return !_M_singular() && !_M_is_begin(); }
331
332 // Can we advance the iterator @p __n steps (@p __n may be negative)
333 bool
334 _M_can_advance(const difference_type& __n) const;
335
336 // Is the iterator range [*this, __rhs) valid?
337 template<typename _Other>
338 bool
339 _M_valid_range(const _Safe_iterator<_Other, _Sequence>& __rhs) const;
340
341 // The sequence this iterator references.
342 const _Sequence*
343 _M_get_sequence() const
344 { return static_cast<const _Sequence*>(_M_sequence); }
345
346 /** Determine the distance between two iterators with some known
347 * precision.
348 */
349 template<typename _Iterator1, typename _Iterator2>
350 static pair<difference_type, _Distance_precision>
351 _M_get_distance(const _Iterator1& __lhs, const _Iterator2& __rhs)
352 {
353 typedef typename iterator_traits<_Iterator1>::iterator_category
354 _Category;
355 return _M_get_distance(__lhs, __rhs, _Category());
356 }
357
358 template<typename _Iterator1, typename _Iterator2>
359 static pair<difference_type, _Distance_precision>
360 _M_get_distance(const _Iterator1& __lhs, const _Iterator2& __rhs,
361 std::random_access_iterator_tag)
362 {
363 return std::make_pair(__rhs.base() - __lhs.base(), __dp_exact);
364 }
365
366 template<typename _Iterator1, typename _Iterator2>
367 static pair<difference_type, _Distance_precision>
368 _M_get_distance(const _Iterator1& __lhs, const _Iterator2& __rhs,
369 std::forward_iterator_tag)
370 {
371 return std::make_pair(__lhs.base() == __rhs.base()? 0 : 1,
372 __dp_equality);
373 }
374
375 /// Is this iterator equal to the sequence's begin() iterator?
376 bool _M_is_begin() const
377 { return *this == static_cast<const _Sequence*>(_M_sequence)->begin(); }
378
379 /// Is this iterator equal to the sequence's end() iterator?
380 bool _M_is_end() const
381 { return *this == static_cast<const _Sequence*>(_M_sequence)->end(); }
382 };
383
384 template<typename _IteratorL, typename _IteratorR, typename _Sequence>
385 inline bool
386 operator==(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
387 const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
388 {
389 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
390 _M_message(__msg_iter_compare_bad)
391 ._M_iterator(__lhs, "lhs")
392 ._M_iterator(__rhs, "rhs"));
393 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
394 _M_message(__msg_compare_different)
395 ._M_iterator(__lhs, "lhs")
396 ._M_iterator(__rhs, "rhs"));
397 return __lhs.base() == __rhs.base();
398 }
399
400 template<typename _Iterator, typename _Sequence>
401 inline bool
402 operator==(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
403 const _Safe_iterator<_Iterator, _Sequence>& __rhs)
404 {
405 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
406 _M_message(__msg_iter_compare_bad)
407 ._M_iterator(__lhs, "lhs")
408 ._M_iterator(__rhs, "rhs"));
409 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
410 _M_message(__msg_compare_different)
411 ._M_iterator(__lhs, "lhs")
412 ._M_iterator(__rhs, "rhs"));
413 return __lhs.base() == __rhs.base();
414 }
415
416 template<typename _IteratorL, typename _IteratorR, typename _Sequence>
417 inline bool
418 operator!=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
419 const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
420 {
421 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
422 _M_message(__msg_iter_compare_bad)
423 ._M_iterator(__lhs, "lhs")
424 ._M_iterator(__rhs, "rhs"));
425 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
426 _M_message(__msg_compare_different)
427 ._M_iterator(__lhs, "lhs")
428 ._M_iterator(__rhs, "rhs"));
429 return __lhs.base() != __rhs.base();
430 }
431
432 template<typename _Iterator, typename _Sequence>
433 inline bool
434 operator!=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
435 const _Safe_iterator<_Iterator, _Sequence>& __rhs)
436 {
437 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
438 _M_message(__msg_iter_compare_bad)
439 ._M_iterator(__lhs, "lhs")
440 ._M_iterator(__rhs, "rhs"));
441 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
442 _M_message(__msg_compare_different)
443 ._M_iterator(__lhs, "lhs")
444 ._M_iterator(__rhs, "rhs"));
445 return __lhs.base() != __rhs.base();
446 }
447
448 template<typename _IteratorL, typename _IteratorR, typename _Sequence>
449 inline bool
450 operator<(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
451 const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
452 {
453 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
454 _M_message(__msg_iter_order_bad)
455 ._M_iterator(__lhs, "lhs")
456 ._M_iterator(__rhs, "rhs"));
457 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
458 _M_message(__msg_order_different)
459 ._M_iterator(__lhs, "lhs")
460 ._M_iterator(__rhs, "rhs"));
461 return __lhs.base() < __rhs.base();
462 }
463
464 template<typename _Iterator, typename _Sequence>
465 inline bool
466 operator<(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
467 const _Safe_iterator<_Iterator, _Sequence>& __rhs)
468 {
469 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
470 _M_message(__msg_iter_order_bad)
471 ._M_iterator(__lhs, "lhs")
472 ._M_iterator(__rhs, "rhs"));
473 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
474 _M_message(__msg_order_different)
475 ._M_iterator(__lhs, "lhs")
476 ._M_iterator(__rhs, "rhs"));
477 return __lhs.base() < __rhs.base();
478 }
479
480 template<typename _IteratorL, typename _IteratorR, typename _Sequence>
481 inline bool
482 operator<=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
483 const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
484 {
485 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
486 _M_message(__msg_iter_order_bad)
487 ._M_iterator(__lhs, "lhs")
488 ._M_iterator(__rhs, "rhs"));
489 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
490 _M_message(__msg_order_different)
491 ._M_iterator(__lhs, "lhs")
492 ._M_iterator(__rhs, "rhs"));
493 return __lhs.base() <= __rhs.base();
494 }
495
496 template<typename _Iterator, typename _Sequence>
497 inline bool
498 operator<=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
499 const _Safe_iterator<_Iterator, _Sequence>& __rhs)
500 {
501 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
502 _M_message(__msg_iter_order_bad)
503 ._M_iterator(__lhs, "lhs")
504 ._M_iterator(__rhs, "rhs"));
505 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
506 _M_message(__msg_order_different)
507 ._M_iterator(__lhs, "lhs")
508 ._M_iterator(__rhs, "rhs"));
509 return __lhs.base() <= __rhs.base();
510 }
511
512 template<typename _IteratorL, typename _IteratorR, typename _Sequence>
513 inline bool
514 operator>(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
515 const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
516 {
517 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
518 _M_message(__msg_iter_order_bad)
519 ._M_iterator(__lhs, "lhs")
520 ._M_iterator(__rhs, "rhs"));
521 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
522 _M_message(__msg_order_different)
523 ._M_iterator(__lhs, "lhs")
524 ._M_iterator(__rhs, "rhs"));
525 return __lhs.base() > __rhs.base();
526 }
527
528 template<typename _Iterator, typename _Sequence>
529 inline bool
530 operator>(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
531 const _Safe_iterator<_Iterator, _Sequence>& __rhs)
532 {
533 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
534 _M_message(__msg_iter_order_bad)
535 ._M_iterator(__lhs, "lhs")
536 ._M_iterator(__rhs, "rhs"));
537 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
538 _M_message(__msg_order_different)
539 ._M_iterator(__lhs, "lhs")
540 ._M_iterator(__rhs, "rhs"));
541 return __lhs.base() > __rhs.base();
542 }
543
544 template<typename _IteratorL, typename _IteratorR, typename _Sequence>
545 inline bool
546 operator>=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
547 const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
548 {
549 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
550 _M_message(__msg_iter_order_bad)
551 ._M_iterator(__lhs, "lhs")
552 ._M_iterator(__rhs, "rhs"));
553 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
554 _M_message(__msg_order_different)
555 ._M_iterator(__lhs, "lhs")
556 ._M_iterator(__rhs, "rhs"));
557 return __lhs.base() >= __rhs.base();
558 }
559
560 template<typename _Iterator, typename _Sequence>
561 inline bool
562 operator>=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
563 const _Safe_iterator<_Iterator, _Sequence>& __rhs)
564 {
565 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
566 _M_message(__msg_iter_order_bad)
567 ._M_iterator(__lhs, "lhs")
568 ._M_iterator(__rhs, "rhs"));
569 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
570 _M_message(__msg_order_different)
571 ._M_iterator(__lhs, "lhs")
572 ._M_iterator(__rhs, "rhs"));
573 return __lhs.base() >= __rhs.base();
574 }
575
576 // _GLIBCXX_RESOLVE_LIB_DEFECTS
577 // According to the resolution of DR179 not only the various comparison
578 // operators but also operator- must accept mixed iterator/const_iterator
579 // parameters.
580 template<typename _IteratorL, typename _IteratorR, typename _Sequence>
581 inline typename _Safe_iterator<_IteratorL, _Sequence>::difference_type
582 operator-(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
583 const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
584 {
585 _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
586 _M_message(__msg_distance_bad)
587 ._M_iterator(__lhs, "lhs")
588 ._M_iterator(__rhs, "rhs"));
589 _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
590 _M_message(__msg_distance_different)
591 ._M_iterator(__lhs, "lhs")
592 ._M_iterator(__rhs, "rhs"));
593 return __lhs.base() - __rhs.base();
594 }
595
596 template<typename _Iterator, typename _Sequence>
597 inline _Safe_iterator<_Iterator, _Sequence>
598 operator+(typename _Safe_iterator<_Iterator,_Sequence>::difference_type __n,
599 const _Safe_iterator<_Iterator, _Sequence>& __i)
600 { return __i + __n; }
601 } // namespace __gnu_debug
602
603 #ifndef _GLIBCXX_EXPORT_TEMPLATE
604 # include <debug/safe_iterator.tcc>
605 #endif
606
607 #endif