File indexing completed on 2025-01-19 09:47:36
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_SPIRIT_KARMA_DETAIL_PASS_CONTAINER_HPP
0009 #define BOOST_SPIRIT_KARMA_DETAIL_PASS_CONTAINER_HPP
0010
0011 #if defined(_MSC_VER)
0012 #pragma once
0013 #endif
0014
0015 #include <boost/spirit/home/karma/detail/attributes.hpp>
0016 #include <boost/spirit/home/support/container.hpp>
0017 #include <boost/spirit/home/support/handles_container.hpp>
0018 #include <boost/spirit/home/support/detail/hold_any.hpp>
0019 #include <boost/type_traits/is_base_of.hpp>
0020 #include <boost/type_traits/is_convertible.hpp>
0021 #include <boost/mpl/bool.hpp>
0022 #include <boost/mpl/and.hpp>
0023 #include <boost/mpl/or.hpp>
0024 #include <boost/preprocessor/cat.hpp>
0025 #include <boost/preprocessor/repetition/repeat.hpp>
0026 #include <boost/range/iterator_range_core.hpp>
0027 #include <boost/fusion/include/deduce_sequence.hpp>
0028
0029 namespace boost { namespace spirit { namespace karma { namespace detail
0030 {
0031
0032
0033 template <typename Sequence, typename Attribute, typename ValueType>
0034 struct negate_weak_substitute_if_not
0035 : mpl::if_<
0036 Sequence
0037 , typename traits::is_weak_substitute<Attribute, ValueType>::type
0038 , typename mpl::not_<
0039 traits::is_weak_substitute<Attribute, ValueType>
0040 >::type>
0041 {};
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051 template <typename Container, typename ValueType, typename Attribute
0052 , typename Sequence, typename Enable = void>
0053 struct pass_through_container_base
0054 : negate_weak_substitute_if_not<Sequence, ValueType, Attribute>
0055 {};
0056
0057
0058
0059
0060
0061
0062
0063 template <typename Container, typename ValueType, typename Attribute
0064 , typename Sequence = mpl::true_>
0065 struct not_compatible_element
0066 : mpl::and_<
0067 negate_weak_substitute_if_not<Sequence, Container, Attribute>
0068 , negate_weak_substitute_if_not<Sequence, ValueType, Attribute> >
0069 {};
0070
0071
0072
0073
0074 template <typename Container, typename ValueType, typename Attribute
0075 , typename Sequence
0076 , bool IsSequence = fusion::traits::is_sequence<ValueType>::value>
0077 struct pass_through_container_fusion_sequence
0078 {
0079 typedef typename mpl::find_if<
0080 Attribute, not_compatible_element<Container, ValueType, mpl::_1>
0081 >::type iter;
0082 typedef typename mpl::end<Attribute>::type end;
0083
0084 typedef typename is_same<iter, end>::type type;
0085 };
0086
0087
0088
0089
0090 template <typename Container, typename ValueType, typename Attribute
0091 , typename Sequence>
0092 struct pass_through_container_fusion_sequence<
0093 Container, ValueType, Attribute, Sequence, true>
0094 {
0095 typedef typename mpl::find_if<
0096 Attribute
0097 , not_compatible_element<Container, ValueType, mpl::_1, Sequence>
0098 >::type iter;
0099 typedef typename mpl::end<Attribute>::type end;
0100
0101 typedef typename is_same<iter, end>::type type;
0102 };
0103
0104 template <typename Container, typename ValueType, typename Attribute
0105 , typename Sequence>
0106 struct pass_through_container_base<Container, ValueType, Attribute
0107 , Sequence
0108 , typename enable_if<fusion::traits::is_sequence<Attribute> >::type>
0109 : pass_through_container_fusion_sequence<
0110 Container, ValueType, Attribute, Sequence>
0111 {};
0112
0113
0114
0115
0116
0117
0118 template <typename Container, typename ValueType, typename Attribute
0119 , typename Sequence, typename AttributeValueType
0120 , bool IsSequence = fusion::traits::is_sequence<AttributeValueType>::value>
0121 struct pass_through_container_container
0122 : mpl::or_<
0123 traits::is_weak_substitute<Container, Attribute>
0124 , traits::is_weak_substitute<Container, AttributeValueType> >
0125 {};
0126
0127
0128
0129 template <typename Container, typename ValueType, typename Attribute
0130 , typename Sequence, typename AttributeValueType>
0131 struct pass_through_container_container<
0132 Container, ValueType, Attribute, Sequence, AttributeValueType, true>
0133 : pass_through_container_fusion_sequence<
0134 Container, ValueType, AttributeValueType, Sequence>
0135 {};
0136
0137 template <typename Container, typename ValueType, typename Attribute
0138 , typename Sequence>
0139 struct pass_through_container_base<Container, ValueType, Attribute
0140 , Sequence
0141 , typename enable_if<traits::is_container<Attribute> >::type>
0142 : detail::pass_through_container_container<
0143 Container, ValueType, Attribute, Sequence
0144 , typename traits::container_value<Attribute>::type>
0145 {};
0146
0147
0148
0149
0150
0151
0152
0153 template <typename Container, typename ValueType, typename Attribute
0154 , typename Sequence
0155 , bool IsSequence = fusion::traits::is_sequence<Attribute>::value>
0156 struct pass_through_container_optional
0157 : mpl::or_<
0158 traits::is_weak_substitute<Container, Attribute>
0159 , traits::is_weak_substitute<ValueType, Attribute> >
0160 {};
0161
0162
0163
0164 template <typename Container, typename ValueType, typename Attribute
0165 , typename Sequence>
0166 struct pass_through_container_optional<
0167 Container, ValueType, Attribute, Sequence, true>
0168 : pass_through_container_fusion_sequence<
0169 Container, ValueType, Attribute, Sequence>
0170 {};
0171
0172
0173 template <typename Container, typename ValueType, typename Attribute
0174 , typename Sequence>
0175 struct pass_through_container
0176 : pass_through_container_base<Container, ValueType, Attribute, Sequence>
0177 {};
0178
0179
0180 template <typename Container, typename ValueType, typename Attribute
0181 , typename Sequence>
0182 struct pass_through_container<
0183 Container, ValueType, boost::optional<Attribute>, Sequence>
0184 : pass_through_container_optional<
0185 Container, ValueType, Attribute, Sequence>
0186 {};
0187
0188
0189
0190
0191 template <typename Container, typename ValueType, typename Attribute
0192 , typename Sequence>
0193 struct pass_through_container<
0194 Container, boost::optional<ValueType>, boost::optional<Attribute>
0195 , Sequence>
0196 : mpl::not_<traits::is_weak_substitute<ValueType, Attribute> >
0197 {};
0198
0199
0200
0201
0202
0203
0204 #if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES)
0205 template <typename Container, typename ValueType, typename Sequence
0206 , typename T>
0207 struct pass_through_container<Container, ValueType, boost::variant<T>
0208 , Sequence>
0209 : pass_through_container<Container, ValueType, T, Sequence>
0210 {};
0211
0212 template <typename Container, typename ValueType, typename Sequence
0213 , typename T0, typename ...TN>
0214 struct pass_through_container<Container, ValueType
0215 , boost::variant<T0, TN...>, Sequence>
0216 : mpl::bool_<pass_through_container<
0217 Container, ValueType, T0, Sequence
0218 >::type::value || pass_through_container<
0219 Container, ValueType, boost::variant<TN...>, Sequence
0220 >::type::value>
0221 {};
0222 #else
0223 #define BOOST_SPIRIT_PASS_THROUGH_CONTAINER(z, N, _) \
0224 pass_through_container<Container, ValueType, \
0225 BOOST_PP_CAT(T, N), Sequence>::type::value || \
0226
0227
0228
0229 template <typename Container, typename ValueType, typename Sequence>
0230 struct pass_through_container<Container, ValueType
0231 , boost::detail::variant::void_, Sequence>
0232 : mpl::false_
0233 {};
0234
0235 template <typename Container, typename ValueType, typename Sequence
0236 , BOOST_VARIANT_ENUM_PARAMS(typename T)>
0237 struct pass_through_container<Container, ValueType
0238 , boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Sequence>
0239 : mpl::bool_<BOOST_PP_REPEAT(BOOST_VARIANT_LIMIT_TYPES
0240 , BOOST_SPIRIT_PASS_THROUGH_CONTAINER, _) false>
0241 {};
0242
0243 #undef BOOST_SPIRIT_PASS_THROUGH_CONTAINER
0244 #endif
0245 }}}}
0246
0247
0248 namespace boost { namespace spirit { namespace traits
0249 {
0250
0251
0252 template <typename Container, typename ValueType, typename Attribute
0253 , typename Sequence>
0254 struct pass_through_container<
0255 Container, ValueType, Attribute, Sequence, karma::domain>
0256 : karma::detail::pass_through_container<
0257 Container, ValueType, Attribute, Sequence>
0258 {};
0259 }}}
0260
0261 namespace boost { namespace spirit { namespace karma { namespace detail
0262 {
0263 template <typename Iterator>
0264 struct pass_container_base
0265 {
0266 pass_container_base(Iterator begin, Iterator end)
0267 : iter(begin), end(end)
0268 {}
0269
0270 mutable Iterator iter;
0271 mutable Iterator end;
0272 };
0273
0274 #ifdef _MSC_VER
0275 # pragma warning(push)
0276 # pragma warning(disable: 4512)
0277 #endif
0278 template <typename Iterator>
0279 struct pass_container_base<Iterator&>
0280 {
0281 pass_container_base(Iterator& begin, Iterator& end)
0282 : iter(begin), end(end)
0283 {}
0284
0285 Iterator& iter;
0286 Iterator& end;
0287 };
0288
0289
0290
0291
0292
0293 template <typename F, typename Attr, typename Iterator, typename Sequence>
0294 struct pass_container : pass_container_base<Iterator>
0295 {
0296 typedef pass_container_base<Iterator> base_type;
0297 typedef typename F::context_type context_type;
0298
0299 pass_container(F const& f, Iterator begin, Iterator end)
0300 : base_type(begin, end)
0301 , f(f)
0302 {}
0303
0304 bool is_at_end() const
0305 {
0306 return traits::compare(this->iter, this->end);
0307 }
0308
0309 void next()
0310 {
0311 traits::next(this->iter);
0312 }
0313
0314
0315
0316 template <typename Component>
0317 bool dispatch_container(Component const& component, mpl::false_) const
0318 {
0319
0320 if (!is_at_end() && !f(component, traits::deref(this->iter)))
0321 {
0322
0323 traits::next(this->iter);
0324 return false;
0325 }
0326
0327
0328 return true;
0329 }
0330
0331
0332
0333
0334 template <typename Component>
0335 bool dispatch_container(Component const& component, mpl::true_) const
0336 {
0337 return f(component, make_iterator_range(this->iter, this->end));
0338 }
0339
0340
0341
0342
0343 template <typename Component>
0344 bool dispatch_attribute(Component const& component, mpl::false_) const
0345 {
0346 return f(component, unused);
0347 }
0348
0349
0350 template <typename Component>
0351 bool dispatch_attribute(Component const& component, mpl::true_) const
0352 {
0353 typedef typename traits::container_value<Attr>::type value_type;
0354 typedef typename
0355 traits::attribute_of<Component, context_type>::type
0356 lhs_attribute;
0357
0358
0359
0360
0361 typedef mpl::and_<
0362 traits::handles_container<Component, Attr, context_type>
0363 , traits::pass_through_container<
0364 Attr, value_type, lhs_attribute, Sequence, karma::domain>
0365 > predicate;
0366
0367 return dispatch_container(component, predicate());
0368 }
0369
0370
0371
0372 template <typename Component>
0373 bool operator()(Component const& component) const
0374 {
0375
0376
0377
0378
0379 typedef traits::not_is_unused<
0380 typename traits::attribute_of<Component, context_type>::type
0381 > predicate;
0382
0383 return dispatch_attribute(component, predicate());
0384 }
0385
0386 F f;
0387 };
0388 #ifdef _MSC_VER
0389 # pragma warning(pop)
0390 #endif
0391 }}}}
0392
0393 #endif