// 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