1 // Debugging support implementation -*- C++ -*- 2 3 // Copyright (C) 2003-2018 Free Software Foundation, Inc. 4 // 5 // This file is part of the GNU ISO C++ Library. This library is free 6 // software; you can redistribute it and/or modify it under the 7 // terms of the GNU General Public License as published by the 8 // Free Software Foundation; either version 3, or (at your option) 9 // any later version. 10 11 // This library is distributed in the hope that it will be useful, 12 // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 // GNU General Public License for more details. 15 16 // Under Section 7 of GPL version 3, you are granted additional 17 // permissions described in the GCC Runtime Library Exception, version 18 // 3.1, as published by the Free Software Foundation. 19 20 // You should have received a copy of the GNU General Public License and 21 // a copy of the GCC Runtime Library Exception along with this program; 22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23 // <http://www.gnu.org/licenses/>. 24 25 /** @file debug/helper_functions.h 26 * This file is a GNU debug extension to the Standard C++ Library. 27 */ 28 29 #ifndef _GLIBCXX_DEBUG_HELPER_FUNCTIONS_H 30 #define _GLIBCXX_DEBUG_HELPER_FUNCTIONS_H 1 31 32 #include <bits/stl_iterator_base_types.h> // for iterator_traits, 33 // categories and _Iter_base 34 #include <bits/cpp_type_traits.h> // for __is_integer 35 36 #include <bits/stl_pair.h> // for pair 37 38 namespace __gnu_debug 39 { 40 /** The precision to which we can calculate the distance between 41 * two iterators. 42 */ 43 enum _Distance_precision 44 { 45 __dp_none, // Not even an iterator type 46 __dp_equality, //< Can compare iterator equality, only 47 __dp_sign, //< Can determine equality and ordering 48 __dp_exact //< Can determine distance precisely 49 }; 50 51 template<typename _Iterator, 52 typename = typename std::__is_integer<_Iterator>::__type> 53 struct _Distance_traits 54 { 55 private: 56 typedef 57 typename std::iterator_traits<_Iterator>::difference_type _ItDiffType; 58 59 template<typename _DiffType, 60 typename = typename std::__is_void<_DiffType>::__type> 61 struct _DiffTraits 62 { typedef _DiffType __type; }; 63 64 template<typename _DiffType> 65 struct _DiffTraits<_DiffType, std::__true_type> 66 { typedef std::ptrdiff_t __type; }; 67 68 typedef typename _DiffTraits<_ItDiffType>::__type _DiffType; 69 70 public: 71 typedef std::pair<_DiffType, _Distance_precision> __type; 72 }; 73 74 template<typename _Integral> 75 struct _Distance_traits<_Integral, std::__true_type> 76 { typedef std::pair<std::ptrdiff_t, _Distance_precision> __type; }; 77 78 /** Determine the distance between two iterators with some known 79 * precision. 80 */ 81 template<typename _Iterator> 82 inline typename _Distance_traits<_Iterator>::__type 83 __get_distance(const _Iterator& __lhs, const _Iterator& __rhs, 84 std::random_access_iterator_tag) 85 { return std::make_pair(__rhs - __lhs, __dp_exact); } 86 87 template<typename _Iterator> 88 inline typename _Distance_traits<_Iterator>::__type 89 __get_distance(const _Iterator& __lhs, const _Iterator& __rhs, 90 std::input_iterator_tag) 91 { 92 if (__lhs == __rhs) 93 return std::make_pair(0, __dp_exact); 94 95 return std::make_pair(1, __dp_equality); 96 } 97 98 template<typename _Iterator> 99 inline typename _Distance_traits<_Iterator>::__type 100 __get_distance(const _Iterator& __lhs, const _Iterator& __rhs) 101 { return __get_distance(__lhs, __rhs, std::__iterator_category(__lhs)); } 102 103 /** We say that integral types for a valid range, and defer to other 104 * routines to realize what to do with integral types instead of 105 * iterators. 106 */ 107 template<typename _Integral> 108 inline bool 109 __valid_range_aux(const _Integral&, const _Integral&, 110 typename _Distance_traits<_Integral>::__type& __dist, 111 std::__true_type) 112 { 113 __dist = std::make_pair(0, __dp_none); 114 return true; 115 } 116 117 /** We have iterators, so figure out what kind of iterators that are 118 * to see if we can check the range ahead of time. 119 */ 120 template<typename _InputIterator> 121 inline bool 122 __valid_range_aux(const _InputIterator& __first, 123 const _InputIterator& __last, 124 typename _Distance_traits<_InputIterator>::__type& __dist, 125 std::__false_type) 126 { 127 __dist = __get_distance(__first, __last); 128 switch (__dist.second) 129 { 130 case __dp_none: 131 break; 132 case __dp_equality: 133 if (__dist.first == 0) 134 return true; 135 break; 136 case __dp_sign: 137 case __dp_exact: 138 return __dist.first >= 0; 139 } 140 141 // Can't tell so assume it is fine. 142 return true; 143 } 144 145 /** Don't know what these iterators are, or if they are even 146 * iterators (we may get an integral type for InputIterator), so 147 * see if they are integral and pass them on to the next phase 148 * otherwise. 149 */ 150 template<typename _InputIterator> 151 inline bool 152 __valid_range(const _InputIterator& __first, const _InputIterator& __last, 153 typename _Distance_traits<_InputIterator>::__type& __dist) 154 { 155 typedef typename std::__is_integer<_InputIterator>::__type _Integral; 156 return __valid_range_aux(__first, __last, __dist, _Integral()); 157 } 158 159 template<typename _InputIterator> 160 inline bool 161 __valid_range(const _InputIterator& __first, const _InputIterator& __last) 162 { 163 typename _Distance_traits<_InputIterator>::__type __dist; 164 return __valid_range(__first, __last, __dist); 165 } 166 167 #if __cplusplus < 201103L 168 // Helper struct to detect random access safe iterators. 169 template<typename _Iterator> 170 struct __is_safe_random_iterator 171 { 172 enum { __value = 0 }; 173 typedef std::__false_type __type; 174 }; 175 176 template<typename _Iterator> 177 struct _Siter_base 178 : std::_Iter_base<_Iterator, __is_safe_random_iterator<_Iterator>::__value> 179 { }; 180 181 /** Helper function to extract base iterator of random access safe iterator 182 in order to reduce performance impact of debug mode. Limited to random 183 access iterator because it is the only category for which it is possible 184 to check for correct iterators order in the __valid_range function 185 thanks to the < operator. 186 */ 187 template<typename _Iterator> 188 inline typename _Siter_base<_Iterator>::iterator_type 189 __base(_Iterator __it) 190 { return _Siter_base<_Iterator>::_S_base(__it); } 191 #else 192 template<typename _Iterator> 193 inline _Iterator 194 __base(_Iterator __it) 195 { return __it; } 196 #endif 197 198 #if __cplusplus < 201103L 199 template<typename _Iterator> 200 struct _Unsafe_type 201 { typedef _Iterator _Type; }; 202 #endif 203 204 /* Remove debug mode safe iterator layer, if any. */ 205 template<typename _Iterator> 206 inline _Iterator 207 __unsafe(_Iterator __it) 208 { return __it; } 209 } 210 211 #endif 212