Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2024-11-15 09:32:02

0001 /*=============================================================================
0002     Copyright (c) 2001-2011 Joel de Guzman
0003     Copyright (c) 2001-2011 Hartmut Kaiser
0004     http://spirit.sourceforge.net/
0005 
0006     Distributed under the Boost Software License, Version 1.0. (See accompanying
0007     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
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     //  This file contains some container utils for stl containers. The
0031     //  utilities provided also accept spirit's unused_type; all no-ops.
0032     //  Compiler optimization will easily strip these away.
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/* = void*/>
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     // make sure unused variant parameters do not affect the outcome
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/* = void*/>
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     //[customization_container_value_default
0129     template <typename Container, typename Enable/* = void*/>
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     // this will be instantiated if the optional holds a container
0141     template <typename T>
0142     struct container_value<boost::optional<T> >
0143       : container_value<T>
0144     {};
0145 
0146     // this will be instantiated if the variant holds a container
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     //[customization_container_value_unused
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/* = void*/>
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/* = void*/>
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     //[customization_push_back_default
0286     template <typename Container, typename T, typename Enable/* = void*/>
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                 // this variant doesn't hold a container
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     //[customization_push_back_unused
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/* = void*/>
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     // Ensure the attribute is actually a container type
0398     template <typename Container, typename Enable/* = void*/>
0399     struct make_container_attribute
0400     {
0401         static void call(Container&)
0402         {
0403             // for static types this function does nothing
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/* = void*/>
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/* = void*/>
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/* = void*/>
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/* = void*/>
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         // do nothing
0506     }
0507 
0508     ///////////////////////////////////////////////////////////////////////////
0509     template <typename Iterator, typename Enable/* = void*/>
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