You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and dots ('.'), can be up to 35 characters long. Letters must be lowercase.
621 lines
21 KiB
621 lines
21 KiB
// Boost string_algo library collection_traits.hpp header file -----------------------// |
|
|
|
// Copyright Pavol Droba 2002-2003. Use, modification and |
|
// distribution is subject to the Boost Software License, Version |
|
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at |
|
// http://www.boost.org/LICENSE_1_0.txt) |
|
|
|
// See http://www.boost.org for updates, documentation, and revision history. |
|
|
|
#ifndef BOOST_RANGE_STRING_DETAIL_COLLECTION_TRAITS_HPP |
|
#define BOOST_RANGE_STRING_DETAIL_COLLECTION_TRAITS_HPP |
|
|
|
#include <boost/algorithm/string/config.hpp> |
|
#include <cstddef> |
|
#include <string> |
|
#include <boost/type_traits/is_array.hpp> |
|
#include <boost/type_traits/is_pointer.hpp> |
|
#include <boost/type_traits/is_const.hpp> |
|
#include <boost/type_traits/is_convertible.hpp> |
|
#include <boost/type_traits/remove_pointer.hpp> |
|
#include <boost/type_traits/remove_cv.hpp> |
|
#include <boost/mpl/eval_if.hpp> |
|
#include <boost/mpl/identity.hpp> |
|
#include <boost/mpl/vector.hpp> |
|
#include <boost/mpl/fold.hpp> |
|
#include <boost/detail/iterator.hpp> |
|
#include <boost/algorithm/string/yes_no_type.hpp> |
|
|
|
// Container traits implementation --------------------------------------------------------- |
|
|
|
namespace boost { |
|
namespace algorithm { |
|
namespace detail { |
|
|
|
// Default collection traits ----------------------------------------------------------------- |
|
|
|
// Default collection helper |
|
/* |
|
Wraps std::container compliant containers |
|
*/ |
|
template< typename ContainerT > |
|
struct default_container_traits |
|
{ |
|
typedef BOOST_STRING_TYPENAME ContainerT::value_type value_type; |
|
typedef BOOST_STRING_TYPENAME ContainerT::iterator iterator; |
|
typedef BOOST_STRING_TYPENAME ContainerT::const_iterator const_iterator; |
|
typedef BOOST_STRING_TYPENAME |
|
::boost::mpl::if_< ::boost::is_const<ContainerT>, |
|
const_iterator, |
|
iterator |
|
>::type result_iterator; |
|
typedef BOOST_STRING_TYPENAME ContainerT::difference_type difference_type; |
|
typedef BOOST_STRING_TYPENAME ContainerT::size_type size_type; |
|
|
|
// static operations |
|
template< typename C > |
|
static size_type size( const C& c ) |
|
{ |
|
return c.size(); |
|
} |
|
|
|
template< typename C > |
|
static bool empty( const C& c ) |
|
{ |
|
return c.empty(); |
|
} |
|
|
|
#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING |
|
|
|
template< typename C > |
|
static iterator begin( C& c ) |
|
{ |
|
return c.begin(); |
|
} |
|
|
|
template< typename C > |
|
static const_iterator begin( const C& c ) |
|
{ |
|
return c.begin(); |
|
} |
|
|
|
template< typename C > |
|
static iterator end( C& c ) |
|
{ |
|
return c.end(); |
|
} |
|
|
|
template< typename C > |
|
static const_iterator end( const C& c ) |
|
{ |
|
return c.end(); |
|
} |
|
|
|
#else // BOOST_NO_FUNCTION_TEMPLATE_ORDERING |
|
|
|
template< typename C > |
|
static result_iterator begin( C& c ) |
|
{ |
|
return c.begin(); |
|
} |
|
|
|
template< typename C > |
|
static result_iterator end( C& c ) |
|
{ |
|
return c.end(); |
|
} |
|
|
|
#endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING |
|
|
|
}; |
|
|
|
template<typename T> |
|
struct default_container_traits_selector |
|
{ |
|
typedef default_container_traits<T> type; |
|
}; |
|
|
|
// Pair container traits --------------------------------------------------------------------- |
|
|
|
// pair selector |
|
template< typename T, typename U > |
|
yes_type is_pair_impl( const std::pair<T,U>* ); |
|
no_type is_pair_impl( ... ); |
|
|
|
template<typename T> struct is_pair |
|
{ |
|
private: |
|
static T* t; |
|
public: |
|
BOOST_STATIC_CONSTANT( bool, value= |
|
sizeof(is_pair_impl(t))==sizeof(yes_type) ); |
|
}; |
|
|
|
// pair helper |
|
template< typename PairT > |
|
struct pair_container_traits |
|
{ |
|
typedef BOOST_STRING_TYPENAME PairT::first_type element_type; |
|
|
|
typedef BOOST_STRING_TYPENAME ::boost::detail:: |
|
iterator_traits<element_type>::value_type value_type; |
|
typedef std::size_t size_type; |
|
typedef BOOST_STRING_TYPENAME ::boost::detail:: |
|
iterator_traits<element_type>::difference_type difference_type; |
|
|
|
typedef element_type iterator; |
|
typedef element_type const_iterator; |
|
typedef element_type result_iterator; |
|
|
|
// static operations |
|
template< typename P > |
|
static size_type size( const P& p ) |
|
{ |
|
difference_type diff = std::distance( p.first, p.second ); |
|
if ( diff < 0 ) |
|
return 0; |
|
else |
|
return diff; |
|
} |
|
|
|
template< typename P > |
|
static bool empty( const P& p ) |
|
{ |
|
return p.first==p.second; |
|
} |
|
|
|
template< typename P > |
|
static const_iterator begin( const P& p ) |
|
{ |
|
return p.first; |
|
} |
|
|
|
template< typename P > |
|
static const_iterator end( const P& p ) |
|
{ |
|
return p.second; |
|
} |
|
}; // 'pair_container_helper' |
|
|
|
template<typename T> |
|
struct pair_container_traits_selector |
|
{ |
|
typedef pair_container_traits<T> type; |
|
}; |
|
|
|
// Array container traits --------------------------------------------------------------- |
|
|
|
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION |
|
// array traits ( partial specialization ) |
|
template< typename T > |
|
struct array_traits; |
|
|
|
template< typename T, std::size_t sz > |
|
struct array_traits<T[sz]> |
|
{ |
|
// typedef |
|
typedef T* iterator; |
|
typedef const T* const_iterator; |
|
typedef T value_type; |
|
typedef std::size_t size_type; |
|
typedef std::ptrdiff_t difference_type; |
|
|
|
// size of the array ( static ); |
|
BOOST_STATIC_CONSTANT( size_type, array_size = sz ); |
|
}; |
|
|
|
#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION |
|
|
|
// array traits ( no partial specialization ) |
|
/* |
|
without parial specialization we are able to |
|
provide support only for a limited number of |
|
types. Currently the primitive numeric types |
|
are supported |
|
*/ |
|
template< typename T, typename BaseT > |
|
struct array_traits_impl |
|
{ |
|
typedef BaseT value_type; |
|
typedef BaseT* iterator; |
|
typedef const BaseT* const_iterator; |
|
typedef std::size_t size_type; |
|
typedef std::ptrdiff_t difference_type; |
|
|
|
// size of the array |
|
BOOST_STATIC_CONSTANT( size_type, array_size = sizeof(T)/sizeof(BaseT) ); |
|
}; |
|
|
|
template< typename T, typename BaseT > |
|
struct array_traits_impl_selector |
|
{ |
|
typedef array_traits_impl<T,BaseT> type; |
|
}; |
|
|
|
struct array_traits_void |
|
{ |
|
typedef void type; |
|
}; |
|
|
|
template< typename T, typename BaseT > |
|
struct array_traits_cv_selector |
|
{ |
|
typedef BOOST_STRING_TYPENAME |
|
::boost::mpl::eval_if< |
|
::boost::is_convertible<T,BaseT*>, |
|
array_traits_impl_selector<T,BaseT>, |
|
::boost::mpl::eval_if< |
|
::boost::is_convertible<T,const BaseT*>, |
|
array_traits_impl_selector<T, const BaseT>, |
|
::boost::mpl::eval_if< |
|
::boost::is_convertible<T, volatile BaseT*>, |
|
array_traits_impl_selector<T, volatile BaseT>, |
|
array_traits_impl_selector<T, const volatile BaseT> |
|
> |
|
> |
|
>::type type; |
|
}; |
|
|
|
template< typename T > |
|
struct array_traits_select |
|
{ |
|
template< typename T1, typename T2 > |
|
struct apply |
|
{ |
|
typedef BOOST_STRING_TYPENAME |
|
::boost::mpl::eval_if< |
|
::boost::is_convertible<T,const volatile T2*>, |
|
array_traits_cv_selector<T,T2>, |
|
::boost::mpl::identity<T1> >::type type; |
|
}; |
|
}; |
|
|
|
template< typename T > |
|
struct array_traits_selector |
|
{ |
|
private: |
|
// supported array base types |
|
#ifndef BOOST_NO_INTRINSIC_WCHAR_T |
|
typedef BOOST_STRING_TYPENAME |
|
::boost::mpl::vector10< |
|
wchar_t, |
|
#else // BOOST_NO_INTRINSIC_WCHAR_T |
|
typedef BOOST_STRING_TYPENAME |
|
::boost::mpl::vector9< |
|
#endif // BOOST_NO_INTRINSIC_WCHAR_T |
|
char, |
|
signed char, |
|
unsigned char, |
|
signed short, |
|
unsigned short, |
|
signed int, |
|
unsigned int, |
|
signed long, |
|
unsigned long |
|
>::type array_base_types; |
|
|
|
public: |
|
typedef BOOST_STRING_TYPENAME |
|
::boost::mpl::fold< |
|
array_base_types, |
|
::boost::algorithm::detail::array_traits_void, |
|
::boost::algorithm::detail::array_traits_select<T> >::type type; |
|
}; |
|
|
|
template< typename T > |
|
struct array_traits |
|
{ |
|
typedef BOOST_STRING_TYPENAME |
|
array_traits_selector<T>::type traits_type; |
|
|
|
typedef BOOST_STRING_TYPENAME |
|
traits_type::value_type value_type; |
|
typedef BOOST_STRING_TYPENAME |
|
traits_type::iterator iterator; |
|
typedef BOOST_STRING_TYPENAME |
|
traits_type::const_iterator const_iterator; |
|
typedef BOOST_STRING_TYPENAME |
|
traits_type::size_type size_type; |
|
typedef BOOST_STRING_TYPENAME |
|
traits_type::difference_type difference_type; |
|
|
|
BOOST_STATIC_CONSTANT( size_type, array_size = traits_type::array_size ); |
|
}; |
|
|
|
#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION |
|
|
|
// array lenght resolving |
|
/* |
|
Lenght of string contained in a static array could |
|
be different from the size of the array. |
|
For string processing we need the lenght without |
|
terminating 0. |
|
|
|
Therefore, the lenght is calulated for char and wchar_t |
|
using char_traits, rather then simply returning |
|
the array size. |
|
*/ |
|
template< typename T > |
|
struct array_length_selector |
|
{ |
|
template< typename TraitsT > |
|
struct array_length |
|
{ |
|
typedef BOOST_STRING_TYPENAME |
|
TraitsT::size_type size_type; |
|
|
|
BOOST_STATIC_CONSTANT( |
|
size_type, |
|
array_size=TraitsT::array_size ); |
|
|
|
template< typename A > |
|
static size_type length( const A& ) |
|
{ |
|
return array_size; |
|
} |
|
|
|
template< typename A > |
|
static bool empty( const A& ) |
|
{ |
|
return array_size==0; |
|
} |
|
}; |
|
}; |
|
|
|
// specialization for char |
|
template<> |
|
struct array_length_selector<char> |
|
{ |
|
template< typename TraitsT > |
|
struct array_length |
|
{ |
|
typedef BOOST_STRING_TYPENAME |
|
TraitsT::size_type size_type; |
|
|
|
template< typename A > |
|
static size_type length( const A& a ) |
|
{ |
|
if ( a==0 ) |
|
return 0; |
|
else |
|
return std::char_traits<char>::length(a); |
|
} |
|
|
|
template< typename A > |
|
static bool empty( const A& a ) |
|
{ |
|
return a==0 || a[0]==0; |
|
} |
|
}; |
|
}; |
|
|
|
// specialization for wchar_t |
|
template<> |
|
struct array_length_selector<wchar_t> |
|
{ |
|
template< typename TraitsT > |
|
struct array_length |
|
{ |
|
typedef BOOST_STRING_TYPENAME |
|
TraitsT::size_type size_type; |
|
|
|
template< typename A > |
|
static size_type length( const A& a ) |
|
{ |
|
if ( a==0 ) |
|
return 0; |
|
else |
|
return std::char_traits<wchar_t>::length(a); |
|
} |
|
|
|
template< typename A > |
|
static bool empty( const A& a ) |
|
{ |
|
return a==0 || a[0]==0; |
|
} |
|
}; |
|
}; |
|
|
|
template< typename T > |
|
struct array_container_traits |
|
{ |
|
private: |
|
// resolve array traits |
|
typedef array_traits<T> traits_type; |
|
|
|
public: |
|
typedef BOOST_STRING_TYPENAME |
|
traits_type::value_type value_type; |
|
typedef BOOST_STRING_TYPENAME |
|
traits_type::iterator iterator; |
|
typedef BOOST_STRING_TYPENAME |
|
traits_type::const_iterator const_iterator; |
|
typedef BOOST_STRING_TYPENAME |
|
traits_type::size_type size_type; |
|
typedef BOOST_STRING_TYPENAME |
|
traits_type::difference_type difference_type; |
|
|
|
typedef BOOST_STRING_TYPENAME |
|
::boost::mpl::if_< ::boost::is_const<T>, |
|
const_iterator, |
|
iterator |
|
>::type result_iterator; |
|
|
|
private: |
|
// resolve array size |
|
typedef BOOST_STRING_TYPENAME |
|
::boost::remove_cv<value_type>::type char_type; |
|
typedef BOOST_STRING_TYPENAME |
|
array_length_selector<char_type>:: |
|
BOOST_NESTED_TEMPLATE array_length<traits_type> array_length_type; |
|
|
|
public: |
|
BOOST_STATIC_CONSTANT( size_type, array_size = traits_type::array_size ); |
|
|
|
// static operations |
|
template< typename A > |
|
static size_type size( const A& a ) |
|
{ |
|
return array_length_type::length(a); |
|
} |
|
|
|
template< typename A > |
|
static bool empty( const A& a ) |
|
{ |
|
return array_length_type::empty(a); |
|
} |
|
|
|
|
|
#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING |
|
|
|
template< typename A > |
|
static iterator begin( A& a ) |
|
{ |
|
return a; |
|
} |
|
|
|
template< typename A > |
|
static const_iterator begin( const A& a ) |
|
{ |
|
return a; |
|
} |
|
|
|
template< typename A > |
|
static iterator end( A& a ) |
|
{ |
|
return a+array_length_type::length(a); |
|
} |
|
|
|
template< typename A > |
|
static const_iterator end( const A& a ) |
|
{ |
|
return a+array_length_type::length(a); |
|
} |
|
|
|
#else // BOOST_NO_FUNCTION_TEMPLATE_ORDERING |
|
|
|
template< typename A > |
|
static result_iterator begin( A& a ) |
|
{ |
|
return a; |
|
} |
|
|
|
template< typename A > |
|
static result_iterator end( A& a ) |
|
{ |
|
return a+array_length_type::length(a); |
|
} |
|
|
|
#endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING |
|
|
|
}; |
|
|
|
template<typename T> |
|
struct array_container_traits_selector |
|
{ |
|
typedef array_container_traits<T> type; |
|
}; |
|
|
|
// Pointer container traits --------------------------------------------------------------- |
|
|
|
template<typename T> |
|
struct pointer_container_traits |
|
{ |
|
typedef BOOST_STRING_TYPENAME |
|
::boost::remove_pointer<T>::type value_type; |
|
|
|
typedef BOOST_STRING_TYPENAME |
|
::boost::remove_cv<value_type>::type char_type; |
|
typedef ::std::char_traits<char_type> char_traits; |
|
|
|
typedef value_type* iterator; |
|
typedef const value_type* const_iterator; |
|
typedef std::ptrdiff_t difference_type; |
|
typedef std::size_t size_type; |
|
|
|
typedef BOOST_STRING_TYPENAME |
|
::boost::mpl::if_< ::boost::is_const<T>, |
|
const_iterator, |
|
iterator |
|
>::type result_iterator; |
|
|
|
// static operations |
|
template< typename P > |
|
static size_type size( const P& p ) |
|
{ |
|
if ( p==0 ) |
|
return 0; |
|
else |
|
return char_traits::length(p); |
|
} |
|
|
|
template< typename P > |
|
static bool empty( const P& p ) |
|
{ |
|
return p==0 || p[0]==0; |
|
} |
|
|
|
#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING |
|
|
|
template< typename P > |
|
static iterator begin( P& p ) |
|
{ |
|
return p; |
|
} |
|
|
|
template< typename P > |
|
static const_iterator begin( const P& p ) |
|
{ |
|
return p; |
|
} |
|
|
|
template< typename P > |
|
static iterator end( P& p ) |
|
{ |
|
if ( p==0 ) |
|
return p; |
|
else |
|
return p+char_traits::length(p); |
|
} |
|
|
|
template< typename P > |
|
static const_iterator end( const P& p ) |
|
{ |
|
if ( p==0 ) |
|
return p; |
|
else |
|
return p+char_traits::length(p); |
|
} |
|
|
|
#else // BOOST_NO_FUNCTION_TEMPLATE_ORDERING |
|
|
|
template< typename P > |
|
static result_iterator begin( P& p ) |
|
{ |
|
return p; |
|
} |
|
|
|
template< typename P > |
|
static result_iterator end( P& p ) |
|
{ |
|
if ( p==0 ) |
|
return p; |
|
else |
|
return p+char_traits::length(p); |
|
} |
|
|
|
#endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING |
|
}; |
|
|
|
template<typename T> |
|
struct pointer_container_traits_selector |
|
{ |
|
typedef pointer_container_traits<T> type; |
|
}; |
|
|
|
} // namespace detail |
|
} // namespace algorithm |
|
} // namespace boost |
|
|
|
|
|
#endif // BOOST_STRING_DETAIL_COLLECTION_HPP
|
|
|