safe_iterator.h

Go to the documentation of this file.
00001 // Safe iterator implementation  -*- C++ -*-
00002 
00003 // Copyright (C) 2003, 2004
00004 // Free Software Foundation, Inc.
00005 //
00006 // This file is part of the GNU ISO C++ Library.  This library is free
00007 // software; you can redistribute it and/or modify it under the
00008 // terms of the GNU General Public License as published by the
00009 // Free Software Foundation; either version 2, or (at your option)
00010 // any later version.
00011 
00012 // This library is distributed in the hope that it will be useful,
00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 // GNU General Public License for more details.
00016 
00017 // You should have received a copy of the GNU General Public License along
00018 // with this library; see the file COPYING.  If not, write to the Free
00019 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
00020 // USA.
00021 
00022 // As a special exception, you may use this file as part of a free software
00023 // library without restriction.  Specifically, if other files instantiate
00024 // templates or use macros or inline functions from this file, or you compile
00025 // this file and link it with other files to produce an executable, this
00026 // file does not by itself cause the resulting executable to be covered by
00027 // the GNU General Public License.  This exception does not however
00028 // invalidate any other reasons why the executable file might be covered by
00029 // the GNU General Public License.
00030 
00031 #ifndef _GLIBCXX_DEBUG_SAFE_ITERATOR_H
00032 #define _GLIBCXX_DEBUG_SAFE_ITERATOR_H 1
00033 
00034 #include <bits/stl_pair.h>
00035 #include <debug/debug.h>
00036 #include <debug/formatter.h>
00037 #include <debug/safe_base.h>
00038 #include <bits/cpp_type_traits.h>
00039 
00040 namespace __gnu_debug
00041 {
00042   using std::iterator_traits;
00043   using std::pair;
00044 
00049   inline bool __check_singular_aux(const _Safe_iterator_base* __x)
00050   { return __x->_M_singular(); }
00051 
00063   template<typename _Iterator, typename _Sequence>
00064     class _Safe_iterator : public _Safe_iterator_base
00065     {
00066       typedef _Safe_iterator _Self;
00067 
00071       enum _Distance_precision
00072     {
00073       __dp_equality, //< Can compare iterator equality, only
00074       __dp_sign,     //< Can determine equality and ordering
00075       __dp_exact     //< Can determine distance precisely
00076     };
00077 
00079       _Iterator _M_current;
00080 
00082       bool
00083       _M_constant() const
00084       {
00085     typedef typename _Sequence::const_iterator const_iterator;
00086     return __is_same<const_iterator, _Safe_iterator>::value;
00087       }
00088 
00089       typedef iterator_traits<_Iterator> _Traits;
00090 
00091     public:
00092       typedef _Iterator                           _Base_iterator;
00093       typedef typename _Traits::iterator_category iterator_category;
00094       typedef typename _Traits::value_type        value_type;
00095       typedef typename _Traits::difference_type   difference_type;
00096       typedef typename _Traits::reference         reference;
00097       typedef typename _Traits::pointer           pointer;
00098 
00100       _Safe_iterator() : _M_current() { }
00101 
00109       _Safe_iterator(const _Iterator& __i, const _Sequence* __seq)
00110       : _Safe_iterator_base(__seq, _M_constant()), _M_current(__i)
00111       {
00112     _GLIBCXX_DEBUG_VERIFY(! this->_M_singular(),
00113                   _M_message(__msg_init_singular)
00114                   ._M_iterator(*this, "this"));
00115       }
00116 
00121       _Safe_iterator(const _Safe_iterator& __x)
00122       : _Safe_iterator_base(__x, _M_constant()), _M_current(__x._M_current)
00123       {
00124     _GLIBCXX_DEBUG_VERIFY(!__x._M_singular(),
00125                   _M_message(__msg_init_copy_singular)
00126                   ._M_iterator(*this, "this")
00127                   ._M_iterator(__x, "other"));
00128       }
00129 
00136       template<typename _MutableIterator>
00137         _Safe_iterator(
00138           const _Safe_iterator<_MutableIterator,
00139           typename std::__enable_if<
00140                      _Sequence,
00141                      (std::__are_same<_MutableIterator,
00142                       typename _Sequence::iterator::_Base_iterator>::_M_type)
00143                    >::_M_type>& __x)
00144     : _Safe_iterator_base(__x, _M_constant()), _M_current(__x.base())
00145         {
00146       _GLIBCXX_DEBUG_VERIFY(!__x._M_singular(),
00147                 _M_message(__msg_init_const_singular)
00148                 ._M_iterator(*this, "this")
00149                 ._M_iterator(__x, "other"));
00150     }
00151 
00156       _Safe_iterator&
00157       operator=(const _Safe_iterator& __x)
00158       {
00159     _GLIBCXX_DEBUG_VERIFY(!__x._M_singular(),
00160                   _M_message(__msg_copy_singular)
00161                   ._M_iterator(*this, "this")
00162                   ._M_iterator(__x, "other"));
00163     _M_current = __x._M_current;
00164     this->_M_attach(static_cast<_Sequence*>(__x._M_sequence));
00165     return *this;
00166       }
00167 
00172       reference
00173       operator*() const
00174       {
00175 
00176     _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
00177                   _M_message(__msg_bad_deref)
00178                   ._M_iterator(*this, "this"));
00179     return *_M_current;
00180       }
00181 
00188       pointer
00189       operator->() const
00190       {
00191     _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
00192                   _M_message(__msg_bad_deref)
00193                   ._M_iterator(*this, "this"));
00194     return &*_M_current;
00195       }
00196 
00197       // ------ Input iterator requirements ------
00202       _Safe_iterator&
00203       operator++()
00204       {
00205     _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
00206                   _M_message(__msg_bad_inc)
00207                   ._M_iterator(*this, "this"));
00208     ++_M_current;
00209     return *this;
00210       }
00211 
00216       _Safe_iterator
00217       operator++(int)
00218       {
00219     _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
00220                   _M_message(__msg_bad_inc)
00221                   ._M_iterator(*this, "this"));
00222     _Safe_iterator __tmp(*this);
00223     ++_M_current;
00224     return __tmp;
00225       }
00226 
00227       // ------ Bidirectional iterator requirements ------
00232       _Safe_iterator&
00233       operator--()
00234       {
00235     _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
00236                   _M_message(__msg_bad_dec)
00237                   ._M_iterator(*this, "this"));
00238     --_M_current;
00239     return *this;
00240       }
00241 
00246       _Safe_iterator
00247       operator--(int)
00248       {
00249     _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
00250                   _M_message(__msg_bad_dec)
00251                   ._M_iterator(*this, "this"));
00252     _Safe_iterator __tmp(*this);
00253     --_M_current;
00254     return __tmp;
00255       }
00256 
00257       // ------ Random access iterator requirements ------
00258       reference
00259       operator[](const difference_type& __n) const
00260       {
00261     _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n)
00262                   && this->_M_can_advance(__n+1),
00263                   _M_message(__msg_iter_subscript_oob)
00264                   ._M_iterator(*this)._M_integer(__n));
00265 
00266     return _M_current[__n];
00267       }
00268 
00269       _Safe_iterator&
00270       operator+=(const difference_type& __n)
00271       {
00272     _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n),
00273                   _M_message(__msg_advance_oob)
00274                   ._M_iterator(*this)._M_integer(__n));
00275     _M_current += __n;
00276     return *this;
00277       }
00278 
00279       _Safe_iterator
00280       operator+(const difference_type& __n) const
00281       {
00282     _Safe_iterator __tmp(*this);
00283     __tmp += __n;
00284     return __tmp;
00285       }
00286 
00287       _Safe_iterator&
00288       operator-=(const difference_type& __n)
00289       {
00290     _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(-__n),
00291                   _M_message(__msg_retreat_oob)
00292                   ._M_iterator(*this)._M_integer(__n));
00293     _M_current += -__n;
00294     return *this;
00295       }
00296 
00297       _Safe_iterator
00298       operator-(const difference_type& __n) const
00299       {
00300     _Safe_iterator __tmp(*this);
00301     __tmp -= __n;
00302     return __tmp;
00303       }
00304 
00305       // ------ Utilities ------
00309       _Iterator
00310       base() const { return _M_current; }
00311 
00316       operator _Iterator() const { return _M_current; }
00317 
00319       void
00320       _M_attach(const _Sequence* __seq)
00321       {
00322     _Safe_iterator_base::_M_attach(const_cast<_Sequence*>(__seq),
00323                        _M_constant());
00324       }
00325 
00327       void
00328       _M_invalidate();
00329 
00331       bool
00332       _M_dereferenceable() const
00333       { return !this->_M_singular() && !_M_is_end(); }
00334 
00336       bool
00337       _M_incrementable() const { return this->_M_dereferenceable(); }
00338 
00339       // Is the iterator decrementable?
00340       bool
00341       _M_decrementable() const { return !_M_singular() && !_M_is_begin(); }
00342 
00343       // Can we advance the iterator @p __n steps (@p __n may be negative)
00344       bool
00345       _M_can_advance(const difference_type& __n) const;
00346 
00347       // Is the iterator range [*this, __rhs) valid?
00348       template<typename _Other>
00349         bool
00350         _M_valid_range(const _Safe_iterator<_Other, _Sequence>& __rhs) const;
00351 
00352       // The sequence this iterator references.
00353       const _Sequence*
00354       _M_get_sequence() const
00355       { return static_cast<const _Sequence*>(_M_sequence); }
00356 
00360     template<typename _Iterator1, typename _Iterator2>
00361       static pair<difference_type, _Distance_precision>
00362       _M_get_distance(const _Iterator1& __lhs, const _Iterator2& __rhs)
00363       {
00364         typedef typename iterator_traits<_Iterator1>::iterator_category
00365       _Category;
00366         return _M_get_distance(__lhs, __rhs, _Category());
00367       }
00368 
00369     template<typename _Iterator1, typename _Iterator2>
00370       static pair<difference_type, _Distance_precision>
00371       _M_get_distance(const _Iterator1& __lhs, const _Iterator2& __rhs,
00372               std::random_access_iterator_tag)
00373       {
00374         return std::make_pair(__rhs.base() - __lhs.base(), __dp_exact);
00375       }
00376 
00377     template<typename _Iterator1, typename _Iterator2>
00378       static pair<difference_type, _Distance_precision>
00379       _M_get_distance(const _Iterator1& __lhs, const _Iterator2& __rhs,
00380             std::forward_iterator_tag)
00381       {
00382         return std::make_pair(__lhs.base() == __rhs.base()? 0 : 1,
00383                   __dp_equality);
00384       }
00385 
00387       bool _M_is_begin() const
00388       { return *this == static_cast<const _Sequence*>(_M_sequence)->begin(); }
00389 
00391       bool _M_is_end() const
00392       { return *this == static_cast<const _Sequence*>(_M_sequence)->end(); }
00393     };
00394 
00395   template<typename _IteratorL, typename _IteratorR, typename _Sequence>
00396     inline bool
00397     operator==(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
00398            const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
00399     {
00400       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
00401                 _M_message(__msg_iter_compare_bad)
00402                 ._M_iterator(__lhs, "lhs")
00403                 ._M_iterator(__rhs, "rhs"));
00404       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
00405                 _M_message(__msg_compare_different)
00406                 ._M_iterator(__lhs, "lhs")
00407                 ._M_iterator(__rhs, "rhs"));
00408       return __lhs.base() == __rhs.base();
00409     }
00410 
00411   template<typename _Iterator, typename _Sequence>
00412     inline bool
00413     operator==(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
00414                const _Safe_iterator<_Iterator, _Sequence>& __rhs)
00415     {
00416       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
00417                 _M_message(__msg_iter_compare_bad)
00418                 ._M_iterator(__lhs, "lhs")
00419                 ._M_iterator(__rhs, "rhs"));
00420       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
00421                 _M_message(__msg_compare_different)
00422                 ._M_iterator(__lhs, "lhs")
00423                 ._M_iterator(__rhs, "rhs"));
00424       return __lhs.base() == __rhs.base();
00425     }
00426 
00427   template<typename _IteratorL, typename _IteratorR, typename _Sequence>
00428     inline bool
00429     operator!=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
00430            const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
00431     {
00432       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
00433                 _M_message(__msg_iter_compare_bad)
00434                 ._M_iterator(__lhs, "lhs")
00435                 ._M_iterator(__rhs, "rhs"));
00436       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
00437                 _M_message(__msg_compare_different)
00438                 ._M_iterator(__lhs, "lhs")
00439                 ._M_iterator(__rhs, "rhs"));
00440       return __lhs.base() != __rhs.base();
00441     }
00442 
00443   template<typename _Iterator, typename _Sequence>
00444     inline bool
00445     operator!=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
00446                const _Safe_iterator<_Iterator, _Sequence>& __rhs)
00447     {
00448       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
00449                 _M_message(__msg_iter_compare_bad)
00450                 ._M_iterator(__lhs, "lhs")
00451                 ._M_iterator(__rhs, "rhs"));
00452       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
00453                 _M_message(__msg_compare_different)
00454                 ._M_iterator(__lhs, "lhs")
00455                 ._M_iterator(__rhs, "rhs"));
00456       return __lhs.base() != __rhs.base();
00457     }
00458 
00459   template<typename _IteratorL, typename _IteratorR, typename _Sequence>
00460     inline bool
00461     operator<(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
00462           const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
00463     {
00464       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
00465                 _M_message(__msg_iter_order_bad)
00466                 ._M_iterator(__lhs, "lhs")
00467                 ._M_iterator(__rhs, "rhs"));
00468       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
00469                 _M_message(__msg_order_different)
00470                 ._M_iterator(__lhs, "lhs")
00471                 ._M_iterator(__rhs, "rhs"));
00472       return __lhs.base() < __rhs.base();
00473     }
00474 
00475   template<typename _Iterator, typename _Sequence>
00476     inline bool
00477     operator<(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
00478           const _Safe_iterator<_Iterator, _Sequence>& __rhs)
00479     {
00480       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
00481                 _M_message(__msg_iter_order_bad)
00482                 ._M_iterator(__lhs, "lhs")
00483                 ._M_iterator(__rhs, "rhs"));
00484       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
00485                 _M_message(__msg_order_different)
00486                 ._M_iterator(__lhs, "lhs")
00487                 ._M_iterator(__rhs, "rhs"));
00488       return __lhs.base() < __rhs.base();
00489     }
00490 
00491   template<typename _IteratorL, typename _IteratorR, typename _Sequence>
00492     inline bool
00493     operator<=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
00494            const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
00495     {
00496       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
00497                 _M_message(__msg_iter_order_bad)
00498                 ._M_iterator(__lhs, "lhs")
00499                 ._M_iterator(__rhs, "rhs"));
00500       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
00501                 _M_message(__msg_order_different)
00502                 ._M_iterator(__lhs, "lhs")
00503                 ._M_iterator(__rhs, "rhs"));
00504       return __lhs.base() <= __rhs.base();
00505     }
00506 
00507   template<typename _Iterator, typename _Sequence>
00508     inline bool
00509     operator<=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
00510                const _Safe_iterator<_Iterator, _Sequence>& __rhs)
00511     {
00512       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
00513                 _M_message(__msg_iter_order_bad)
00514                 ._M_iterator(__lhs, "lhs")
00515                 ._M_iterator(__rhs, "rhs"));
00516       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
00517                 _M_message(__msg_order_different)
00518                 ._M_iterator(__lhs, "lhs")
00519                 ._M_iterator(__rhs, "rhs"));
00520       return __lhs.base() <= __rhs.base();
00521     }
00522 
00523   template<typename _IteratorL, typename _IteratorR, typename _Sequence>
00524     inline bool
00525     operator>(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
00526           const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
00527     {
00528       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
00529                 _M_message(__msg_iter_order_bad)
00530                 ._M_iterator(__lhs, "lhs")
00531                 ._M_iterator(__rhs, "rhs"));
00532       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
00533                 _M_message(__msg_order_different)
00534                 ._M_iterator(__lhs, "lhs")
00535                 ._M_iterator(__rhs, "rhs"));
00536       return __lhs.base() > __rhs.base();
00537     }
00538 
00539   template<typename _Iterator, typename _Sequence>
00540     inline bool
00541     operator>(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
00542           const _Safe_iterator<_Iterator, _Sequence>& __rhs)
00543     {
00544       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
00545                 _M_message(__msg_iter_order_bad)
00546                 ._M_iterator(__lhs, "lhs")
00547                 ._M_iterator(__rhs, "rhs"));
00548       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
00549                 _M_message(__msg_order_different)
00550                 ._M_iterator(__lhs, "lhs")
00551                 ._M_iterator(__rhs, "rhs"));
00552       return __lhs.base() > __rhs.base();
00553     }
00554 
00555   template<typename _IteratorL, typename _IteratorR, typename _Sequence>
00556     inline bool
00557     operator>=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
00558            const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
00559     {
00560       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
00561                 _M_message(__msg_iter_order_bad)
00562                 ._M_iterator(__lhs, "lhs")
00563                 ._M_iterator(__rhs, "rhs"));
00564       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
00565                 _M_message(__msg_order_different)
00566                 ._M_iterator(__lhs, "lhs")
00567                 ._M_iterator(__rhs, "rhs"));
00568       return __lhs.base() >= __rhs.base();
00569     }
00570 
00571   template<typename _Iterator, typename _Sequence>
00572     inline bool
00573     operator>=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
00574                const _Safe_iterator<_Iterator, _Sequence>& __rhs)
00575     {
00576       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
00577                 _M_message(__msg_iter_order_bad)
00578                 ._M_iterator(__lhs, "lhs")
00579                 ._M_iterator(__rhs, "rhs"));
00580       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
00581                 _M_message(__msg_order_different)
00582                 ._M_iterator(__lhs, "lhs")
00583                 ._M_iterator(__rhs, "rhs"));
00584       return __lhs.base() >= __rhs.base();
00585     }
00586 
00587   // _GLIBCXX_RESOLVE_LIB_DEFECTS
00588   // According to the resolution of DR179 not only the various comparison
00589   // operators but also operator- must accept mixed iterator/const_iterator
00590   // parameters.
00591   template<typename _IteratorL, typename _IteratorR, typename _Sequence>
00592     inline typename _Safe_iterator<_IteratorL, _Sequence>::difference_type
00593     operator-(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
00594           const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
00595     {
00596       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
00597                 _M_message(__msg_distance_bad)
00598                 ._M_iterator(__lhs, "lhs")
00599                 ._M_iterator(__rhs, "rhs"));
00600       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
00601                 _M_message(__msg_distance_different)
00602                 ._M_iterator(__lhs, "lhs")
00603                 ._M_iterator(__rhs, "rhs"));
00604       return __lhs.base() - __rhs.base();
00605     }
00606 
00607   template<typename _Iterator, typename _Sequence>
00608     inline _Safe_iterator<_Iterator, _Sequence>
00609     operator+(typename _Safe_iterator<_Iterator,_Sequence>::difference_type __n,
00610           const _Safe_iterator<_Iterator, _Sequence>& __i)
00611     { return __i + __n; }
00612 } // namespace __gnu_debug
00613 
00614 #ifndef _GLIBCXX_EXPORT_TEMPLATE
00615 #  include <debug/safe_iterator.tcc>
00616 #endif
00617 
00618 #endif

Generated on Tue Jan 30 17:31:52 2007 for GNU C++ STL by doxygen 1.3.6