libstdc++
|
00001 // Debugging support implementation -*- C++ -*- 00002 00003 // Copyright (C) 2003-2018 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/helper_functions.h 00026 * This file is a GNU debug extension to the Standard C++ Library. 00027 */ 00028 00029 #ifndef _GLIBCXX_DEBUG_HELPER_FUNCTIONS_H 00030 #define _GLIBCXX_DEBUG_HELPER_FUNCTIONS_H 1 00031 00032 #include <bits/stl_iterator_base_types.h> // for iterator_traits, 00033 // categories and _Iter_base 00034 #include <bits/cpp_type_traits.h> // for __is_integer 00035 00036 #include <bits/stl_pair.h> // for pair 00037 00038 namespace __gnu_debug 00039 { 00040 /** The precision to which we can calculate the distance between 00041 * two iterators. 00042 */ 00043 enum _Distance_precision 00044 { 00045 __dp_none, // Not even an iterator type 00046 __dp_equality, //< Can compare iterator equality, only 00047 __dp_sign, //< Can determine equality and ordering 00048 __dp_exact //< Can determine distance precisely 00049 }; 00050 00051 template<typename _Iterator, 00052 typename = typename std::__is_integer<_Iterator>::__type> 00053 struct _Distance_traits 00054 { 00055 private: 00056 typedef 00057 typename std::iterator_traits<_Iterator>::difference_type _ItDiffType; 00058 00059 template<typename _DiffType, 00060 typename = typename std::__is_void<_DiffType>::__type> 00061 struct _DiffTraits 00062 { typedef _DiffType __type; }; 00063 00064 template<typename _DiffType> 00065 struct _DiffTraits<_DiffType, std::__true_type> 00066 { typedef std::ptrdiff_t __type; }; 00067 00068 typedef typename _DiffTraits<_ItDiffType>::__type _DiffType; 00069 00070 public: 00071 typedef std::pair<_DiffType, _Distance_precision> __type; 00072 }; 00073 00074 template<typename _Integral> 00075 struct _Distance_traits<_Integral, std::__true_type> 00076 { typedef std::pair<std::ptrdiff_t, _Distance_precision> __type; }; 00077 00078 /** Determine the distance between two iterators with some known 00079 * precision. 00080 */ 00081 template<typename _Iterator> 00082 inline typename _Distance_traits<_Iterator>::__type 00083 __get_distance(const _Iterator& __lhs, const _Iterator& __rhs, 00084 std::random_access_iterator_tag) 00085 { return std::make_pair(__rhs - __lhs, __dp_exact); } 00086 00087 template<typename _Iterator> 00088 inline typename _Distance_traits<_Iterator>::__type 00089 __get_distance(const _Iterator& __lhs, const _Iterator& __rhs, 00090 std::input_iterator_tag) 00091 { 00092 if (__lhs == __rhs) 00093 return std::make_pair(0, __dp_exact); 00094 00095 return std::make_pair(1, __dp_equality); 00096 } 00097 00098 template<typename _Iterator> 00099 inline typename _Distance_traits<_Iterator>::__type 00100 __get_distance(const _Iterator& __lhs, const _Iterator& __rhs) 00101 { return __get_distance(__lhs, __rhs, std::__iterator_category(__lhs)); } 00102 00103 /** We say that integral types for a valid range, and defer to other 00104 * routines to realize what to do with integral types instead of 00105 * iterators. 00106 */ 00107 template<typename _Integral> 00108 inline bool 00109 __valid_range_aux(const _Integral&, const _Integral&, 00110 typename _Distance_traits<_Integral>::__type& __dist, 00111 std::__true_type) 00112 { 00113 __dist = std::make_pair(0, __dp_none); 00114 return true; 00115 } 00116 00117 /** We have iterators, so figure out what kind of iterators that are 00118 * to see if we can check the range ahead of time. 00119 */ 00120 template<typename _InputIterator> 00121 inline bool 00122 __valid_range_aux(const _InputIterator& __first, 00123 const _InputIterator& __last, 00124 typename _Distance_traits<_InputIterator>::__type& __dist, 00125 std::__false_type) 00126 { 00127 __dist = __get_distance(__first, __last); 00128 switch (__dist.second) 00129 { 00130 case __dp_none: 00131 break; 00132 case __dp_equality: 00133 if (__dist.first == 0) 00134 return true; 00135 break; 00136 case __dp_sign: 00137 case __dp_exact: 00138 return __dist.first >= 0; 00139 } 00140 00141 // Can't tell so assume it is fine. 00142 return true; 00143 } 00144 00145 /** Don't know what these iterators are, or if they are even 00146 * iterators (we may get an integral type for InputIterator), so 00147 * see if they are integral and pass them on to the next phase 00148 * otherwise. 00149 */ 00150 template<typename _InputIterator> 00151 inline bool 00152 __valid_range(const _InputIterator& __first, const _InputIterator& __last, 00153 typename _Distance_traits<_InputIterator>::__type& __dist) 00154 { 00155 typedef typename std::__is_integer<_InputIterator>::__type _Integral; 00156 return __valid_range_aux(__first, __last, __dist, _Integral()); 00157 } 00158 00159 template<typename _InputIterator> 00160 inline bool 00161 __valid_range(const _InputIterator& __first, const _InputIterator& __last) 00162 { 00163 typename _Distance_traits<_InputIterator>::__type __dist; 00164 return __valid_range(__first, __last, __dist); 00165 } 00166 00167 #if __cplusplus < 201103L 00168 // Helper struct to detect random access safe iterators. 00169 template<typename _Iterator> 00170 struct __is_safe_random_iterator 00171 { 00172 enum { __value = 0 }; 00173 typedef std::__false_type __type; 00174 }; 00175 00176 template<typename _Iterator> 00177 struct _Siter_base 00178 : std::_Iter_base<_Iterator, __is_safe_random_iterator<_Iterator>::__value> 00179 { }; 00180 00181 /** Helper function to extract base iterator of random access safe iterator 00182 in order to reduce performance impact of debug mode. Limited to random 00183 access iterator because it is the only category for which it is possible 00184 to check for correct iterators order in the __valid_range function 00185 thanks to the < operator. 00186 */ 00187 template<typename _Iterator> 00188 inline typename _Siter_base<_Iterator>::iterator_type 00189 __base(_Iterator __it) 00190 { return _Siter_base<_Iterator>::_S_base(__it); } 00191 #else 00192 template<typename _Iterator> 00193 inline _Iterator 00194 __base(_Iterator __it) 00195 { return __it; } 00196 #endif 00197 00198 #if __cplusplus < 201103L 00199 template<typename _Iterator> 00200 struct _Unsafe_type 00201 { typedef _Iterator _Type; }; 00202 #endif 00203 00204 /* Remove debug mode safe iterator layer, if any. */ 00205 template<typename _Iterator> 00206 inline _Iterator 00207 __unsafe(_Iterator __it) 00208 { return __it; } 00209 } 00210 00211 #endif