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