1 // Debugging support implementation -*- C++ -*-
2 
3 // Copyright (C) 2003-2016 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       return true;
142     }
143 
144   /** Don't know what these iterators are, or if they are even
145    *  iterators (we may get an integral type for InputIterator), so
146    *  see if they are integral and pass them on to the next phase
147    *  otherwise.
148   */
149   template<typename _InputIterator>
150     inline bool
151     __valid_range(const _InputIterator& __first, const _InputIterator& __last,
152 		  typename _Distance_traits<_InputIterator>::__type& __dist)
153     {
154       typedef typename std::__is_integer<_InputIterator>::__type _Integral;
155       return __valid_range_aux(__first, __last, __dist, _Integral());
156     }
157 
158   template<typename _InputIterator>
159     inline bool
160     __valid_range(const _InputIterator& __first, const _InputIterator& __last)
161     {
162       typename _Distance_traits<_InputIterator>::__type __dist;
163       return __valid_range(__first, __last, __dist);
164     }
165 
166 #if __cplusplus < 201103L
167   // Helper struct to detect random access safe iterators.
168   template<typename _Iterator>
169     struct __is_safe_random_iterator
170     {
171       enum { __value = 0 };
172       typedef std::__false_type __type;
173     };
174 
175   template<typename _Iterator>
176     struct _Siter_base
177     : std::_Iter_base<_Iterator, __is_safe_random_iterator<_Iterator>::__value>
178     { };
179 
180   /** Helper function to extract base iterator of random access safe iterator
181       in order to reduce performance impact of debug mode.  Limited to random
182       access iterator because it is the only category for which it is possible
183       to check for correct iterators order in the __valid_range function
184       thanks to the < operator.
185   */
186   template<typename _Iterator>
187     inline typename _Siter_base<_Iterator>::iterator_type
188     __base(_Iterator __it)
189     { return _Siter_base<_Iterator>::_S_base(__it); }
190 #else
191   template<typename _Iterator>
192     inline _Iterator
193     __base(_Iterator __it)
194     { return __it; }
195 #endif
196 
197 #if __cplusplus < 201103L
198   template<typename _Iterator>
199     struct _Unsafe_type
200     { typedef _Iterator _Type; };
201 #endif
202 
203   /* Remove debug mode safe iterator layer, if any. */
204   template<typename _Iterator>
205     inline _Iterator
206     __unsafe(_Iterator __it)
207     { return __it; }
208 }
209 
210 #endif
211