blob: dbc1dda4ef45f2a50d9bbe844210b0be4825621e [file] [log] [blame]
/*=============================================================================
Copyright (c) 2001-2011 Joel de Guzman
Copyright (c) 2001-2011 Hartmut Kaiser
http://spirit.sourceforge.net/
Distributed under 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)
=============================================================================*/
#if !defined(BOOST_SPIRIT_CONTAINER_FEBRUARY_06_2007_1001AM)
#define BOOST_SPIRIT_CONTAINER_FEBRUARY_06_2007_1001AM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/support/attributes_fwd.hpp>
#include <boost/detail/iterator.hpp> // for boost::detail::iterator_traits
#include <boost/mpl/has_xxx.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/optional.hpp>
#include <boost/variant.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/repeat.hpp>
#include <boost/range/iterator_range.hpp>
namespace boost { namespace spirit { namespace traits
{
///////////////////////////////////////////////////////////////////////////
// This file contains some container utils for stl containers. The
// utilities provided also accept spirit's unused_type; all no-ops.
// Compiler optimization will easily strip these away.
///////////////////////////////////////////////////////////////////////////
namespace detail
{
BOOST_MPL_HAS_XXX_TRAIT_DEF(value_type)
BOOST_MPL_HAS_XXX_TRAIT_DEF(iterator)
BOOST_MPL_HAS_XXX_TRAIT_DEF(size_type)
BOOST_MPL_HAS_XXX_TRAIT_DEF(reference)
}
template <typename T, typename Enable/* = void*/>
struct is_container
: mpl::bool_<
detail::has_value_type<T>::value &&
detail::has_iterator<T>::value &&
detail::has_size_type<T>::value &&
detail::has_reference<T>::value>
{};
template <typename T>
struct is_container<T&>
: is_container<T>
{};
template <typename T>
struct is_container<optional<T> >
: is_container<T>
{};
#define BOOST_SPIRIT_IS_CONTAINER(z, N, data) \
is_container<BOOST_PP_CAT(T, N)>::value || \
/***/
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct is_container<variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
: mpl::bool_<BOOST_PP_REPEAT(BOOST_VARIANT_LIMIT_TYPES
, BOOST_SPIRIT_IS_CONTAINER, _) false>
{};
#undef BOOST_SPIRIT_IS_CONTAINER
template <typename T, typename Enable/* = void*/>
struct is_iterator_range
: mpl::false_
{};
template <typename T>
struct is_iterator_range<iterator_range<T> >
: mpl::true_
{};
///////////////////////////////////////////////////////////////////////////
namespace detail
{
template <typename T>
struct remove_value_const
{
typedef T type;
};
template <typename T>
struct remove_value_const<T const>
: remove_value_const<T>
{};
template <typename F, typename S>
struct remove_value_const<std::pair<F, S> >
{
typedef typename remove_value_const<F>::type first_type;
typedef typename remove_value_const<S>::type second_type;
typedef std::pair<first_type, second_type> type;
};
}
///////////////////////////////////////////////////////////////////////
//[customization_container_value_default
template <typename Container, typename Enable/* = void*/>
struct container_value
: detail::remove_value_const<typename Container::value_type>
{};
//]
template <typename T>
struct container_value<T&>
: container_value<T>
{};
// this will be instantiated if the optional holds a container
template <typename T>
struct container_value<optional<T> >
: container_value<T>
{};
// this will be instantiated if the variant holds a container
template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct container_value<variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
{
typedef typename
variant<BOOST_VARIANT_ENUM_PARAMS(T)>::types
types;
typedef typename
mpl::find_if<types, is_container<mpl::_1> >::type
iter;
typedef typename container_value<
typename mpl::if_<
is_same<iter, typename mpl::end<types>::type>
, unused_type, typename mpl::deref<iter>::type
>::type
>::type type;
};
//[customization_container_value_unused
template <>
struct container_value<unused_type>
{
typedef unused_type type;
};
//]
template <>
struct container_value<unused_type const>
{
typedef unused_type type;
};
///////////////////////////////////////////////////////////////////////////
template <typename Container, typename Enable/* = void*/>
struct container_iterator
{
typedef typename Container::iterator type;
};
template <typename Container>
struct container_iterator<Container&>
: container_iterator<Container>
{};
template <typename Container>
struct container_iterator<Container const>
{
typedef typename Container::const_iterator type;
};
template <typename Iterator>
struct container_iterator<iterator_range<Iterator> >
{
typedef typename range_const_iterator<
iterator_range<Iterator> >::type type;
};
template <>
struct container_iterator<unused_type>
{
typedef unused_type const* type;
};
template <>
struct container_iterator<unused_type const>
{
typedef unused_type const* type;
};
///////////////////////////////////////////////////////////////////////////
template <typename T, typename Enable/* = void*/>
struct optional_attribute
{
typedef T const& type;
static type call(T const& val)
{
return val;
}
static bool is_valid(T const&)
{
return true;
}
};
template <typename T>
struct optional_attribute<optional<T> >
{
typedef T const& type;
static type call(optional<T> const& val)
{
return boost::get<T>(val);
}
static bool is_valid(optional<T> const& val)
{
return val;
}
};
template <typename T>
typename optional_attribute<T>::type
optional_value(T const& val)
{
return optional_attribute<T>::call(val);
}
inline unused_type optional_value(unused_type)
{
return unused;
}
template <typename T>
bool has_optional_value(T const& val)
{
return optional_attribute<T>::is_valid(val);
}
inline bool has_optional_value(unused_type)
{
return true;
}
///////////////////////////////////////////////////////////////////////////
template <typename Container, typename T>
bool push_back(Container& c, T const& val);
//[customization_push_back_default
template <typename Container, typename T, typename Enable/* = void*/>
struct push_back_container
{
static bool call(Container& c, T const& val)
{
c.insert(c.end(), val);
return true;
}
};
//]
template <typename Container, typename T>
struct push_back_container<optional<Container>, T>
{
static bool call(optional<Container>& c, T const& val)
{
if (!c)
c = Container();
return push_back(boost::get<Container>(c), val);
}
};
namespace detail
{
template <typename T>
struct push_back_visitor : public static_visitor<>
{
typedef bool result_type;
push_back_visitor(T const& t) : t_(t) {}
template <typename Container>
bool push_back_impl(Container& c, mpl::true_) const
{
return push_back(c, t_);
}
template <typename T_>
bool push_back_impl(T_&, mpl::false_) const
{
// this variant doesn't hold a container
BOOST_ASSERT(false && "This variant doesn't hold a container");
return false;
}
template <typename T_>
bool operator()(T_& c) const
{
return push_back_impl(c, typename is_container<T_>::type());
}
T const& t_;
};
}
template <BOOST_VARIANT_ENUM_PARAMS(typename T_), typename T>
struct push_back_container<variant<BOOST_VARIANT_ENUM_PARAMS(T_)>, T>
{
static bool call(variant<BOOST_VARIANT_ENUM_PARAMS(T_)>& c, T const& val)
{
return apply_visitor(detail::push_back_visitor<T>(val), c);
}
};
template <typename Container, typename T>
bool push_back(Container& c, T const& val)
{
return push_back_container<Container, T>::call(c, val);
}
//[customization_push_back_unused
template <typename Container>
bool push_back(Container&, unused_type)
{
return true;
}
//]
template <typename T>
bool push_back(unused_type, T const&)
{
return true;
}
inline bool push_back(unused_type, unused_type)
{
return true;
}
///////////////////////////////////////////////////////////////////////////
template <typename Container, typename Enable/* = void*/>
struct is_empty_container
{
static bool call(Container const& c)
{
return c.empty();
}
};
template <typename Container>
bool is_empty(Container const& c)
{
return is_empty_container<Container>::call(c);
}
inline bool is_empty(unused_type)
{
return true;
}
///////////////////////////////////////////////////////////////////////////
// Ensure the attribute is actually a container type
template <typename Container, typename Enable/* = void*/>
struct make_container_attribute
{
static void call(Container& c)
{
// for static types this function does nothing
}
};
template <typename T>
void make_container(T& t)
{
make_container_attribute<T>::call(t);
}
inline void make_container(unused_type)
{
}
///////////////////////////////////////////////////////////////////////////
template <typename Container, typename Enable/* = void*/>
struct begin_container
{
static typename container_iterator<Container>::type call(Container& c)
{
return c.begin();
}
};
template <typename Container>
typename spirit::result_of::begin<Container>::type
begin(Container& c)
{
return begin_container<Container>::call(c);
}
inline unused_type const*
begin(unused_type)
{
return &unused;
}
///////////////////////////////////////////////////////////////////////////
template <typename Container, typename Enable/* = void*/>
struct end_container
{
static typename container_iterator<Container>::type call(Container& c)
{
return c.end();
}
};
template <typename Container>
inline typename spirit::result_of::end<Container>::type
end(Container& c)
{
return end_container<Container>::call(c);
}
inline unused_type const*
end(unused_type)
{
return &unused;
}
///////////////////////////////////////////////////////////////////////////
template <typename Iterator, typename Enable/* = void*/>
struct deref_iterator
{
typedef typename boost::detail::iterator_traits<Iterator>::reference type;
static type call(Iterator& it)
{
return *it;
}
};
template <typename Iterator>
typename deref_iterator<Iterator>::type
deref(Iterator& it)
{
return deref_iterator<Iterator>::call(it);
}
inline unused_type
deref(unused_type const*)
{
return unused;
}
///////////////////////////////////////////////////////////////////////////
template <typename Iterator, typename Enable/* = void*/>
struct next_iterator
{
static void call(Iterator& it)
{
++it;
}
};
template <typename Iterator>
void next(Iterator& it)
{
next_iterator<Iterator>::call(it);
}
inline void next(unused_type const*)
{
// do nothing
}
///////////////////////////////////////////////////////////////////////////
template <typename Iterator, typename Enable/* = void*/>
struct compare_iterators
{
static bool call(Iterator const& it1, Iterator const& it2)
{
return it1 == it2;
}
};
template <typename Iterator>
bool compare(Iterator& it1, Iterator& it2)
{
return compare_iterators<Iterator>::call(it1, it2);
}
inline bool compare(unused_type const*, unused_type const*)
{
return false;
}
}}}
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace result_of
{
///////////////////////////////////////////////////////////////////////////
template <typename T>
struct optional_value
{
typedef T type;
};
template <typename T>
struct optional_value<optional<T> >
{
typedef T type;
};
template <typename T>
struct optional_value<optional<T> const>
{
typedef T const type;
};
template <>
struct optional_value<unused_type>
{
typedef unused_type type;
};
template <>
struct optional_value<unused_type const>
{
typedef unused_type type;
};
///////////////////////////////////////////////////////////////////////////
template <typename Container>
struct begin
: traits::container_iterator<Container>
{};
template <typename Container>
struct end
: traits::container_iterator<Container>
{};
template <typename Iterator>
struct deref
: traits::deref_iterator<Iterator>
{};
template <>
struct deref<unused_type const*>
{
typedef unused_type type;
};
}}}
#endif