1 /*============================================================================= 2 Copyright (c) 2001-2011 Hartmut Kaiser 3 Copyright (c) 2001-2011 Joel de Guzman 4 5 Distributed under the Boost Software License, Version 1.0. (See accompanying 6 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 ==============================================================================*/ 8 #if !defined(BOOST_SPIRIT_ANY_IF_MARCH_30_2007_1220PM) 9 #define BOOST_SPIRIT_ANY_IF_MARCH_30_2007_1220PM 10 11 #if defined(_MSC_VER) 12 #pragma once 13 #endif 14 15 #include <boost/fusion/include/equal_to.hpp> 16 #include <boost/fusion/include/next.hpp> 17 #include <boost/fusion/include/deref.hpp> 18 #include <boost/fusion/include/value_of.hpp> 19 #include <boost/fusion/include/begin.hpp> 20 #include <boost/fusion/include/end.hpp> 21 #include <boost/fusion/include/is_sequence.hpp> 22 #include <boost/fusion/include/any.hpp> 23 #include <boost/spirit/home/support/unused.hpp> 24 25 #include <boost/mpl/bool.hpp> 26 #include <boost/mpl/apply.hpp> 27 #include <boost/mpl/if.hpp> 28 #include <boost/mpl/identity.hpp> 29 #include <boost/mpl/and.hpp> 30 #include <boost/mpl/not.hpp> 31 32 namespace boost { namespace spirit 33 { 34 /////////////////////////////////////////////////////////////////////////// 35 // This is a special version for a binary fusion::any. The predicate 36 // is used to decide whether to advance the second iterator or not. 37 // This is needed for sequences containing components with unused 38 // attributes. The second iterator is advanced only if the attribute 39 // of the corresponding component iterator is not unused. 40 /////////////////////////////////////////////////////////////////////////// 41 namespace detail 42 { 43 /////////////////////////////////////////////////////////////////////// 44 template <typename Iterator, typename Pred> 45 struct apply_predicate 46 : mpl::apply1<Pred, typename fusion::result_of::value_of<Iterator>::type> 47 {}; 48 49 /////////////////////////////////////////////////////////////////////// 50 // if the predicate is true, attribute_next returns next(Iterator2), 51 // otherwise Iterator2 52 namespace result_of 53 { 54 template < 55 typename Iterator1, typename Iterator2, typename Last2 56 , typename Pred> 57 struct attribute_next 58 { 59 typedef mpl::and_< 60 apply_predicate<Iterator1, Pred> 61 , mpl::not_<fusion::result_of::equal_to<Iterator2, Last2> > 62 > pred; 63 64 typedef typename 65 mpl::eval_if< 66 pred 67 , fusion::result_of::next<Iterator2> 68 , mpl::identity<Iterator2> 69 >::type 70 type; 71 72 template <typename Iterator> 73 static type callboost::spirit::detail::result_of::attribute_next74 call(Iterator const& i, mpl::true_) 75 { 76 return fusion::next(i); 77 } 78 79 template <typename Iterator> 80 static type callboost::spirit::detail::result_of::attribute_next81 call(Iterator const& i, mpl::false_) 82 { 83 return i; 84 } 85 86 template <typename Iterator> 87 static type callboost::spirit::detail::result_of::attribute_next88 call(Iterator const& i) 89 { 90 return call(i, pred()); 91 } 92 }; 93 } 94 95 template < 96 typename Pred, typename Iterator1, typename Last2 97 , typename Iterator2> 98 inline typename 99 result_of::attribute_next<Iterator1, Iterator2, Last2, Pred 100 >::type const attribute_next(Iterator2 const & i)101 attribute_next(Iterator2 const& i) 102 { 103 return result_of::attribute_next< 104 Iterator1, Iterator2, Last2, Pred>::call(i); 105 } 106 107 /////////////////////////////////////////////////////////////////////// 108 // if the predicate is true, attribute_value returns deref(Iterator2), 109 // otherwise unused 110 namespace result_of 111 { 112 template < 113 typename Iterator1, typename Iterator2, typename Last2 114 , typename Pred> 115 struct attribute_value 116 { 117 typedef mpl::and_< 118 apply_predicate<Iterator1, Pred> 119 , mpl::not_<fusion::result_of::equal_to<Iterator2, Last2> > 120 > pred; 121 122 typedef typename 123 mpl::eval_if< 124 pred 125 , fusion::result_of::deref<Iterator2> 126 , mpl::identity<unused_type const> 127 >::type 128 type; 129 130 template <typename Iterator> 131 static type callboost::spirit::detail::result_of::attribute_value132 call(Iterator const& i, mpl::true_) 133 { 134 return fusion::deref(i); 135 } 136 137 template <typename Iterator> 138 static type callboost::spirit::detail::result_of::attribute_value139 call(Iterator const&, mpl::false_) 140 { 141 return unused; 142 } 143 144 template <typename Iterator> 145 static type callboost::spirit::detail::result_of::attribute_value146 call(Iterator const& i) 147 { 148 return call(i, pred()); 149 } 150 }; 151 } 152 153 template < 154 typename Pred, typename Iterator1, typename Last2 155 , typename Iterator2> 156 inline typename 157 result_of::attribute_value<Iterator1, Iterator2, Last2, Pred 158 >::type attribute_value(Iterator2 const & i)159 attribute_value(Iterator2 const& i) 160 { 161 return result_of::attribute_value< 162 Iterator1, Iterator2, Last2, Pred>::call(i); 163 } 164 165 /////////////////////////////////////////////////////////////////////// 166 template < 167 typename Pred, typename First1, typename Last1, typename First2 168 , typename Last2, typename F> 169 inline bool any_if(First1 const &,First2 const &,Last1 const &,Last2 const &,F const &,mpl::true_)170 any_if (First1 const&, First2 const&, Last1 const&, Last2 const& 171 , F const&, mpl::true_) 172 { 173 return false; 174 } 175 176 template < 177 typename Pred, typename First1, typename Last1, typename First2 178 , typename Last2, typename F> 179 inline bool any_if(First1 const & first1,First2 const & first2,Last1 const & last1,Last2 const & last2,F & f,mpl::false_)180 any_if (First1 const& first1, First2 const& first2, Last1 const& last1 181 , Last2 const& last2, F& f, mpl::false_) 182 { 183 typename result_of::attribute_value<First1, First2, Last2, Pred>::type 184 attribute = spirit::detail::attribute_value<Pred, First1, Last2>(first2); 185 186 return f(*first1, attribute) || 187 detail::any_if<Pred>( 188 fusion::next(first1) 189 , attribute_next<Pred, First1, Last2>(first2) 190 , last1, last2 191 , f 192 , fusion::result_of::equal_to< 193 typename fusion::result_of::next<First1>::type, Last1>()); 194 } 195 } 196 197 template <typename Pred, typename Sequence1, typename Sequence2, typename F> 198 inline bool any_if(Sequence1 const & seq1,Sequence2 & seq2,F f,Pred)199 any_if(Sequence1 const& seq1, Sequence2& seq2, F f, Pred) 200 { 201 return detail::any_if<Pred>( 202 fusion::begin(seq1), fusion::begin(seq2) 203 , fusion::end(seq1), fusion::end(seq2) 204 , f 205 , fusion::result_of::equal_to< 206 typename fusion::result_of::begin<Sequence1>::type 207 , typename fusion::result_of::end<Sequence1>::type>()); 208 } 209 210 template <typename Pred, typename Sequence, typename F> 211 inline bool any_if(Sequence const & seq,unused_type const,F f,Pred)212 any_if(Sequence const& seq, unused_type const, F f, Pred) 213 { 214 return fusion::any(seq, f); 215 } 216 217 }} 218 219 #endif 220 221