File indexing completed on 2025-01-19 09:47:43
0001
0002
0003
0004
0005
0006
0007
0008
0009 #if !defined(BOOST_SPIRIT_ASSIGN_TO_APR_16_2006_0812PM)
0010 #define BOOST_SPIRIT_ASSIGN_TO_APR_16_2006_0812PM
0011
0012 #if defined(_MSC_VER)
0013 #pragma once
0014 #endif
0015
0016 #include <boost/spirit/home/qi/detail/construct.hpp>
0017 #include <boost/spirit/home/support/unused.hpp>
0018 #include <boost/spirit/home/qi/detail/attributes.hpp>
0019 #include <boost/spirit/home/support/container.hpp>
0020 #include <boost/fusion/include/copy.hpp>
0021 #include <boost/fusion/adapted/struct/detail/extension.hpp>
0022 #include <boost/ref.hpp>
0023 #include <boost/range/range_fwd.hpp>
0024
0025 namespace boost { namespace spirit { namespace traits
0026 {
0027
0028
0029
0030
0031
0032 namespace detail
0033 {
0034 template <typename T>
0035 struct is_iter_range : mpl::false_ {};
0036
0037 template <typename I>
0038 struct is_iter_range<boost::iterator_range<I> > : mpl::true_ {};
0039
0040 template <typename C>
0041 struct is_container_of_ranges
0042 : is_iter_range<typename C::value_type> {};
0043 }
0044
0045 template <typename Attribute, typename Iterator, typename Enable>
0046 struct assign_to_attribute_from_iterators
0047 {
0048
0049 static void
0050 call(Iterator const& first, Iterator const& last, Attribute& attr, mpl::false_)
0051 {
0052 if (traits::is_empty(attr))
0053 attr = Attribute(first, last);
0054 else {
0055 for (Iterator i = first; i != last; ++i)
0056 push_back(attr, *i);
0057 }
0058 }
0059
0060
0061
0062 static void
0063 call(Iterator const& first, Iterator const& last, Attribute& attr, mpl::true_)
0064 {
0065 typename Attribute::value_type rng(first, last);
0066 push_back(attr, rng);
0067 }
0068
0069 static void
0070 call(Iterator const& first, Iterator const& last, Attribute& attr)
0071 {
0072 call(first, last, attr, detail::is_container_of_ranges<Attribute>());
0073 }
0074 };
0075
0076 template <typename Attribute, typename Iterator>
0077 struct assign_to_attribute_from_iterators<
0078 reference_wrapper<Attribute>, Iterator>
0079 {
0080 static void
0081 call(Iterator const& first, Iterator const& last
0082 , reference_wrapper<Attribute> attr)
0083 {
0084 if (traits::is_empty(attr))
0085 attr = Attribute(first, last);
0086 else {
0087 for (Iterator i = first; i != last; ++i)
0088 push_back(attr, *i);
0089 }
0090 }
0091 };
0092
0093 template <typename Attribute, typename Iterator>
0094 struct assign_to_attribute_from_iterators<
0095 boost::optional<Attribute>, Iterator>
0096 {
0097 static void
0098 call(Iterator const& first, Iterator const& last
0099 , boost::optional<Attribute>& attr)
0100 {
0101 Attribute val;
0102 assign_to(first, last, val);
0103 attr = val;
0104 }
0105 };
0106
0107 template <typename Iterator>
0108 struct assign_to_attribute_from_iterators<
0109 iterator_range<Iterator>, Iterator>
0110 {
0111 static void
0112 call(Iterator const& first, Iterator const& last
0113 , iterator_range<Iterator>& attr)
0114 {
0115 attr = iterator_range<Iterator>(first, last);
0116 }
0117 };
0118
0119 template <typename Iterator, typename Attribute>
0120 inline void
0121 assign_to(Iterator const& first, Iterator const& last, Attribute& attr)
0122 {
0123 assign_to_attribute_from_iterators<Attribute, Iterator>::
0124 call(first, last, attr);
0125 }
0126
0127 template <typename Iterator>
0128 inline void
0129 assign_to(Iterator const&, Iterator const&, unused_type)
0130 {
0131 }
0132
0133
0134 template <typename T, typename Attribute>
0135 void assign_to(T const& val, Attribute& attr);
0136
0137 template <typename Attribute, typename T, typename Enable>
0138 struct assign_to_attribute_from_value
0139 {
0140 typedef typename traits::one_element_sequence<Attribute>::type
0141 is_one_element_sequence;
0142
0143 typedef typename mpl::eval_if<
0144 is_one_element_sequence
0145 , fusion::result_of::at_c<Attribute, 0>
0146 , mpl::identity<Attribute&>
0147 >::type type;
0148
0149 template <typename T_>
0150 static void
0151 call(T_ const& val, Attribute& attr, mpl::false_)
0152 {
0153 attr = static_cast<Attribute>(val);
0154 }
0155
0156
0157
0158
0159 template <typename T_>
0160 static void
0161 call(T_ const& val, Attribute& attr, mpl::true_)
0162 {
0163 typedef typename fusion::result_of::value_at_c<Attribute, 0>::type
0164 element_type;
0165 fusion::at_c<0>(attr) = static_cast<element_type>(val);
0166 }
0167
0168 static void
0169 call(T const& val, Attribute& attr)
0170 {
0171 call(val, attr, is_one_element_sequence());
0172 }
0173 };
0174
0175 template <typename Attribute>
0176 struct assign_to_attribute_from_value<Attribute, Attribute>
0177 {
0178 static void
0179 call(Attribute const& val, Attribute& attr)
0180 {
0181 attr = val;
0182 }
0183 };
0184
0185 template <typename Attribute, typename T>
0186 struct assign_to_attribute_from_value<Attribute, reference_wrapper<T>
0187 , typename disable_if<is_same<Attribute, reference_wrapper<T> > >::type>
0188 {
0189 static void
0190 call(reference_wrapper<T> const& val, Attribute& attr)
0191 {
0192 assign_to(val.get(), attr);
0193 }
0194 };
0195
0196 template <typename Attribute, typename T>
0197 struct assign_to_attribute_from_value<Attribute, boost::optional<T>
0198 , typename disable_if<is_same<Attribute, boost::optional<T> > >::type>
0199 {
0200 static void
0201 call(boost::optional<T> const& val, Attribute& attr)
0202 {
0203 assign_to(val.get(), attr);
0204 }
0205 };
0206
0207 template <typename Attribute, int N, bool Const, typename T>
0208 struct assign_to_attribute_from_value<fusion::extension::adt_attribute_proxy<Attribute, N, Const>, T>
0209 {
0210 static void
0211 call(T const& val, typename fusion::extension::adt_attribute_proxy<Attribute, N, Const>& attr)
0212 {
0213 attr = val;
0214 }
0215 };
0216
0217 namespace detail
0218 {
0219 template <typename A, typename B>
0220 struct is_same_size_sequence
0221 : mpl::bool_<fusion::result_of::size<A>::value
0222 == fusion::result_of::size<B>::value>
0223 {};
0224 }
0225
0226 template <typename Attribute, typename T>
0227 struct assign_to_attribute_from_value<Attribute, T,
0228 mpl::and_<
0229 fusion::traits::is_sequence<Attribute>,
0230 fusion::traits::is_sequence<T>,
0231 detail::is_same_size_sequence<Attribute, T>
0232 >
0233 >
0234 {
0235 static void
0236 call(T const& val, Attribute& attr)
0237 {
0238 fusion::copy(val, attr);
0239 }
0240 };
0241
0242
0243 template <typename Attribute, typename T, typename Enable>
0244 struct assign_to_container_from_value
0245 {
0246
0247 template <typename T_>
0248 static void call(T_ const& val, Attribute& attr, mpl::false_, mpl::false_)
0249 {
0250 traits::push_back(attr, val);
0251 }
0252
0253
0254
0255 template <typename T_>
0256 static void
0257 append_to_container_not_string(T_ const& val, Attribute& attr, mpl::true_)
0258 {
0259 traits::push_back(attr, val);
0260 }
0261
0262
0263 template <typename T_>
0264 static void
0265 append_to_container_not_string(T_ const& val, Attribute& attr, mpl::false_)
0266 {
0267 typedef typename traits::container_iterator<T_ const>::type
0268 iterator_type;
0269
0270 iterator_type end = traits::end(val);
0271 for (iterator_type i = traits::begin(val); i != end; traits::next(i))
0272 traits::push_back(attr, traits::deref(i));
0273 }
0274
0275
0276 template <typename T_>
0277 static void call(T_ const& val, Attribute& attr, mpl::true_, mpl::false_)
0278 {
0279 typedef typename container_value<Attribute>::type value_type;
0280 typedef typename is_convertible<T, value_type>::type is_value_type;
0281
0282 append_to_container_not_string(val, attr, is_value_type());
0283 }
0284
0285
0286
0287 template <typename Iterator>
0288 static void append_to_string(Attribute& attr, Iterator begin, Iterator end)
0289 {
0290 for (Iterator i = begin; i != end; ++i)
0291 traits::push_back(attr, *i);
0292 }
0293
0294
0295 template <typename T_>
0296 static void append_to_container(T_ const& val, Attribute& attr, mpl::false_)
0297 {
0298 typedef typename char_type_of<T_>::type char_type;
0299
0300 append_to_string(attr, traits::get_begin<char_type>(val)
0301 , traits::get_end<char_type>(val));
0302 }
0303
0304
0305 template <typename T_>
0306 static void append_to_container(T_ const& val, Attribute& attr, mpl::true_)
0307 {
0308 traits::push_back(attr, val);
0309 }
0310
0311 template <typename T_, typename Pred>
0312 static void call(T_ const& val, Attribute& attr, Pred, mpl::true_)
0313 {
0314 typedef typename container_value<Attribute>::type value_type;
0315 typedef typename is_convertible<T, value_type>::type is_value_type;
0316
0317 append_to_container(val, attr, is_value_type());
0318 }
0319
0320
0321 static void call(T const& val, Attribute& attr)
0322 {
0323 typedef typename traits::is_container<T>::type is_container;
0324 typedef typename traits::is_string<T>::type is_string;
0325
0326 call(val, attr, is_container(), is_string());
0327 }
0328 };
0329
0330 template <typename Attribute>
0331 struct assign_to_container_from_value<Attribute, Attribute>
0332 {
0333 static void
0334 call(Attribute const& val, Attribute& attr)
0335 {
0336 attr = val;
0337 }
0338 };
0339
0340 template <typename Attribute, typename T>
0341 struct assign_to_container_from_value<Attribute, boost::optional<T>
0342 , typename disable_if<is_same<Attribute, boost::optional<T> > >::type>
0343 {
0344 static void
0345 call(boost::optional<T> const& val, Attribute& attr)
0346 {
0347 assign_to(val.get(), attr);
0348 }
0349 };
0350
0351 template <typename Attribute, typename T>
0352 struct assign_to_container_from_value<Attribute, reference_wrapper<T>
0353 , typename disable_if<is_same<Attribute, reference_wrapper<T> > >::type>
0354 {
0355 static void
0356 call(reference_wrapper<T> const& val, Attribute& attr)
0357 {
0358 assign_to(val.get(), attr);
0359 }
0360 };
0361
0362
0363 namespace detail
0364 {
0365
0366 template <typename T, typename Attribute>
0367 inline void
0368 assign_to(T const& val, Attribute& attr, mpl::false_)
0369 {
0370 assign_to_attribute_from_value<Attribute, T>::call(val, attr);
0371 }
0372
0373
0374
0375 template <typename T, typename Attribute>
0376 inline void
0377 assign_to(T const& val, Attribute& attr, mpl::true_)
0378 {
0379 assign_to_container_from_value<Attribute, T>::call(val, attr);
0380 }
0381 }
0382
0383 template <typename T, typename Attribute>
0384 inline void
0385 assign_to(T const& val, Attribute& attr)
0386 {
0387 typedef typename mpl::and_<
0388 traits::is_container<Attribute>
0389 , traits::not_is_variant<Attribute>
0390 , traits::not_is_optional<Attribute>
0391 >::type is_not_wrapped_container;
0392
0393 detail::assign_to(val, attr, is_not_wrapped_container());
0394 }
0395
0396 template <typename T>
0397 inline void
0398 assign_to(T const&, unused_type)
0399 {
0400 }
0401 }}}
0402
0403 #endif