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