safe_iterator.tcc 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. // Debugging iterator implementation (out of line) -*- C++ -*-
  2. // Copyright (C) 2003-2019 Free Software Foundation, Inc.
  3. //
  4. // This file is part of the GNU ISO C++ Library. This library is free
  5. // software; you can redistribute it and/or modify it under the
  6. // terms of the GNU General Public License as published by the
  7. // Free Software Foundation; either version 3, or (at your option)
  8. // any later version.
  9. // This library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. // Under Section 7 of GPL version 3, you are granted additional
  14. // permissions described in the GCC Runtime Library Exception, version
  15. // 3.1, as published by the Free Software Foundation.
  16. // You should have received a copy of the GNU General Public License and
  17. // a copy of the GCC Runtime Library Exception along with this program;
  18. // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
  19. // <http://www.gnu.org/licenses/>.
  20. /** @file debug/safe_iterator.tcc
  21. * This file is a GNU debug extension to the Standard C++ Library.
  22. */
  23. #ifndef _GLIBCXX_DEBUG_SAFE_ITERATOR_TCC
  24. #define _GLIBCXX_DEBUG_SAFE_ITERATOR_TCC 1
  25. namespace __gnu_debug
  26. {
  27. template<typename _Iterator, typename _Sequence, typename _Category>
  28. typename _Distance_traits<_Iterator>::__type
  29. _Safe_iterator<_Iterator, _Sequence, _Category>::
  30. _M_get_distance_from_begin() const
  31. {
  32. typedef _Sequence_traits<_Sequence> _SeqTraits;
  33. // No need to consider before_begin as this function is only used in
  34. // _M_can_advance which won't be used for forward_list iterators.
  35. if (_M_is_begin())
  36. return std::make_pair(0, __dp_exact);
  37. if (_M_is_end())
  38. return _SeqTraits::_S_size(*_M_get_sequence());
  39. typename _Distance_traits<_Iterator>::__type __res
  40. = __get_distance(_M_get_sequence()->_M_base().begin(), base());
  41. if (__res.second == __dp_equality)
  42. return std::make_pair(1, __dp_sign);
  43. return __res;
  44. }
  45. template<typename _Iterator, typename _Sequence, typename _Category>
  46. typename _Distance_traits<_Iterator>::__type
  47. _Safe_iterator<_Iterator, _Sequence, _Category>::
  48. _M_get_distance_to_end() const
  49. {
  50. typedef _Sequence_traits<_Sequence> _SeqTraits;
  51. // No need to consider before_begin as this function is only used in
  52. // _M_can_advance which won't be used for forward_list iterators.
  53. if (_M_is_begin())
  54. return _SeqTraits::_S_size(*_M_get_sequence());
  55. if (_M_is_end())
  56. return std::make_pair(0, __dp_exact);
  57. typename _Distance_traits<_Iterator>::__type __res
  58. = __get_distance(base(), _M_get_sequence()->_M_base().end());
  59. if (__res.second == __dp_equality)
  60. return std::make_pair(1, __dp_sign);
  61. return __res;
  62. }
  63. template<typename _Iterator, typename _Sequence, typename _Category>
  64. bool
  65. _Safe_iterator<_Iterator, _Sequence, _Category>::
  66. _M_can_advance(difference_type __n) const
  67. {
  68. if (this->_M_singular())
  69. return false;
  70. if (__n == 0)
  71. return true;
  72. if (__n < 0)
  73. {
  74. std::pair<difference_type, _Distance_precision> __dist =
  75. _M_get_distance_from_begin();
  76. bool __ok = ((__dist.second == __dp_exact && __dist.first >= -__n)
  77. || (__dist.second != __dp_exact && __dist.first > 0));
  78. return __ok;
  79. }
  80. else
  81. {
  82. std::pair<difference_type, _Distance_precision> __dist =
  83. _M_get_distance_to_end();
  84. bool __ok = ((__dist.second == __dp_exact && __dist.first >= __n)
  85. || (__dist.second != __dp_exact && __dist.first > 0));
  86. return __ok;
  87. }
  88. }
  89. template<typename _Iterator, typename _Sequence, typename _Category>
  90. typename _Distance_traits<_Iterator>::__type
  91. _Safe_iterator<_Iterator, _Sequence, _Category>::
  92. _M_get_distance_to(const _Safe_iterator& __rhs) const
  93. {
  94. typedef typename _Distance_traits<_Iterator>::__type _Diff;
  95. typedef _Sequence_traits<_Sequence> _SeqTraits;
  96. if (this->base() == __rhs.base())
  97. return std::make_pair(0, __dp_exact);
  98. if (this->_M_is_before_begin())
  99. {
  100. if (__rhs._M_is_begin())
  101. return std::make_pair(1, __dp_exact);
  102. return std::make_pair(1, __dp_sign);
  103. }
  104. if (this->_M_is_begin())
  105. {
  106. if (__rhs._M_is_before_begin())
  107. return std::make_pair(-1, __dp_exact);
  108. if (__rhs._M_is_end())
  109. return _SeqTraits::_S_size(*this->_M_get_sequence());
  110. return std::make_pair(1, __dp_sign);
  111. }
  112. if (this->_M_is_end())
  113. {
  114. if (__rhs._M_is_before_begin())
  115. return std::make_pair(-1, __dp_exact);
  116. if (__rhs._M_is_begin())
  117. {
  118. _Diff __diff = _SeqTraits::_S_size(*this->_M_get_sequence());
  119. return std::make_pair(-__diff.first, __diff.second);
  120. }
  121. return std::make_pair(-1, __dp_sign);
  122. }
  123. if (__rhs._M_is_before_begin() || __rhs._M_is_begin())
  124. return std::make_pair(-1, __dp_sign);
  125. if (__rhs._M_is_end())
  126. return std::make_pair(1, __dp_sign);
  127. return std::make_pair(1, __dp_equality);
  128. }
  129. template<typename _Iterator, typename _Sequence, typename _Category>
  130. bool
  131. _Safe_iterator<_Iterator, _Sequence, _Category>::
  132. _M_valid_range(const _Safe_iterator& __rhs,
  133. std::pair<difference_type, _Distance_precision>& __dist,
  134. bool __check_dereferenceable) const
  135. {
  136. if (!_M_can_compare(__rhs))
  137. return false;
  138. /* Determine iterators order */
  139. __dist = _M_get_distance_to(__rhs);
  140. switch (__dist.second)
  141. {
  142. case __dp_equality:
  143. if (__dist.first == 0)
  144. return true;
  145. break;
  146. case __dp_sign:
  147. case __dp_exact:
  148. // If range is not empty first iterator must be dereferenceable.
  149. if (__dist.first > 0)
  150. return !__check_dereferenceable || _M_dereferenceable();
  151. return __dist.first == 0;
  152. }
  153. // Assume that this is a valid range; we can't check anything else.
  154. return true;
  155. }
  156. template<typename _Iterator, typename _Sequence>
  157. bool
  158. _Safe_iterator<_Iterator, _Sequence, std::random_access_iterator_tag>::
  159. _M_valid_range(const _Safe_iterator& __rhs,
  160. std::pair<difference_type,
  161. _Distance_precision>& __dist) const
  162. {
  163. if (!this->_M_can_compare(__rhs))
  164. return false;
  165. /* Determine iterators order */
  166. __dist = std::make_pair(__rhs.base() - this->base(), __dp_exact);
  167. // If range is not empty first iterator must be dereferenceable.
  168. if (__dist.first > 0)
  169. return this->_M_dereferenceable();
  170. return __dist.first == 0;
  171. }
  172. } // namespace __gnu_debug
  173. #endif