1 /*============================================================================= 2 Copyright (c) 2001-2014 Joel de Guzman 3 Copyright (c) 2001-2011 Hartmut Kaiser 4 http://spirit.sourceforge.net/ 5 6 Distributed under the Boost Software License, Version 1.0. (See accompanying 7 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 8 =============================================================================*/ 9 #if !defined(BOOST_SPIRIT_X3_CONTAINER_FEBRUARY_06_2007_1001AM) 10 #define BOOST_SPIRIT_X3_CONTAINER_FEBRUARY_06_2007_1001AM 11 12 #include <boost/fusion/support/category_of.hpp> 13 #include <boost/spirit/home/x3/support/unused.hpp> 14 #include <boost/fusion/include/deque.hpp> 15 #include <boost/mpl/identity.hpp> 16 #include <boost/type_traits/make_void.hpp> 17 18 #include <vector> 19 #include <string> 20 #include <iterator> 21 #include <algorithm> 22 23 namespace boost { namespace spirit { namespace x3 { namespace traits 24 { 25 /////////////////////////////////////////////////////////////////////////// 26 // This file contains some container utils for stl containers. 27 /////////////////////////////////////////////////////////////////////////// 28 29 namespace detail 30 { 31 template <typename T, typename Enabler = void> 32 struct is_container_impl : mpl::false_ {}; 33 34 template <typename T> 35 struct is_container_impl<T, void_t< 36 typename T::value_type, typename T::iterator, 37 typename T::size_type, typename T::reference> > : mpl::true_ {}; 38 39 template <typename T, typename Enabler = void> 40 struct is_associative_impl : mpl::false_ {}; 41 42 template <typename T> 43 struct is_associative_impl<T, void_t<typename T::key_type>> 44 : mpl::true_ {}; 45 } 46 47 template <typename T> 48 using is_container = typename detail::is_container_impl<T>::type; 49 50 template <typename T> 51 using is_associative = typename detail::is_associative_impl<T>::type; 52 53 /////////////////////////////////////////////////////////////////////////// 54 namespace detail 55 { 56 template <typename T> 57 struct remove_value_const : mpl::identity<T> {}; 58 59 template <typename T> 60 struct remove_value_const<T const> : remove_value_const<T> {}; 61 62 template <typename F, typename S> 63 struct remove_value_const<std::pair<F, S>> 64 { 65 typedef typename remove_value_const<F>::type first_type; 66 typedef typename remove_value_const<S>::type second_type; 67 typedef std::pair<first_type, second_type> type; 68 }; 69 } 70 71 /////////////////////////////////////////////////////////////////////// 72 template <typename Container, typename Enable = void> 73 struct container_value 74 : detail::remove_value_const<typename Container::value_type> 75 {}; 76 77 template <typename Container> 78 struct container_value<Container const> : container_value<Container> {}; 79 80 // There is no single container value for fusion maps, but because output 81 // of this metafunc is used to check wheter parser's attribute can be 82 // saved to container, we simply return whole fusion::map as is 83 // so that check can be done in traits::is_substitute specialisation 84 template <typename T> 85 struct container_value<T 86 , typename enable_if<typename mpl::eval_if < 87 fusion::traits::is_sequence<T> 88 , fusion::traits::is_associative<T> 89 , mpl::false_ >::type >::type> 90 : mpl::identity<T> {}; 91 92 template <> 93 struct container_value<unused_type> : mpl::identity<unused_type> {}; 94 95 /////////////////////////////////////////////////////////////////////////// 96 template <typename Container, typename Enable = void> 97 struct container_iterator 98 : mpl::identity<typename Container::iterator> {}; 99 100 template <typename Container> 101 struct container_iterator<Container const> 102 : mpl::identity<typename Container::const_iterator> {}; 103 104 template <> 105 struct container_iterator<unused_type> 106 : mpl::identity<unused_type const*> {}; 107 108 template <> 109 struct container_iterator<unused_type const> 110 : mpl::identity<unused_type const*> {}; 111 112 /////////////////////////////////////////////////////////////////////////// 113 template <typename Container, typename T> 114 bool push_back(Container& c, T&& val); 115 116 template <typename Container, typename Enable = void> 117 struct push_back_container 118 { 119 template <typename T> callboost::spirit::x3::traits::push_back_container120 static bool call(Container& c, T&& val) 121 { 122 c.insert(c.end(), static_cast<T&&>(val)); 123 return true; 124 } 125 }; 126 127 template <typename Container, typename T> push_back(Container & c,T && val)128 inline bool push_back(Container& c, T&& val) 129 { 130 return push_back_container<Container>::call(c, static_cast<T&&>(val)); 131 } 132 133 template <typename Container> push_back(Container &,unused_type)134 inline bool push_back(Container&, unused_type) 135 { 136 return true; 137 } 138 139 template <typename T> push_back(unused_type,T &&)140 inline bool push_back(unused_type, T&&) 141 { 142 return true; 143 } 144 push_back(unused_type,unused_type)145 inline bool push_back(unused_type, unused_type) 146 { 147 return true; 148 } 149 150 /////////////////////////////////////////////////////////////////////////// 151 template <typename Container, typename Iterator> 152 bool append(Container& c, Iterator first, Iterator last); 153 154 template <typename Container, typename Enable = void> 155 struct append_container 156 { 157 private: 158 template <typename Iterator> insertboost::spirit::x3::traits::append_container159 static void insert(Container& c, Iterator first, Iterator last, mpl::false_) 160 { 161 c.insert(c.end(), first, last); 162 } 163 164 template <typename Iterator> insertboost::spirit::x3::traits::append_container165 static void insert(Container& c, Iterator first, Iterator last, mpl::true_) 166 { 167 c.insert(first, last); 168 } 169 170 public: 171 template <typename Iterator> callboost::spirit::x3::traits::append_container172 static bool call(Container& c, Iterator first, Iterator last) 173 { 174 insert(c, first, last, is_associative<Container>{}); 175 return true; 176 } 177 }; 178 179 template <typename Container, typename Iterator> append(Container & c,Iterator first,Iterator last)180 inline bool append(Container& c, Iterator first, Iterator last) 181 { 182 return append_container<Container>::call(c, first, last); 183 } 184 185 template <typename Iterator> append(unused_type,Iterator,Iterator)186 inline bool append(unused_type, Iterator /* first */, Iterator /* last */) 187 { 188 return true; 189 } 190 191 /////////////////////////////////////////////////////////////////////////// 192 template <typename Container, typename Enable = void> 193 struct is_empty_container 194 { callboost::spirit::x3::traits::is_empty_container195 static bool call(Container const& c) 196 { 197 return c.empty(); 198 } 199 }; 200 201 template <typename Container> is_empty(Container const & c)202 inline bool is_empty(Container const& c) 203 { 204 return is_empty_container<Container>::call(c); 205 } 206 is_empty(unused_type)207 inline bool is_empty(unused_type) 208 { 209 return true; 210 } 211 212 /////////////////////////////////////////////////////////////////////////// 213 template <typename Container, typename Enable = void> 214 struct begin_container 215 { callboost::spirit::x3::traits::begin_container216 static typename container_iterator<Container>::type call(Container& c) 217 { 218 return c.begin(); 219 } 220 }; 221 222 template <typename Container> 223 inline typename container_iterator<Container>::type begin(Container & c)224 begin(Container& c) 225 { 226 return begin_container<Container>::call(c); 227 } 228 229 inline unused_type const* begin(unused_type)230 begin(unused_type) 231 { 232 return &unused; 233 } 234 235 /////////////////////////////////////////////////////////////////////////// 236 template <typename Container, typename Enable = void> 237 struct end_container 238 { callboost::spirit::x3::traits::end_container239 static typename container_iterator<Container>::type call(Container& c) 240 { 241 return c.end(); 242 } 243 }; 244 245 template <typename Container> 246 inline typename container_iterator<Container>::type end(Container & c)247 end(Container& c) 248 { 249 return end_container<Container>::call(c); 250 } 251 252 inline unused_type const* end(unused_type)253 end(unused_type) 254 { 255 return &unused; 256 } 257 258 259 /////////////////////////////////////////////////////////////////////////// 260 template <typename Iterator, typename Enable = void> 261 struct deref_iterator 262 { 263 typedef typename std::iterator_traits<Iterator>::reference type; callboost::spirit::x3::traits::deref_iterator264 static type call(Iterator& it) 265 { 266 return *it; 267 } 268 }; 269 270 template <typename Iterator> 271 typename deref_iterator<Iterator>::type deref(Iterator & it)272 deref(Iterator& it) 273 { 274 return deref_iterator<Iterator>::call(it); 275 } 276 277 inline unused_type deref(unused_type const *)278 deref(unused_type const*) 279 { 280 return unused; 281 } 282 283 /////////////////////////////////////////////////////////////////////////// 284 template <typename Iterator, typename Enable = void> 285 struct next_iterator 286 { callboost::spirit::x3::traits::next_iterator287 static void call(Iterator& it) 288 { 289 ++it; 290 } 291 }; 292 293 template <typename Iterator> next(Iterator & it)294 void next(Iterator& it) 295 { 296 next_iterator<Iterator>::call(it); 297 } 298 next(unused_type const *)299 inline void next(unused_type const*) 300 { 301 // do nothing 302 } 303 304 /////////////////////////////////////////////////////////////////////////// 305 template <typename Iterator, typename Enable = void> 306 struct compare_iterators 307 { callboost::spirit::x3::traits::compare_iterators308 static bool call(Iterator const& it1, Iterator const& it2) 309 { 310 return it1 == it2; 311 } 312 }; 313 314 template <typename Iterator> compare(Iterator & it1,Iterator & it2)315 bool compare(Iterator& it1, Iterator& it2) 316 { 317 return compare_iterators<Iterator>::call(it1, it2); 318 } 319 compare(unused_type const *,unused_type const *)320 inline bool compare(unused_type const*, unused_type const*) 321 { 322 return false; 323 } 324 325 /////////////////////////////////////////////////////////////////////////// 326 template <typename T> 327 struct build_container : mpl::identity<std::vector<T>> {}; 328 329 template <typename T> 330 struct build_container<boost::fusion::deque<T> > : build_container<T> {}; 331 332 template <> 333 struct build_container<unused_type> : mpl::identity<unused_type> {}; 334 335 template <> 336 struct build_container<char> : mpl::identity<std::string> {}; 337 338 }}}} 339 340 #endif 341