safe_iterator.h

Go to the documentation of this file.
00001 // Safe iterator implementation  -*- C++ -*-
00002 
00003 // Copyright (C) 2003, 2004, 2005
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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
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 <debug/debug.h>
00035 #include <debug/macros.h>
00036 #include <debug/functions.h>
00037 #include <debug/formatter.h>
00038 #include <debug/safe_base.h>
00039 #include <bits/stl_pair.h>
00040 #include <bits/cpp_type_traits.h>
00041 
00042 namespace __gnu_debug
00043 {
00044   using std::iterator_traits;
00045   using std::pair;
00046 
00051   inline bool 
00052   __check_singular_aux(const _Safe_iterator_base* __x)
00053   { return __x->_M_singular(); }
00054 
00066   template<typename _Iterator, typename _Sequence>
00067     class _Safe_iterator : public _Safe_iterator_base
00068     {
00069       typedef _Safe_iterator _Self;
00070 
00074       enum _Distance_precision
00075     {
00076       __dp_equality, //< Can compare iterator equality, only
00077       __dp_sign,     //< Can determine equality and ordering
00078       __dp_exact     //< Can determine distance precisely
00079     };
00080 
00082       _Iterator _M_current;
00083 
00085       bool
00086       _M_constant() const
00087       {
00088     typedef typename _Sequence::const_iterator const_iterator;
00089     return __is_same<const_iterator, _Safe_iterator>::value;
00090       }
00091 
00092       typedef iterator_traits<_Iterator> _Traits;
00093 
00094     public:
00095       typedef _Iterator                           _Base_iterator;
00096       typedef typename _Traits::iterator_category iterator_category;
00097       typedef typename _Traits::value_type        value_type;
00098       typedef typename _Traits::difference_type   difference_type;
00099       typedef typename _Traits::reference         reference;
00100       typedef typename _Traits::pointer           pointer;
00101 
00103       _Safe_iterator() : _M_current() { }
00104 
00112       _Safe_iterator(const _Iterator& __i, const _Sequence* __seq)
00113       : _Safe_iterator_base(__seq, _M_constant()), _M_current(__i)
00114       {
00115     _GLIBCXX_DEBUG_VERIFY(! this->_M_singular(),
00116                   _M_message(__msg_init_singular)
00117                   ._M_iterator(*this, "this"));
00118       }
00119 
00124       _Safe_iterator(const _Safe_iterator& __x)
00125       : _Safe_iterator_base(__x, _M_constant()), _M_current(__x._M_current)
00126       {
00127     _GLIBCXX_DEBUG_VERIFY(!__x._M_singular(),
00128                   _M_message(__msg_init_copy_singular)
00129                   ._M_iterator(*this, "this")
00130                   ._M_iterator(__x, "other"));
00131       }
00132 
00139       template<typename _MutableIterator>
00140         _Safe_iterator(
00141           const _Safe_iterator<_MutableIterator,
00142           typename std::__enable_if<
00143                      _Sequence,
00144                      (std::__are_same<_MutableIterator,
00145                       typename _Sequence::iterator::_Base_iterator>::__value)
00146                    >::__type>& __x)
00147     : _Safe_iterator_base(__x, _M_constant()), _M_current(__x.base())
00148         {
00149       _GLIBCXX_DEBUG_VERIFY(!__x._M_singular(),
00150                 _M_message(__msg_init_const_singular)
00151                 ._M_iterator(*this, "this")
00152                 ._M_iterator(__x, "other"));
00153     }
00154 
00159       _Safe_iterator&
00160       operator=(const _Safe_iterator& __x)
00161       {
00162     _GLIBCXX_DEBUG_VERIFY(!__x._M_singular(),
00163                   _M_message(__msg_copy_singular)
00164                   ._M_iterator(*this, "this")
00165                   ._M_iterator(__x, "other"));
00166     _M_current = __x._M_current;
00167     this->_M_attach(static_cast<_Sequence*>(__x._M_sequence));
00168     return *this;
00169       }
00170 
00175       reference
00176       operator*() const
00177       {
00178 
00179     _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
00180                   _M_message(__msg_bad_deref)
00181                   ._M_iterator(*this, "this"));
00182     return *_M_current;
00183       }
00184 
00191       pointer
00192       operator->() const
00193       {
00194     _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(),
00195                   _M_message(__msg_bad_deref)
00196                   ._M_iterator(*this, "this"));
00197     return &*_M_current;
00198       }
00199 
00200       // ------ Input iterator requirements ------
00205       _Safe_iterator&
00206       operator++()
00207       {
00208     _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
00209                   _M_message(__msg_bad_inc)
00210                   ._M_iterator(*this, "this"));
00211     ++_M_current;
00212     return *this;
00213       }
00214 
00219       _Safe_iterator
00220       operator++(int)
00221       {
00222     _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
00223                   _M_message(__msg_bad_inc)
00224                   ._M_iterator(*this, "this"));
00225     _Safe_iterator __tmp(*this);
00226     ++_M_current;
00227     return __tmp;
00228       }
00229 
00230       // ------ Bidirectional iterator requirements ------
00235       _Safe_iterator&
00236       operator--()
00237       {
00238     _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
00239                   _M_message(__msg_bad_dec)
00240                   ._M_iterator(*this, "this"));
00241     --_M_current;
00242     return *this;
00243       }
00244 
00249       _Safe_iterator
00250       operator--(int)
00251       {
00252     _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(),
00253                   _M_message(__msg_bad_dec)
00254                   ._M_iterator(*this, "this"));
00255     _Safe_iterator __tmp(*this);
00256     --_M_current;
00257     return __tmp;
00258       }
00259 
00260       // ------ Random access iterator requirements ------
00261       reference
00262       operator[](const difference_type& __n) const
00263       {
00264     _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n)
00265                   && this->_M_can_advance(__n+1),
00266                   _M_message(__msg_iter_subscript_oob)
00267                   ._M_iterator(*this)._M_integer(__n));
00268 
00269     return _M_current[__n];
00270       }
00271 
00272       _Safe_iterator&
00273       operator+=(const difference_type& __n)
00274       {
00275     _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n),
00276                   _M_message(__msg_advance_oob)
00277                   ._M_iterator(*this)._M_integer(__n));
00278     _M_current += __n;
00279     return *this;
00280       }
00281 
00282       _Safe_iterator
00283       operator+(const difference_type& __n) const
00284       {
00285     _Safe_iterator __tmp(*this);
00286     __tmp += __n;
00287     return __tmp;
00288       }
00289 
00290       _Safe_iterator&
00291       operator-=(const difference_type& __n)
00292       {
00293     _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(-__n),
00294                   _M_message(__msg_retreat_oob)
00295                   ._M_iterator(*this)._M_integer(__n));
00296     _M_current += -__n;
00297     return *this;
00298       }
00299 
00300       _Safe_iterator
00301       operator-(const difference_type& __n) const
00302       {
00303     _Safe_iterator __tmp(*this);
00304     __tmp -= __n;
00305     return __tmp;
00306       }
00307 
00308       // ------ Utilities ------
00312       _Iterator
00313       base() const { return _M_current; }
00314 
00319       operator _Iterator() const { return _M_current; }
00320 
00322       void
00323       _M_attach(const _Sequence* __seq)
00324       {
00325     _Safe_iterator_base::_M_attach(const_cast<_Sequence*>(__seq),
00326                        _M_constant());
00327       }
00328 
00330       void
00331       _M_invalidate();
00332 
00334       bool
00335       _M_dereferenceable() const
00336       { return !this->_M_singular() && !_M_is_end(); }
00337 
00339       bool
00340       _M_incrementable() const { return this->_M_dereferenceable(); }
00341 
00342       // Is the iterator decrementable?
00343       bool
00344       _M_decrementable() const { return !_M_singular() && !_M_is_begin(); }
00345 
00346       // Can we advance the iterator @p __n steps (@p __n may be negative)
00347       bool
00348       _M_can_advance(const difference_type& __n) const;
00349 
00350       // Is the iterator range [*this, __rhs) valid?
00351       template<typename _Other>
00352         bool
00353         _M_valid_range(const _Safe_iterator<_Other, _Sequence>& __rhs) const;
00354 
00355       // The sequence this iterator references.
00356       const _Sequence*
00357       _M_get_sequence() const
00358       { return static_cast<const _Sequence*>(_M_sequence); }
00359 
00363     template<typename _Iterator1, typename _Iterator2>
00364       static pair<difference_type, _Distance_precision>
00365       _M_get_distance(const _Iterator1& __lhs, const _Iterator2& __rhs)
00366       {
00367         typedef typename iterator_traits<_Iterator1>::iterator_category
00368       _Category;
00369         return _M_get_distance(__lhs, __rhs, _Category());
00370       }
00371 
00372     template<typename _Iterator1, typename _Iterator2>
00373       static pair<difference_type, _Distance_precision>
00374       _M_get_distance(const _Iterator1& __lhs, const _Iterator2& __rhs,
00375               std::random_access_iterator_tag)
00376       {
00377         return std::make_pair(__rhs.base() - __lhs.base(), __dp_exact);
00378       }
00379 
00380     template<typename _Iterator1, typename _Iterator2>
00381       static pair<difference_type, _Distance_precision>
00382       _M_get_distance(const _Iterator1& __lhs, const _Iterator2& __rhs,
00383             std::forward_iterator_tag)
00384       {
00385         return std::make_pair(__lhs.base() == __rhs.base()? 0 : 1,
00386                   __dp_equality);
00387       }
00388 
00390       bool _M_is_begin() const
00391       { return *this == static_cast<const _Sequence*>(_M_sequence)->begin(); }
00392 
00394       bool _M_is_end() const
00395       { return *this == static_cast<const _Sequence*>(_M_sequence)->end(); }
00396     };
00397 
00398   template<typename _IteratorL, typename _IteratorR, typename _Sequence>
00399     inline bool
00400     operator==(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
00401            const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
00402     {
00403       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
00404                 _M_message(__msg_iter_compare_bad)
00405                 ._M_iterator(__lhs, "lhs")
00406                 ._M_iterator(__rhs, "rhs"));
00407       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
00408                 _M_message(__msg_compare_different)
00409                 ._M_iterator(__lhs, "lhs")
00410                 ._M_iterator(__rhs, "rhs"));
00411       return __lhs.base() == __rhs.base();
00412     }
00413 
00414   template<typename _Iterator, typename _Sequence>
00415     inline bool
00416     operator==(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
00417                const _Safe_iterator<_Iterator, _Sequence>& __rhs)
00418     {
00419       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
00420                 _M_message(__msg_iter_compare_bad)
00421                 ._M_iterator(__lhs, "lhs")
00422                 ._M_iterator(__rhs, "rhs"));
00423       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
00424                 _M_message(__msg_compare_different)
00425                 ._M_iterator(__lhs, "lhs")
00426                 ._M_iterator(__rhs, "rhs"));
00427       return __lhs.base() == __rhs.base();
00428     }
00429 
00430   template<typename _IteratorL, typename _IteratorR, typename _Sequence>
00431     inline bool
00432     operator!=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
00433            const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
00434     {
00435       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
00436                 _M_message(__msg_iter_compare_bad)
00437                 ._M_iterator(__lhs, "lhs")
00438                 ._M_iterator(__rhs, "rhs"));
00439       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
00440                 _M_message(__msg_compare_different)
00441                 ._M_iterator(__lhs, "lhs")
00442                 ._M_iterator(__rhs, "rhs"));
00443       return __lhs.base() != __rhs.base();
00444     }
00445 
00446   template<typename _Iterator, typename _Sequence>
00447     inline bool
00448     operator!=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
00449                const _Safe_iterator<_Iterator, _Sequence>& __rhs)
00450     {
00451       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
00452                 _M_message(__msg_iter_compare_bad)
00453                 ._M_iterator(__lhs, "lhs")
00454                 ._M_iterator(__rhs, "rhs"));
00455       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
00456                 _M_message(__msg_compare_different)
00457                 ._M_iterator(__lhs, "lhs")
00458                 ._M_iterator(__rhs, "rhs"));
00459       return __lhs.base() != __rhs.base();
00460     }
00461 
00462   template<typename _IteratorL, typename _IteratorR, typename _Sequence>
00463     inline bool
00464     operator<(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
00465           const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
00466     {
00467       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
00468                 _M_message(__msg_iter_order_bad)
00469                 ._M_iterator(__lhs, "lhs")
00470                 ._M_iterator(__rhs, "rhs"));
00471       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
00472                 _M_message(__msg_order_different)
00473                 ._M_iterator(__lhs, "lhs")
00474                 ._M_iterator(__rhs, "rhs"));
00475       return __lhs.base() < __rhs.base();
00476     }
00477 
00478   template<typename _Iterator, typename _Sequence>
00479     inline bool
00480     operator<(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
00481           const _Safe_iterator<_Iterator, _Sequence>& __rhs)
00482     {
00483       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
00484                 _M_message(__msg_iter_order_bad)
00485                 ._M_iterator(__lhs, "lhs")
00486                 ._M_iterator(__rhs, "rhs"));
00487       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
00488                 _M_message(__msg_order_different)
00489                 ._M_iterator(__lhs, "lhs")
00490                 ._M_iterator(__rhs, "rhs"));
00491       return __lhs.base() < __rhs.base();
00492     }
00493 
00494   template<typename _IteratorL, typename _IteratorR, typename _Sequence>
00495     inline bool
00496     operator<=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
00497            const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
00498     {
00499       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
00500                 _M_message(__msg_iter_order_bad)
00501                 ._M_iterator(__lhs, "lhs")
00502                 ._M_iterator(__rhs, "rhs"));
00503       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
00504                 _M_message(__msg_order_different)
00505                 ._M_iterator(__lhs, "lhs")
00506                 ._M_iterator(__rhs, "rhs"));
00507       return __lhs.base() <= __rhs.base();
00508     }
00509 
00510   template<typename _Iterator, typename _Sequence>
00511     inline bool
00512     operator<=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
00513                const _Safe_iterator<_Iterator, _Sequence>& __rhs)
00514     {
00515       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
00516                 _M_message(__msg_iter_order_bad)
00517                 ._M_iterator(__lhs, "lhs")
00518                 ._M_iterator(__rhs, "rhs"));
00519       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
00520                 _M_message(__msg_order_different)
00521                 ._M_iterator(__lhs, "lhs")
00522                 ._M_iterator(__rhs, "rhs"));
00523       return __lhs.base() <= __rhs.base();
00524     }
00525 
00526   template<typename _IteratorL, typename _IteratorR, typename _Sequence>
00527     inline bool
00528     operator>(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
00529           const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
00530     {
00531       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
00532                 _M_message(__msg_iter_order_bad)
00533                 ._M_iterator(__lhs, "lhs")
00534                 ._M_iterator(__rhs, "rhs"));
00535       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
00536                 _M_message(__msg_order_different)
00537                 ._M_iterator(__lhs, "lhs")
00538                 ._M_iterator(__rhs, "rhs"));
00539       return __lhs.base() > __rhs.base();
00540     }
00541 
00542   template<typename _Iterator, typename _Sequence>
00543     inline bool
00544     operator>(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
00545           const _Safe_iterator<_Iterator, _Sequence>& __rhs)
00546     {
00547       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
00548                 _M_message(__msg_iter_order_bad)
00549                 ._M_iterator(__lhs, "lhs")
00550                 ._M_iterator(__rhs, "rhs"));
00551       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
00552                 _M_message(__msg_order_different)
00553                 ._M_iterator(__lhs, "lhs")
00554                 ._M_iterator(__rhs, "rhs"));
00555       return __lhs.base() > __rhs.base();
00556     }
00557 
00558   template<typename _IteratorL, typename _IteratorR, typename _Sequence>
00559     inline bool
00560     operator>=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
00561            const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
00562     {
00563       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
00564                 _M_message(__msg_iter_order_bad)
00565                 ._M_iterator(__lhs, "lhs")
00566                 ._M_iterator(__rhs, "rhs"));
00567       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
00568                 _M_message(__msg_order_different)
00569                 ._M_iterator(__lhs, "lhs")
00570                 ._M_iterator(__rhs, "rhs"));
00571       return __lhs.base() >= __rhs.base();
00572     }
00573 
00574   template<typename _Iterator, typename _Sequence>
00575     inline bool
00576     operator>=(const _Safe_iterator<_Iterator, _Sequence>& __lhs,
00577                const _Safe_iterator<_Iterator, _Sequence>& __rhs)
00578     {
00579       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
00580                 _M_message(__msg_iter_order_bad)
00581                 ._M_iterator(__lhs, "lhs")
00582                 ._M_iterator(__rhs, "rhs"));
00583       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
00584                 _M_message(__msg_order_different)
00585                 ._M_iterator(__lhs, "lhs")
00586                 ._M_iterator(__rhs, "rhs"));
00587       return __lhs.base() >= __rhs.base();
00588     }
00589 
00590   // _GLIBCXX_RESOLVE_LIB_DEFECTS
00591   // According to the resolution of DR179 not only the various comparison
00592   // operators but also operator- must accept mixed iterator/const_iterator
00593   // parameters.
00594   template<typename _IteratorL, typename _IteratorR, typename _Sequence>
00595     inline typename _Safe_iterator<_IteratorL, _Sequence>::difference_type
00596     operator-(const _Safe_iterator<_IteratorL, _Sequence>& __lhs,
00597           const _Safe_iterator<_IteratorR, _Sequence>& __rhs)
00598     {
00599       _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(),
00600                 _M_message(__msg_distance_bad)
00601                 ._M_iterator(__lhs, "lhs")
00602                 ._M_iterator(__rhs, "rhs"));
00603       _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs),
00604                 _M_message(__msg_distance_different)
00605                 ._M_iterator(__lhs, "lhs")
00606                 ._M_iterator(__rhs, "rhs"));
00607       return __lhs.base() - __rhs.base();
00608     }
00609 
00610   template<typename _Iterator, typename _Sequence>
00611     inline _Safe_iterator<_Iterator, _Sequence>
00612     operator+(typename _Safe_iterator<_Iterator,_Sequence>::difference_type __n,
00613           const _Safe_iterator<_Iterator, _Sequence>& __i)
00614     { return __i + __n; }
00615 } // namespace __gnu_debug
00616 
00617 #ifndef _GLIBCXX_EXPORT_TEMPLATE
00618 #  include <debug/safe_iterator.tcc>
00619 #endif
00620 
00621 #endif

Generated on Tue Feb 2 16:56:27 2010 for GNU C++ STL by  doxygen 1.4.7