helper_functions.h 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. // Debugging support implementation -*- C++ -*-
  2. // Copyright (C) 2003-2018 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/helper_functions.h
  21. * This file is a GNU debug extension to the Standard C++ Library.
  22. */
  23. #ifndef _GLIBCXX_DEBUG_HELPER_FUNCTIONS_H
  24. #define _GLIBCXX_DEBUG_HELPER_FUNCTIONS_H 1
  25. #include <bits/stl_iterator_base_types.h> // for iterator_traits,
  26. // categories and _Iter_base
  27. #include <bits/cpp_type_traits.h> // for __is_integer
  28. #include <bits/stl_pair.h> // for pair
  29. namespace __gnu_debug
  30. {
  31. /** The precision to which we can calculate the distance between
  32. * two iterators.
  33. */
  34. enum _Distance_precision
  35. {
  36. __dp_none, // Not even an iterator type
  37. __dp_equality, //< Can compare iterator equality, only
  38. __dp_sign, //< Can determine equality and ordering
  39. __dp_exact //< Can determine distance precisely
  40. };
  41. template<typename _Iterator,
  42. typename = typename std::__is_integer<_Iterator>::__type>
  43. struct _Distance_traits
  44. {
  45. private:
  46. typedef
  47. typename std::iterator_traits<_Iterator>::difference_type _ItDiffType;
  48. template<typename _DiffType,
  49. typename = typename std::__is_void<_DiffType>::__type>
  50. struct _DiffTraits
  51. { typedef _DiffType __type; };
  52. template<typename _DiffType>
  53. struct _DiffTraits<_DiffType, std::__true_type>
  54. { typedef std::ptrdiff_t __type; };
  55. typedef typename _DiffTraits<_ItDiffType>::__type _DiffType;
  56. public:
  57. typedef std::pair<_DiffType, _Distance_precision> __type;
  58. };
  59. template<typename _Integral>
  60. struct _Distance_traits<_Integral, std::__true_type>
  61. { typedef std::pair<std::ptrdiff_t, _Distance_precision> __type; };
  62. /** Determine the distance between two iterators with some known
  63. * precision.
  64. */
  65. template<typename _Iterator>
  66. inline typename _Distance_traits<_Iterator>::__type
  67. __get_distance(const _Iterator& __lhs, const _Iterator& __rhs,
  68. std::random_access_iterator_tag)
  69. { return std::make_pair(__rhs - __lhs, __dp_exact); }
  70. template<typename _Iterator>
  71. inline typename _Distance_traits<_Iterator>::__type
  72. __get_distance(const _Iterator& __lhs, const _Iterator& __rhs,
  73. std::input_iterator_tag)
  74. {
  75. if (__lhs == __rhs)
  76. return std::make_pair(0, __dp_exact);
  77. return std::make_pair(1, __dp_equality);
  78. }
  79. template<typename _Iterator>
  80. inline typename _Distance_traits<_Iterator>::__type
  81. __get_distance(const _Iterator& __lhs, const _Iterator& __rhs)
  82. { return __get_distance(__lhs, __rhs, std::__iterator_category(__lhs)); }
  83. /** We say that integral types for a valid range, and defer to other
  84. * routines to realize what to do with integral types instead of
  85. * iterators.
  86. */
  87. template<typename _Integral>
  88. inline bool
  89. __valid_range_aux(const _Integral&, const _Integral&,
  90. typename _Distance_traits<_Integral>::__type& __dist,
  91. std::__true_type)
  92. {
  93. __dist = std::make_pair(0, __dp_none);
  94. return true;
  95. }
  96. /** We have iterators, so figure out what kind of iterators that are
  97. * to see if we can check the range ahead of time.
  98. */
  99. template<typename _InputIterator>
  100. inline bool
  101. __valid_range_aux(const _InputIterator& __first,
  102. const _InputIterator& __last,
  103. typename _Distance_traits<_InputIterator>::__type& __dist,
  104. std::__false_type)
  105. {
  106. __dist = __get_distance(__first, __last);
  107. switch (__dist.second)
  108. {
  109. case __dp_none:
  110. break;
  111. case __dp_equality:
  112. if (__dist.first == 0)
  113. return true;
  114. break;
  115. case __dp_sign:
  116. case __dp_exact:
  117. return __dist.first >= 0;
  118. }
  119. // Can't tell so assume it is fine.
  120. return true;
  121. }
  122. /** Don't know what these iterators are, or if they are even
  123. * iterators (we may get an integral type for InputIterator), so
  124. * see if they are integral and pass them on to the next phase
  125. * otherwise.
  126. */
  127. template<typename _InputIterator>
  128. inline bool
  129. __valid_range(const _InputIterator& __first, const _InputIterator& __last,
  130. typename _Distance_traits<_InputIterator>::__type& __dist)
  131. {
  132. typedef typename std::__is_integer<_InputIterator>::__type _Integral;
  133. return __valid_range_aux(__first, __last, __dist, _Integral());
  134. }
  135. template<typename _InputIterator>
  136. inline bool
  137. __valid_range(const _InputIterator& __first, const _InputIterator& __last)
  138. {
  139. typename _Distance_traits<_InputIterator>::__type __dist;
  140. return __valid_range(__first, __last, __dist);
  141. }
  142. #if __cplusplus < 201103L
  143. // Helper struct to detect random access safe iterators.
  144. template<typename _Iterator>
  145. struct __is_safe_random_iterator
  146. {
  147. enum { __value = 0 };
  148. typedef std::__false_type __type;
  149. };
  150. template<typename _Iterator>
  151. struct _Siter_base
  152. : std::_Iter_base<_Iterator, __is_safe_random_iterator<_Iterator>::__value>
  153. { };
  154. /** Helper function to extract base iterator of random access safe iterator
  155. in order to reduce performance impact of debug mode. Limited to random
  156. access iterator because it is the only category for which it is possible
  157. to check for correct iterators order in the __valid_range function
  158. thanks to the < operator.
  159. */
  160. template<typename _Iterator>
  161. inline typename _Siter_base<_Iterator>::iterator_type
  162. __base(_Iterator __it)
  163. { return _Siter_base<_Iterator>::_S_base(__it); }
  164. #else
  165. template<typename _Iterator>
  166. inline _Iterator
  167. __base(_Iterator __it)
  168. { return __it; }
  169. #endif
  170. #if __cplusplus < 201103L
  171. template<typename _Iterator>
  172. struct _Unsafe_type
  173. { typedef _Iterator _Type; };
  174. #endif
  175. /* Remove debug mode safe iterator layer, if any. */
  176. template<typename _Iterator>
  177. inline _Iterator
  178. __unsafe(_Iterator __it)
  179. { return __it; }
  180. }
  181. #endif