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