libstdc++
|
00001 // Debugging iterator implementation (out of line) -*- C++ -*- 00002 00003 // Copyright (C) 2003-2019 Free Software Foundation, Inc. 00004 // 00005 // This file is part of the GNU ISO C++ Library. This library is free 00006 // software; you can redistribute it and/or modify it under the 00007 // terms of the GNU General Public License as published by the 00008 // Free Software Foundation; either version 3, or (at your option) 00009 // any later version. 00010 00011 // This library is distributed in the hope that it will be useful, 00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 // GNU General Public License for more details. 00015 00016 // Under Section 7 of GPL version 3, you are granted additional 00017 // permissions described in the GCC Runtime Library Exception, version 00018 // 3.1, as published by the Free Software Foundation. 00019 00020 // You should have received a copy of the GNU General Public License and 00021 // a copy of the GCC Runtime Library Exception along with this program; 00022 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 00023 // <http://www.gnu.org/licenses/>. 00024 00025 /** @file debug/safe_iterator.tcc 00026 * This file is a GNU debug extension to the Standard C++ Library. 00027 */ 00028 00029 #ifndef _GLIBCXX_DEBUG_SAFE_ITERATOR_TCC 00030 #define _GLIBCXX_DEBUG_SAFE_ITERATOR_TCC 1 00031 00032 namespace __gnu_debug 00033 { 00034 template<typename _Iterator, typename _Sequence, typename _Category> 00035 typename _Distance_traits<_Iterator>::__type 00036 _Safe_iterator<_Iterator, _Sequence, _Category>:: 00037 _M_get_distance_from_begin() const 00038 { 00039 typedef _Sequence_traits<_Sequence> _SeqTraits; 00040 00041 // No need to consider before_begin as this function is only used in 00042 // _M_can_advance which won't be used for forward_list iterators. 00043 if (_M_is_begin()) 00044 return std::make_pair(0, __dp_exact); 00045 00046 if (_M_is_end()) 00047 return _SeqTraits::_S_size(*_M_get_sequence()); 00048 00049 typename _Distance_traits<_Iterator>::__type __res 00050 = __get_distance(_M_get_sequence()->_M_base().begin(), base()); 00051 00052 if (__res.second == __dp_equality) 00053 return std::make_pair(1, __dp_sign); 00054 00055 return __res; 00056 } 00057 00058 template<typename _Iterator, typename _Sequence, typename _Category> 00059 typename _Distance_traits<_Iterator>::__type 00060 _Safe_iterator<_Iterator, _Sequence, _Category>:: 00061 _M_get_distance_to_end() const 00062 { 00063 typedef _Sequence_traits<_Sequence> _SeqTraits; 00064 00065 // No need to consider before_begin as this function is only used in 00066 // _M_can_advance which won't be used for forward_list iterators. 00067 if (_M_is_begin()) 00068 return _SeqTraits::_S_size(*_M_get_sequence()); 00069 00070 if (_M_is_end()) 00071 return std::make_pair(0, __dp_exact); 00072 00073 typename _Distance_traits<_Iterator>::__type __res 00074 = __get_distance(base(), _M_get_sequence()->_M_base().end()); 00075 00076 if (__res.second == __dp_equality) 00077 return std::make_pair(1, __dp_sign); 00078 00079 return __res; 00080 } 00081 00082 template<typename _Iterator, typename _Sequence, typename _Category> 00083 bool 00084 _Safe_iterator<_Iterator, _Sequence, _Category>:: 00085 _M_can_advance(difference_type __n) const 00086 { 00087 if (this->_M_singular()) 00088 return false; 00089 00090 if (__n == 0) 00091 return true; 00092 00093 if (__n < 0) 00094 { 00095 std::pair<difference_type, _Distance_precision> __dist = 00096 _M_get_distance_from_begin(); 00097 bool __ok = ((__dist.second == __dp_exact && __dist.first >= -__n) 00098 || (__dist.second != __dp_exact && __dist.first > 0)); 00099 return __ok; 00100 } 00101 else 00102 { 00103 std::pair<difference_type, _Distance_precision> __dist = 00104 _M_get_distance_to_end(); 00105 bool __ok = ((__dist.second == __dp_exact && __dist.first >= __n) 00106 || (__dist.second != __dp_exact && __dist.first > 0)); 00107 return __ok; 00108 } 00109 } 00110 00111 template<typename _Iterator, typename _Sequence, typename _Category> 00112 typename _Distance_traits<_Iterator>::__type 00113 _Safe_iterator<_Iterator, _Sequence, _Category>:: 00114 _M_get_distance_to(const _Safe_iterator& __rhs) const 00115 { 00116 typedef typename _Distance_traits<_Iterator>::__type _Diff; 00117 typedef _Sequence_traits<_Sequence> _SeqTraits; 00118 00119 if (this->base() == __rhs.base()) 00120 return std::make_pair(0, __dp_exact); 00121 00122 if (this->_M_is_before_begin()) 00123 { 00124 if (__rhs._M_is_begin()) 00125 return std::make_pair(1, __dp_exact); 00126 00127 return std::make_pair(1, __dp_sign); 00128 } 00129 00130 if (this->_M_is_begin()) 00131 { 00132 if (__rhs._M_is_before_begin()) 00133 return std::make_pair(-1, __dp_exact); 00134 00135 if (__rhs._M_is_end()) 00136 return _SeqTraits::_S_size(*this->_M_get_sequence()); 00137 00138 return std::make_pair(1, __dp_sign); 00139 } 00140 00141 if (this->_M_is_end()) 00142 { 00143 if (__rhs._M_is_before_begin()) 00144 return std::make_pair(-1, __dp_exact); 00145 00146 if (__rhs._M_is_begin()) 00147 { 00148 _Diff __diff = _SeqTraits::_S_size(*this->_M_get_sequence()); 00149 return std::make_pair(-__diff.first, __diff.second); 00150 } 00151 00152 return std::make_pair(-1, __dp_sign); 00153 } 00154 00155 if (__rhs._M_is_before_begin() || __rhs._M_is_begin()) 00156 return std::make_pair(-1, __dp_sign); 00157 00158 if (__rhs._M_is_end()) 00159 return std::make_pair(1, __dp_sign); 00160 00161 return std::make_pair(1, __dp_equality); 00162 } 00163 00164 template<typename _Iterator, typename _Sequence, typename _Category> 00165 bool 00166 _Safe_iterator<_Iterator, _Sequence, _Category>:: 00167 _M_valid_range(const _Safe_iterator& __rhs, 00168 std::pair<difference_type, _Distance_precision>& __dist, 00169 bool __check_dereferenceable) const 00170 { 00171 if (!_M_can_compare(__rhs)) 00172 return false; 00173 00174 /* Determine iterators order */ 00175 __dist = _M_get_distance_to(__rhs); 00176 switch (__dist.second) 00177 { 00178 case __dp_equality: 00179 if (__dist.first == 0) 00180 return true; 00181 break; 00182 00183 case __dp_sign: 00184 case __dp_exact: 00185 // If range is not empty first iterator must be dereferenceable. 00186 if (__dist.first > 0) 00187 return !__check_dereferenceable || _M_dereferenceable(); 00188 return __dist.first == 0; 00189 } 00190 00191 // Assume that this is a valid range; we can't check anything else. 00192 return true; 00193 } 00194 00195 template<typename _Iterator, typename _Sequence> 00196 bool 00197 _Safe_iterator<_Iterator, _Sequence, std::random_access_iterator_tag>:: 00198 _M_valid_range(const _Safe_iterator& __rhs, 00199 std::pair<difference_type, 00200 _Distance_precision>& __dist) const 00201 { 00202 if (!this->_M_can_compare(__rhs)) 00203 return false; 00204 00205 /* Determine iterators order */ 00206 __dist = std::make_pair(__rhs.base() - this->base(), __dp_exact); 00207 00208 // If range is not empty first iterator must be dereferenceable. 00209 if (__dist.first > 0) 00210 return this->_M_dereferenceable(); 00211 return __dist.first == 0; 00212 } 00213 } // namespace __gnu_debug 00214 00215 #endif