File indexing completed on 2025-01-19 09:47:35
0001
0002
0003
0004
0005
0006
0007 #ifndef BOOST_SPIRIT_KARMA_DETAIL_ALTERNATIVE_FUNCTION_HPP
0008 #define BOOST_SPIRIT_KARMA_DETAIL_ALTERNATIVE_FUNCTION_HPP
0009
0010 #if defined(_MSC_VER)
0011 #pragma once
0012 #endif
0013
0014 #include <boost/spirit/home/karma/domain.hpp>
0015 #include <boost/spirit/home/karma/directive/buffer.hpp>
0016 #include <boost/spirit/home/support/unused.hpp>
0017 #include <boost/spirit/home/support/utree/utree_traits_fwd.hpp>
0018 #include <boost/spirit/home/karma/detail/attributes.hpp>
0019 #include <boost/spirit/home/support/detail/hold_any.hpp>
0020 #include <boost/spirit/home/karma/detail/output_iterator.hpp>
0021 #include <boost/spirit/home/support/container.hpp>
0022 #include <boost/utility/enable_if.hpp>
0023 #include <boost/variant.hpp>
0024 #include <boost/detail/workaround.hpp>
0025
0026
0027 namespace boost { namespace spirit { namespace karma { namespace detail
0028 {
0029
0030
0031
0032
0033
0034
0035 template <typename Component, typename Attribute, typename Expected
0036 , typename Enable = void>
0037 struct alternative_generate
0038 {
0039 template <typename OutputIterator, typename Context, typename Delimiter>
0040 static bool
0041 call(Component const&, OutputIterator&, Context&, Delimiter const&
0042 , Attribute const&, bool& failed)
0043 {
0044 failed = true;
0045 return false;
0046 }
0047 };
0048
0049 template <typename Component>
0050 struct alternative_generate<Component, unused_type, unused_type>
0051 {
0052 template <typename OutputIterator, typename Context, typename Delimiter>
0053 static bool
0054 call(Component const& component, OutputIterator& sink, Context& ctx
0055 , Delimiter const& d, unused_type, bool&)
0056 {
0057 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
0058 (void)component;
0059 #endif
0060
0061 return component.generate(sink, ctx, d, unused);
0062 }
0063 };
0064
0065
0066
0067 template <typename Component, typename Expected>
0068 struct alternative_generate<Component, unused_type, Expected>
0069 : alternative_generate<Component, unused_type, unused_type> {};
0070
0071
0072
0073 template <typename Component, typename Attribute>
0074 struct alternative_generate<Component, Attribute, unused_type>
0075 : alternative_generate<Component, unused_type, unused_type> {};
0076
0077
0078
0079 template <typename Component, typename Attribute, typename Expected>
0080 struct alternative_generate<Component, Attribute, Expected
0081 , typename enable_if<
0082 traits::compute_compatible_component<Expected, Attribute, karma::domain> >::type>
0083 {
0084 template <typename OutputIterator, typename Context, typename Delimiter>
0085 static bool
0086 call(Component const& component, OutputIterator& sink
0087 , Context& ctx, Delimiter const& d, Attribute const& attr, bool&)
0088 {
0089 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
0090 (void)component;
0091 #endif
0092 return call(component, sink, ctx, d, attr
0093 , spirit::traits::not_is_variant_or_variant_in_optional<Attribute, karma::domain>());
0094 }
0095
0096 template <typename OutputIterator, typename Context, typename Delimiter>
0097 static bool
0098 call(Component const& component, OutputIterator& sink
0099 , Context& ctx, Delimiter const& d, Attribute const& attr, mpl::true_)
0100 {
0101 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
0102 (void)component;
0103 #endif
0104 return component.generate(sink, ctx, d, attr);
0105 }
0106
0107 template <typename OutputIterator, typename Context, typename Delimiter>
0108 static bool
0109 call(Component const& component, OutputIterator& sink
0110 , Context& ctx, Delimiter const& d, Attribute const& attr, mpl::false_)
0111 {
0112 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
0113 (void)component;
0114 #endif
0115 typedef
0116 traits::compute_compatible_component<Expected, Attribute, domain>
0117 component_type;
0118
0119
0120 if (!traits::has_optional_value(attr))
0121 return false;
0122
0123
0124
0125 typename traits::optional_attribute<Attribute>::type attr_ =
0126 traits::optional_value(attr);
0127 if (!component_type::is_compatible(spirit::traits::which(attr_)))
0128 return false;
0129
0130
0131 typedef typename component_type::compatible_type compatible_type;
0132 return component.generate(sink, ctx, d
0133 , boost::get<compatible_type>(attr_));
0134 }
0135 };
0136
0137
0138
0139
0140
0141
0142 #ifdef _MSC_VER
0143 # pragma warning(push)
0144 # pragma warning(disable: 4512)
0145 #endif
0146 template <typename OutputIterator, typename Context, typename Delimiter,
0147 typename Attribute, typename Strict>
0148 struct alternative_generate_function
0149 {
0150 alternative_generate_function(OutputIterator& sink_, Context& ctx_
0151 , Delimiter const& d, Attribute const& attr_)
0152 : sink(sink_), ctx(ctx_), delim(d), attr(attr_) {}
0153
0154 template <typename Component>
0155 bool operator()(Component const& component)
0156 {
0157 typedef
0158 typename traits::attribute_of<Component, Context>::type
0159 expected_type;
0160 typedef
0161 alternative_generate<Component, Attribute, expected_type>
0162 generate;
0163
0164
0165
0166 detail::enable_buffering<OutputIterator> buffering(sink);
0167 bool r = false;
0168 bool failed = false;
0169 {
0170 detail::disable_counting<OutputIterator> nocounting(sink);
0171 r = generate::call(component, sink, ctx, delim, attr, failed);
0172 }
0173 if (r)
0174 buffering.buffer_copy();
0175 return r;
0176 }
0177
0178
0179 template <typename Component>
0180 bool operator()(buffer_directive<Component> const& component)
0181 {
0182 typedef typename
0183 traits::attribute_of<Component, Context>::type
0184 expected_type;
0185 typedef alternative_generate<
0186 buffer_directive<Component>, Attribute, expected_type>
0187 generate;
0188
0189 bool failed = false;
0190 return generate::call(component, sink, ctx, delim, attr, failed);
0191 }
0192
0193 OutputIterator& sink;
0194 Context& ctx;
0195 Delimiter const& delim;
0196 Attribute const& attr;
0197 };
0198
0199
0200 template <typename OutputIterator, typename Context, typename Delimiter,
0201 typename Attribute>
0202 struct alternative_generate_function<
0203 OutputIterator, Context, Delimiter, Attribute, mpl::true_>
0204 {
0205 alternative_generate_function(OutputIterator& sink_, Context& ctx_
0206 , Delimiter const& d, Attribute const& attr_)
0207 : sink(sink_), ctx(ctx_), delim(d), attr(attr_), failed(false) {}
0208
0209 template <typename Component>
0210 bool operator()(Component const& component)
0211 {
0212 typedef
0213 typename traits::attribute_of<Component, Context>::type
0214 expected_type;
0215 typedef
0216 alternative_generate<Component, Attribute, expected_type>
0217 generate;
0218
0219 if (failed)
0220 return false;
0221
0222
0223
0224 detail::enable_buffering<OutputIterator> buffering(sink);
0225 bool r = false;
0226 {
0227 detail::disable_counting<OutputIterator> nocounting(sink);
0228 r = generate::call(component, sink, ctx, delim, attr, failed);
0229 }
0230 if (r && !failed)
0231 {
0232 buffering.buffer_copy();
0233 return true;
0234 }
0235 return false;
0236 }
0237
0238 OutputIterator& sink;
0239 Context& ctx;
0240 Delimiter const& delim;
0241 Attribute const& attr;
0242 bool failed;
0243 };
0244 #ifdef _MSC_VER
0245 # pragma warning(pop)
0246 #endif
0247 }}}}
0248
0249 #endif