File indexing completed on 2024-11-15 09:32:02
0001
0002
0003
0004
0005
0006
0007
0008
0009 #if !defined(BOOST_SPIRIT_CONTAINER_FEBRUARY_06_2007_1001AM)
0010 #define BOOST_SPIRIT_CONTAINER_FEBRUARY_06_2007_1001AM
0011
0012 #if defined(_MSC_VER)
0013 #pragma once
0014 #endif
0015
0016 #include <boost/spirit/home/support/unused.hpp>
0017 #include <boost/spirit/home/support/attributes_fwd.hpp>
0018 #include <boost/mpl/has_xxx.hpp>
0019 #include <boost/mpl/bool.hpp>
0020 #include <boost/optional.hpp>
0021 #include <boost/variant.hpp>
0022 #include <boost/preprocessor/cat.hpp>
0023 #include <boost/preprocessor/repeat.hpp>
0024 #include <boost/range/range_fwd.hpp>
0025 #include <iterator> // for std::iterator_traits
0026
0027 namespace boost { namespace spirit { namespace traits
0028 {
0029
0030
0031
0032
0033
0034
0035 namespace detail
0036 {
0037 BOOST_MPL_HAS_XXX_TRAIT_DEF(value_type)
0038 BOOST_MPL_HAS_XXX_TRAIT_DEF(iterator)
0039 BOOST_MPL_HAS_XXX_TRAIT_DEF(size_type)
0040 BOOST_MPL_HAS_XXX_TRAIT_DEF(reference)
0041 }
0042
0043 template <typename T, typename Enable>
0044 struct is_container
0045 : mpl::bool_<
0046 detail::has_value_type<T>::value &&
0047 detail::has_iterator<T>::value &&
0048 detail::has_size_type<T>::value &&
0049 detail::has_reference<T>::value>
0050 {};
0051
0052 template <typename T>
0053 struct is_container<T&>
0054 : is_container<T>
0055 {};
0056
0057 template <typename T>
0058 struct is_container<boost::optional<T> >
0059 : is_container<T>
0060 {};
0061
0062 #if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES)
0063 template<typename T>
0064 struct is_container<boost::variant<T> >
0065 : is_container<T>
0066 {};
0067
0068 template<typename T0, typename T1, typename ...TN>
0069 struct is_container<boost::variant<T0, T1, TN...> >
0070 : mpl::bool_<is_container<T0>::value ||
0071 is_container<boost::variant<T1, TN...> >::value>
0072 {};
0073
0074 #else
0075 #define BOOST_SPIRIT_IS_CONTAINER(z, N, data) \
0076 is_container<BOOST_PP_CAT(T, N)>::value || \
0077
0078
0079
0080 template <>
0081 struct is_container<boost::detail::variant::void_>
0082 : mpl::false_
0083 {};
0084
0085 template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
0086 struct is_container<variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
0087 : mpl::bool_<BOOST_PP_REPEAT(BOOST_VARIANT_LIMIT_TYPES
0088 , BOOST_SPIRIT_IS_CONTAINER, _) false>
0089 {};
0090
0091 #undef BOOST_SPIRIT_IS_CONTAINER
0092 #endif
0093
0094 template <typename T, typename Enable>
0095 struct is_iterator_range
0096 : mpl::false_
0097 {};
0098
0099 template <typename T>
0100 struct is_iterator_range<iterator_range<T> >
0101 : mpl::true_
0102 {};
0103
0104
0105 namespace detail
0106 {
0107 template <typename T>
0108 struct remove_value_const
0109 {
0110 typedef T type;
0111 };
0112
0113 template <typename T>
0114 struct remove_value_const<T const>
0115 : remove_value_const<T>
0116 {};
0117
0118 template <typename F, typename S>
0119 struct remove_value_const<std::pair<F, S> >
0120 {
0121 typedef typename remove_value_const<F>::type first_type;
0122 typedef typename remove_value_const<S>::type second_type;
0123 typedef std::pair<first_type, second_type> type;
0124 };
0125 }
0126
0127
0128
0129 template <typename Container, typename Enable>
0130 struct container_value
0131 : detail::remove_value_const<typename Container::value_type>
0132 {};
0133
0134
0135 template <typename T>
0136 struct container_value<T&>
0137 : container_value<T>
0138 {};
0139
0140
0141 template <typename T>
0142 struct container_value<boost::optional<T> >
0143 : container_value<T>
0144 {};
0145
0146
0147 template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
0148 struct container_value<variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
0149 {
0150 typedef typename
0151 variant<BOOST_VARIANT_ENUM_PARAMS(T)>::types
0152 types;
0153 typedef typename
0154 mpl::find_if<types, is_container<mpl::_1> >::type
0155 iter;
0156
0157 typedef typename container_value<
0158 typename mpl::if_<
0159 is_same<iter, typename mpl::end<types>::type>
0160 , unused_type, typename mpl::deref<iter>::type
0161 >::type
0162 >::type type;
0163 };
0164
0165
0166 template <>
0167 struct container_value<unused_type>
0168 {
0169 typedef unused_type type;
0170 };
0171
0172
0173 template <>
0174 struct container_value<unused_type const>
0175 {
0176 typedef unused_type type;
0177 };
0178
0179
0180 template <typename Container, typename Enable>
0181 struct container_iterator
0182 {
0183 typedef typename Container::iterator type;
0184 };
0185
0186 template <typename Container>
0187 struct container_iterator<Container&>
0188 : container_iterator<Container>
0189 {};
0190
0191 template <typename Container>
0192 struct container_iterator<Container const>
0193 {
0194 typedef typename Container::const_iterator type;
0195 };
0196
0197 template <typename T>
0198 struct container_iterator<optional<T> >
0199 : container_iterator<T>
0200 {};
0201
0202 template <typename T>
0203 struct container_iterator<optional<T> const>
0204 : container_iterator<T const>
0205 {};
0206
0207 template <typename Iterator>
0208 struct container_iterator<iterator_range<Iterator> >
0209 {
0210 typedef Iterator type;
0211 };
0212
0213 template <>
0214 struct container_iterator<unused_type>
0215 {
0216 typedef unused_type const* type;
0217 };
0218
0219 template <>
0220 struct container_iterator<unused_type const>
0221 {
0222 typedef unused_type const* type;
0223 };
0224
0225
0226 template <typename T, typename Enable>
0227 struct optional_attribute
0228 {
0229 typedef T const& type;
0230
0231 static type call(T const& val)
0232 {
0233 return val;
0234 }
0235
0236 static bool is_valid(T const&)
0237 {
0238 return true;
0239 }
0240 };
0241
0242 template <typename T>
0243 struct optional_attribute<boost::optional<T> >
0244 {
0245 typedef T const& type;
0246
0247 static type call(boost::optional<T> const& val)
0248 {
0249 return boost::get<T>(val);
0250 }
0251
0252 static bool is_valid(boost::optional<T> const& val)
0253 {
0254 return !!val;
0255 }
0256 };
0257
0258 template <typename T>
0259 typename optional_attribute<T>::type
0260 optional_value(T const& val)
0261 {
0262 return optional_attribute<T>::call(val);
0263 }
0264
0265 inline unused_type optional_value(unused_type)
0266 {
0267 return unused;
0268 }
0269
0270 template <typename T>
0271 bool has_optional_value(T const& val)
0272 {
0273 return optional_attribute<T>::is_valid(val);
0274 }
0275
0276 inline bool has_optional_value(unused_type)
0277 {
0278 return true;
0279 }
0280
0281
0282 template <typename Container, typename T>
0283 bool push_back(Container& c, T const& val);
0284
0285
0286 template <typename Container, typename T, typename Enable>
0287 struct push_back_container
0288 {
0289 static bool call(Container& c, T const& val)
0290 {
0291 c.insert(c.end(), val);
0292 return true;
0293 }
0294 };
0295
0296
0297 template <typename Container, typename T>
0298 struct push_back_container<optional<Container>, T>
0299 {
0300 static bool call(boost::optional<Container>& c, T const& val)
0301 {
0302 if (!c)
0303 c = Container();
0304 return push_back(boost::get<Container>(c), val);
0305 }
0306 };
0307
0308 namespace detail
0309 {
0310 template <typename T>
0311 struct push_back_visitor : public static_visitor<>
0312 {
0313 typedef bool result_type;
0314
0315 push_back_visitor(T const& t) : t_(t) {}
0316
0317 template <typename Container>
0318 bool push_back_impl(Container& c, mpl::true_) const
0319 {
0320 return push_back(c, t_);
0321 }
0322
0323 template <typename T_>
0324 bool push_back_impl(T_&, mpl::false_) const
0325 {
0326
0327 BOOST_ASSERT(false && "This variant doesn't hold a container");
0328 return false;
0329 }
0330
0331 template <typename T_>
0332 bool operator()(T_& c) const
0333 {
0334 return push_back_impl(c, typename is_container<T_>::type());
0335 }
0336
0337 T const& t_;
0338 };
0339 }
0340
0341 template <BOOST_VARIANT_ENUM_PARAMS(typename T_), typename T>
0342 struct push_back_container<variant<BOOST_VARIANT_ENUM_PARAMS(T_)>, T>
0343 {
0344 static bool call(variant<BOOST_VARIANT_ENUM_PARAMS(T_)>& c, T const& val)
0345 {
0346 return apply_visitor(detail::push_back_visitor<T>(val), c);
0347 }
0348 };
0349
0350 template <typename Container, typename T>
0351 bool push_back(Container& c, T const& val)
0352 {
0353 return push_back_container<Container, T>::call(c, val);
0354 }
0355
0356
0357 template <typename Container>
0358 bool push_back(Container&, unused_type)
0359 {
0360 return true;
0361 }
0362
0363
0364 template <typename T>
0365 bool push_back(unused_type, T const&)
0366 {
0367 return true;
0368 }
0369
0370 inline bool push_back(unused_type, unused_type)
0371 {
0372 return true;
0373 }
0374
0375
0376 template <typename Container, typename Enable>
0377 struct is_empty_container
0378 {
0379 static bool call(Container const& c)
0380 {
0381 return c.empty();
0382 }
0383 };
0384
0385 template <typename Container>
0386 bool is_empty(Container const& c)
0387 {
0388 return is_empty_container<Container>::call(c);
0389 }
0390
0391 inline bool is_empty(unused_type)
0392 {
0393 return true;
0394 }
0395
0396
0397
0398 template <typename Container, typename Enable>
0399 struct make_container_attribute
0400 {
0401 static void call(Container&)
0402 {
0403
0404 }
0405 };
0406
0407 template <typename T>
0408 void make_container(T& t)
0409 {
0410 make_container_attribute<T>::call(t);
0411 }
0412
0413 inline void make_container(unused_type)
0414 {
0415 }
0416
0417
0418 template <typename Container, typename Enable>
0419 struct begin_container
0420 {
0421 static typename container_iterator<Container>::type call(Container& c)
0422 {
0423 return c.begin();
0424 }
0425 };
0426
0427 template <typename Container>
0428 typename spirit::result_of::begin<Container>::type
0429 begin(Container& c)
0430 {
0431 return begin_container<Container>::call(c);
0432 }
0433
0434 inline unused_type const*
0435 begin(unused_type)
0436 {
0437 return &unused;
0438 }
0439
0440
0441 template <typename Container, typename Enable>
0442 struct end_container
0443 {
0444 static typename container_iterator<Container>::type call(Container& c)
0445 {
0446 return c.end();
0447 }
0448 };
0449
0450 template <typename Container>
0451 inline typename spirit::result_of::end<Container>::type
0452 end(Container& c)
0453 {
0454 return end_container<Container>::call(c);
0455 }
0456
0457 inline unused_type const*
0458 end(unused_type)
0459 {
0460 return &unused;
0461 }
0462
0463
0464 template <typename Iterator, typename Enable>
0465 struct deref_iterator
0466 {
0467 typedef typename std::iterator_traits<Iterator>::reference type;
0468 static type call(Iterator& it)
0469 {
0470 return *it;
0471 }
0472 };
0473
0474 template <typename Iterator>
0475 typename deref_iterator<Iterator>::type
0476 deref(Iterator& it)
0477 {
0478 return deref_iterator<Iterator>::call(it);
0479 }
0480
0481 inline unused_type
0482 deref(unused_type const*)
0483 {
0484 return unused;
0485 }
0486
0487
0488 template <typename Iterator, typename Enable>
0489 struct next_iterator
0490 {
0491 static void call(Iterator& it)
0492 {
0493 ++it;
0494 }
0495 };
0496
0497 template <typename Iterator>
0498 void next(Iterator& it)
0499 {
0500 next_iterator<Iterator>::call(it);
0501 }
0502
0503 inline void next(unused_type const*)
0504 {
0505
0506 }
0507
0508
0509 template <typename Iterator, typename Enable>
0510 struct compare_iterators
0511 {
0512 static bool call(Iterator const& it1, Iterator const& it2)
0513 {
0514 return it1 == it2;
0515 }
0516 };
0517
0518 template <typename Iterator>
0519 bool compare(Iterator& it1, Iterator& it2)
0520 {
0521 return compare_iterators<Iterator>::call(it1, it2);
0522 }
0523
0524 inline bool compare(unused_type const*, unused_type const*)
0525 {
0526 return false;
0527 }
0528 }}}
0529
0530
0531 namespace boost { namespace spirit { namespace result_of
0532 {
0533
0534 template <typename T>
0535 struct optional_value
0536 {
0537 typedef T type;
0538 };
0539
0540 template <typename T>
0541 struct optional_value<boost::optional<T> >
0542 {
0543 typedef T type;
0544 };
0545
0546 template <typename T>
0547 struct optional_value<boost::optional<T> const>
0548 {
0549 typedef T const type;
0550 };
0551
0552 template <>
0553 struct optional_value<unused_type>
0554 {
0555 typedef unused_type type;
0556 };
0557
0558 template <>
0559 struct optional_value<unused_type const>
0560 {
0561 typedef unused_type type;
0562 };
0563
0564
0565 template <typename Container>
0566 struct begin
0567 : traits::container_iterator<Container>
0568 {};
0569
0570 template <typename Container>
0571 struct end
0572 : traits::container_iterator<Container>
0573 {};
0574
0575 template <typename Iterator>
0576 struct deref
0577 : traits::deref_iterator<Iterator>
0578 {};
0579
0580 template <>
0581 struct deref<unused_type const*>
0582 {
0583 typedef unused_type type;
0584 };
0585
0586 }}}
0587
0588 #endif