// Debugging support implementation -*- C++ -*- // Copyright (C) 2003-2017 Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the // terms of the GNU General Public License as published by the // Free Software Foundation; either version 3, or (at your option) // any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // Under Section 7 of GPL version 3, you are granted additional // permissions described in the GCC Runtime Library Exception, version // 3.1, as published by the Free Software Foundation. // You should have received a copy of the GNU General Public License and // a copy of the GCC Runtime Library Exception along with this program; // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see // . /** @file debug/helper_functions.h * This file is a GNU debug extension to the Standard C++ Library. */ #ifndef _GLIBCXX_DEBUG_HELPER_FUNCTIONS_H #define _GLIBCXX_DEBUG_HELPER_FUNCTIONS_H 1 #include // for iterator_traits, // categories and _Iter_base #include // for __is_integer #include // for pair namespace __gnu_debug { /** The precision to which we can calculate the distance between * two iterators. */ enum _Distance_precision { __dp_none, // Not even an iterator type __dp_equality, //< Can compare iterator equality, only __dp_sign, //< Can determine equality and ordering __dp_exact //< Can determine distance precisely }; template::__type> struct _Distance_traits { private: typedef typename std::iterator_traits<_Iterator>::difference_type _ItDiffType; template::__type> struct _DiffTraits { typedef _DiffType __type; }; template struct _DiffTraits<_DiffType, std::__true_type> { typedef std::ptrdiff_t __type; }; typedef typename _DiffTraits<_ItDiffType>::__type _DiffType; public: typedef std::pair<_DiffType, _Distance_precision> __type; }; template struct _Distance_traits<_Integral, std::__true_type> { typedef std::pair __type; }; /** Determine the distance between two iterators with some known * precision. */ template inline typename _Distance_traits<_Iterator>::__type __get_distance(const _Iterator& __lhs, const _Iterator& __rhs, std::random_access_iterator_tag) { return std::make_pair(__rhs - __lhs, __dp_exact); } template inline typename _Distance_traits<_Iterator>::__type __get_distance(const _Iterator& __lhs, const _Iterator& __rhs, std::input_iterator_tag) { if (__lhs == __rhs) return std::make_pair(0, __dp_exact); return std::make_pair(1, __dp_equality); } template inline typename _Distance_traits<_Iterator>::__type __get_distance(const _Iterator& __lhs, const _Iterator& __rhs) { return __get_distance(__lhs, __rhs, std::__iterator_category(__lhs)); } /** We say that integral types for a valid range, and defer to other * routines to realize what to do with integral types instead of * iterators. */ template inline bool __valid_range_aux(const _Integral&, const _Integral&, typename _Distance_traits<_Integral>::__type& __dist, std::__true_type) { __dist = std::make_pair(0, __dp_none); return true; } /** We have iterators, so figure out what kind of iterators that are * to see if we can check the range ahead of time. */ template inline bool __valid_range_aux(const _InputIterator& __first, const _InputIterator& __last, typename _Distance_traits<_InputIterator>::__type& __dist, std::__false_type) { __dist = __get_distance(__first, __last); switch (__dist.second) { case __dp_none: break; case __dp_equality: if (__dist.first == 0) return true; break; case __dp_sign: case __dp_exact: return __dist.first >= 0; } // Can't tell so assume it is fine. return true; } /** Don't know what these iterators are, or if they are even * iterators (we may get an integral type for InputIterator), so * see if they are integral and pass them on to the next phase * otherwise. */ template inline bool __valid_range(const _InputIterator& __first, const _InputIterator& __last, typename _Distance_traits<_InputIterator>::__type& __dist) { typedef typename std::__is_integer<_InputIterator>::__type _Integral; return __valid_range_aux(__first, __last, __dist, _Integral()); } template inline bool __valid_range(const _InputIterator& __first, const _InputIterator& __last) { typename _Distance_traits<_InputIterator>::__type __dist; return __valid_range(__first, __last, __dist); } #if __cplusplus < 201103L // Helper struct to detect random access safe iterators. template struct __is_safe_random_iterator { enum { __value = 0 }; typedef std::__false_type __type; }; template struct _Siter_base : std::_Iter_base<_Iterator, __is_safe_random_iterator<_Iterator>::__value> { }; /** Helper function to extract base iterator of random access safe iterator in order to reduce performance impact of debug mode. Limited to random access iterator because it is the only category for which it is possible to check for correct iterators order in the __valid_range function thanks to the < operator. */ template inline typename _Siter_base<_Iterator>::iterator_type __base(_Iterator __it) { return _Siter_base<_Iterator>::_S_base(__it); } #else template inline _Iterator __base(_Iterator __it) { return __it; } #endif #if __cplusplus < 201103L template struct _Unsafe_type { typedef _Iterator _Type; }; #endif /* Remove debug mode safe iterator layer, if any. */ template inline _Iterator __unsafe(_Iterator __it) { return __it; } } #endif