libstdc++
|
00001 // Debugging support implementation -*- C++ -*- 00002 00003 // Copyright (C) 2003-2016 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 return true; 00142 } 00143 00144 /** Don't know what these iterators are, or if they are even 00145 * iterators (we may get an integral type for InputIterator), so 00146 * see if they are integral and pass them on to the next phase 00147 * otherwise. 00148 */ 00149 template<typename _InputIterator> 00150 inline bool 00151 __valid_range(const _InputIterator& __first, const _InputIterator& __last, 00152 typename _Distance_traits<_InputIterator>::__type& __dist) 00153 { 00154 typedef typename std::__is_integer<_InputIterator>::__type _Integral; 00155 return __valid_range_aux(__first, __last, __dist, _Integral()); 00156 } 00157 00158 template<typename _InputIterator> 00159 inline bool 00160 __valid_range(const _InputIterator& __first, const _InputIterator& __last) 00161 { 00162 typename _Distance_traits<_InputIterator>::__type __dist; 00163 return __valid_range(__first, __last, __dist); 00164 } 00165 00166 #if __cplusplus < 201103L 00167 // Helper struct to detect random access safe iterators. 00168 template<typename _Iterator> 00169 struct __is_safe_random_iterator 00170 { 00171 enum { __value = 0 }; 00172 typedef std::__false_type __type; 00173 }; 00174 00175 template<typename _Iterator> 00176 struct _Siter_base 00177 : std::_Iter_base<_Iterator, __is_safe_random_iterator<_Iterator>::__value> 00178 { }; 00179 00180 /** Helper function to extract base iterator of random access safe iterator 00181 in order to reduce performance impact of debug mode. Limited to random 00182 access iterator because it is the only category for which it is possible 00183 to check for correct iterators order in the __valid_range function 00184 thanks to the < operator. 00185 */ 00186 template<typename _Iterator> 00187 inline typename _Siter_base<_Iterator>::iterator_type 00188 __base(_Iterator __it) 00189 { return _Siter_base<_Iterator>::_S_base(__it); } 00190 #else 00191 template<typename _Iterator> 00192 inline _Iterator 00193 __base(_Iterator __it) 00194 { return __it; } 00195 #endif 00196 00197 #if __cplusplus < 201103L 00198 template<typename _Iterator> 00199 struct _Unsafe_type 00200 { typedef _Iterator _Type; }; 00201 #endif 00202 00203 /* Remove debug mode safe iterator layer, if any. */ 00204 template<typename _Iterator> 00205 inline _Iterator 00206 __unsafe(_Iterator __it) 00207 { return __it; } 00208 } 00209 00210 #endif