123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340 |
- /*=============================================================================
- Copyright (c) 2001-2014 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_X3_CONTAINER_FEBRUARY_06_2007_1001AM)
- #define BOOST_SPIRIT_X3_CONTAINER_FEBRUARY_06_2007_1001AM
- #include <boost/fusion/support/category_of.hpp>
- #include <boost/spirit/home/x3/support/unused.hpp>
- #include <boost/fusion/include/deque.hpp>
- #include <boost/mpl/identity.hpp>
- #include <boost/type_traits/make_void.hpp>
- #include <vector>
- #include <string>
- #include <iterator>
- #include <algorithm>
- namespace boost { namespace spirit { namespace x3 { namespace traits
- {
- ///////////////////////////////////////////////////////////////////////////
- // This file contains some container utils for stl containers.
- ///////////////////////////////////////////////////////////////////////////
- namespace detail
- {
- template <typename T, typename Enabler = void>
- struct is_container_impl : mpl::false_ {};
- template <typename T>
- struct is_container_impl<T, void_t<
- typename T::value_type, typename T::iterator,
- typename T::size_type, typename T::reference> > : mpl::true_ {};
- template <typename T, typename Enabler = void>
- struct is_associative_impl : mpl::false_ {};
- template <typename T>
- struct is_associative_impl<T, void_t<typename T::key_type>>
- : mpl::true_ {};
- }
- template <typename T>
- using is_container = typename detail::is_container_impl<T>::type;
- template <typename T>
- using is_associative = typename detail::is_associative_impl<T>::type;
- ///////////////////////////////////////////////////////////////////////////
- namespace detail
- {
- template <typename T>
- struct remove_value_const : mpl::identity<T> {};
- 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;
- };
- }
- ///////////////////////////////////////////////////////////////////////
- template <typename Container, typename Enable = void>
- struct container_value
- : detail::remove_value_const<typename Container::value_type>
- {};
- template <typename Container>
- struct container_value<Container const> : container_value<Container> {};
- // There is no single container value for fusion maps, but because output
- // of this metafunc is used to check wheter parser's attribute can be
- // saved to container, we simply return whole fusion::map as is
- // so that check can be done in traits::is_substitute specialisation
- template <typename T>
- struct container_value<T
- , typename enable_if<typename mpl::eval_if <
- fusion::traits::is_sequence<T>
- , fusion::traits::is_associative<T>
- , mpl::false_ >::type >::type>
- : mpl::identity<T> {};
- template <>
- struct container_value<unused_type> : mpl::identity<unused_type> {};
- ///////////////////////////////////////////////////////////////////////////
- template <typename Container, typename Enable = void>
- struct container_iterator
- : mpl::identity<typename Container::iterator> {};
- template <typename Container>
- struct container_iterator<Container const>
- : mpl::identity<typename Container::const_iterator> {};
- template <>
- struct container_iterator<unused_type>
- : mpl::identity<unused_type const*> {};
- template <>
- struct container_iterator<unused_type const>
- : mpl::identity<unused_type const*> {};
- ///////////////////////////////////////////////////////////////////////////
- template <typename Container, typename T>
- bool push_back(Container& c, T&& val);
- template <typename Container, typename Enable = void>
- struct push_back_container
- {
- template <typename T>
- static bool call(Container& c, T&& val)
- {
- c.insert(c.end(), static_cast<T&&>(val));
- return true;
- }
- };
- template <typename Container, typename T>
- inline bool push_back(Container& c, T&& val)
- {
- return push_back_container<Container>::call(c, static_cast<T&&>(val));
- }
- template <typename Container>
- inline bool push_back(Container&, unused_type)
- {
- return true;
- }
- template <typename T>
- inline bool push_back(unused_type, T&&)
- {
- return true;
- }
- inline bool push_back(unused_type, unused_type)
- {
- return true;
- }
- ///////////////////////////////////////////////////////////////////////////
- template <typename Container, typename Iterator>
- bool append(Container& c, Iterator first, Iterator last);
- template <typename Container, typename Enable = void>
- struct append_container
- {
- private:
- template <typename Iterator>
- static void insert(Container& c, Iterator first, Iterator last, mpl::false_)
- {
- c.insert(c.end(), first, last);
- }
- template <typename Iterator>
- static void insert(Container& c, Iterator first, Iterator last, mpl::true_)
- {
- c.insert(first, last);
- }
- public:
- template <typename Iterator>
- static bool call(Container& c, Iterator first, Iterator last)
- {
- insert(c, first, last, is_associative<Container>{});
- return true;
- }
- };
- template <typename Container, typename Iterator>
- inline bool append(Container& c, Iterator first, Iterator last)
- {
- return append_container<Container>::call(c, first, last);
- }
- template <typename Iterator>
- inline bool append(unused_type, Iterator /* first */, Iterator /* last */)
- {
- return true;
- }
- ///////////////////////////////////////////////////////////////////////////
- template <typename Container, typename Enable = void>
- struct is_empty_container
- {
- static bool call(Container const& c)
- {
- return c.empty();
- }
- };
- template <typename Container>
- inline bool is_empty(Container const& c)
- {
- return is_empty_container<Container>::call(c);
- }
- inline bool is_empty(unused_type)
- {
- return true;
- }
- ///////////////////////////////////////////////////////////////////////////
- template <typename Container, typename Enable = void>
- struct begin_container
- {
- static typename container_iterator<Container>::type call(Container& c)
- {
- return c.begin();
- }
- };
- template <typename Container>
- inline typename container_iterator<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 container_iterator<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 std::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;
- }
- ///////////////////////////////////////////////////////////////////////////
- template <typename T>
- struct build_container : mpl::identity<std::vector<T>> {};
- template <typename T>
- struct build_container<boost::fusion::deque<T> > : build_container<T> {};
- template <>
- struct build_container<unused_type> : mpl::identity<unused_type> {};
- template <>
- struct build_container<char> : mpl::identity<std::string> {};
- }}}}
- #endif
|