annotate DEPENDENCIES/generic/include/boost/spirit/home/karma/detail/alternative_function.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents 2665513ce2d3
children
rev   line source
Chris@16 1 // Copyright (c) 2001-2011 Hartmut Kaiser
Chris@16 2 // Copyright (c) 2001-2011 Joel de Guzman
Chris@16 3 //
Chris@16 4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
Chris@16 5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Chris@16 6
Chris@16 7 #if !defined(SPIRIT_KARMA_ALTERNATIVE_MAR_01_2007_1124AM)
Chris@16 8 #define SPIRIT_KARMA_ALTERNATIVE_MAR_01_2007_1124AM
Chris@16 9
Chris@16 10 #if defined(_MSC_VER)
Chris@16 11 #pragma once
Chris@16 12 #endif
Chris@16 13
Chris@16 14 #include <boost/spirit/home/karma/domain.hpp>
Chris@16 15 #include <boost/spirit/home/karma/directive/buffer.hpp>
Chris@16 16 #include <boost/spirit/home/support/unused.hpp>
Chris@16 17 #include <boost/spirit/home/support/utree/utree_traits_fwd.hpp>
Chris@16 18 #include <boost/spirit/home/karma/detail/attributes.hpp>
Chris@16 19 #include <boost/spirit/home/support/detail/hold_any.hpp>
Chris@16 20 #include <boost/spirit/home/karma/detail/output_iterator.hpp>
Chris@16 21 #include <boost/spirit/home/support/container.hpp>
Chris@16 22 #include <boost/utility/enable_if.hpp>
Chris@16 23 #include <boost/variant.hpp>
Chris@16 24 #include <boost/detail/workaround.hpp>
Chris@16 25
Chris@16 26 ///////////////////////////////////////////////////////////////////////////////
Chris@16 27 namespace boost { namespace spirit { namespace karma { namespace detail
Chris@16 28 {
Chris@16 29 ///////////////////////////////////////////////////////////////////////////
Chris@16 30 // execute a generator if the given Attribute type is compatible
Chris@16 31 ///////////////////////////////////////////////////////////////////////////
Chris@16 32
Chris@16 33 // this gets instantiated if the Attribute type is _not_ compatible with
Chris@16 34 // the generator
Chris@16 35 template <typename Component, typename Attribute, typename Expected
Chris@16 36 , typename Enable = void>
Chris@16 37 struct alternative_generate
Chris@16 38 {
Chris@16 39 template <typename OutputIterator, typename Context, typename Delimiter>
Chris@16 40 static bool
Chris@16 41 call(Component const&, OutputIterator&, Context&, Delimiter const&
Chris@16 42 , Attribute const&, bool& failed)
Chris@16 43 {
Chris@16 44 failed = true;
Chris@16 45 return false;
Chris@16 46 }
Chris@16 47 };
Chris@16 48
Chris@16 49 template <typename Component>
Chris@16 50 struct alternative_generate<Component, unused_type, unused_type>
Chris@16 51 {
Chris@16 52 template <typename OutputIterator, typename Context, typename Delimiter>
Chris@16 53 static bool
Chris@16 54 call(Component const& component, OutputIterator& sink, Context& ctx
Chris@16 55 , Delimiter const& d, unused_type, bool&)
Chris@16 56 {
Chris@16 57 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
Chris@16 58 component; // suppresses warning: C4100: 'component' : unreferenced formal parameter
Chris@16 59 #endif
Chris@16 60 // return true if any of the generators succeed
Chris@16 61 return component.generate(sink, ctx, d, unused);
Chris@16 62 }
Chris@16 63 };
Chris@16 64
Chris@16 65 // this gets instantiated if there is no Attribute given for the
Chris@16 66 // alternative generator
Chris@16 67 template <typename Component, typename Expected>
Chris@16 68 struct alternative_generate<Component, unused_type, Expected>
Chris@16 69 : alternative_generate<Component, unused_type, unused_type> {};
Chris@16 70
Chris@16 71 // this gets instantiated if the generator does not expect to receive an
Chris@16 72 // Attribute (the generator is self contained).
Chris@16 73 template <typename Component, typename Attribute>
Chris@16 74 struct alternative_generate<Component, Attribute, unused_type>
Chris@16 75 : alternative_generate<Component, unused_type, unused_type> {};
Chris@16 76
Chris@16 77 // this gets instantiated if the Attribute type is compatible to the
Chris@16 78 // generator
Chris@16 79 template <typename Component, typename Attribute, typename Expected>
Chris@16 80 struct alternative_generate<Component, Attribute, Expected
Chris@16 81 , typename enable_if<
Chris@16 82 traits::compute_compatible_component<Expected, Attribute, karma::domain> >::type>
Chris@16 83 {
Chris@16 84 template <typename OutputIterator, typename Context, typename Delimiter>
Chris@16 85 static bool
Chris@16 86 call(Component const& component, OutputIterator& sink
Chris@16 87 , Context& ctx, Delimiter const& d, Attribute const& attr, bool&)
Chris@16 88 {
Chris@16 89 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
Chris@16 90 component; // suppresses warning: C4100: 'component' : unreferenced formal parameter
Chris@16 91 #endif
Chris@16 92 return call(component, sink, ctx, d, attr
Chris@16 93 , spirit::traits::not_is_variant<Attribute, karma::domain>());
Chris@16 94 }
Chris@16 95
Chris@16 96 template <typename OutputIterator, typename Context, typename Delimiter>
Chris@16 97 static bool
Chris@16 98 call(Component const& component, OutputIterator& sink
Chris@16 99 , Context& ctx, Delimiter const& d, Attribute const& attr, mpl::true_)
Chris@16 100 {
Chris@16 101 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
Chris@16 102 component; // suppresses warning: C4100: 'component' : unreferenced formal parameter
Chris@16 103 #endif
Chris@16 104 return component.generate(sink, ctx, d, attr);
Chris@16 105 }
Chris@16 106
Chris@16 107 template <typename OutputIterator, typename Context, typename Delimiter>
Chris@16 108 static bool
Chris@16 109 call(Component const& component, OutputIterator& sink
Chris@16 110 , Context& ctx, Delimiter const& d, Attribute const& attr, mpl::false_)
Chris@16 111 {
Chris@16 112 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
Chris@16 113 component; // suppresses warning: C4100: 'component' : unreferenced formal parameter
Chris@16 114 #endif
Chris@16 115 typedef
Chris@16 116 traits::compute_compatible_component<Expected, Attribute, domain>
Chris@16 117 component_type;
Chris@16 118
Chris@16 119 // if we got passed an empty optional, just fail generation
Chris@16 120 if (!traits::has_optional_value(attr))
Chris@16 121 return false;
Chris@16 122
Chris@16 123 // make sure, the content of the passed variant matches our
Chris@16 124 // expectations
Chris@16 125 typename traits::optional_attribute<Attribute>::type attr_ =
Chris@16 126 traits::optional_value(attr);
Chris@16 127 if (!component_type::is_compatible(spirit::traits::which(attr_)))
Chris@16 128 return false;
Chris@16 129
Chris@16 130 // returns true if any of the generators succeed
Chris@16 131 typedef typename component_type::compatible_type compatible_type;
Chris@16 132 return component.generate(sink, ctx, d
Chris@16 133 , boost::get<compatible_type>(attr_));
Chris@16 134 }
Chris@16 135 };
Chris@16 136
Chris@16 137 ///////////////////////////////////////////////////////////////////////////
Chris@16 138 // alternative_generate_function: a functor supplied to fusion::any which
Chris@16 139 // will be executed for every generator in a given alternative generator
Chris@16 140 // expression
Chris@16 141 ///////////////////////////////////////////////////////////////////////////
Chris@16 142 template <typename OutputIterator, typename Context, typename Delimiter,
Chris@16 143 typename Attribute, typename Strict>
Chris@16 144 struct alternative_generate_function
Chris@16 145 {
Chris@16 146 alternative_generate_function(OutputIterator& sink_, Context& ctx_
Chris@16 147 , Delimiter const& d, Attribute const& attr_)
Chris@16 148 : sink(sink_), ctx(ctx_), delim(d), attr(attr_) {}
Chris@16 149
Chris@16 150 template <typename Component>
Chris@16 151 bool operator()(Component const& component)
Chris@16 152 {
Chris@16 153 typedef
Chris@16 154 typename traits::attribute_of<Component, Context>::type
Chris@16 155 expected_type;
Chris@16 156 typedef
Chris@16 157 alternative_generate<Component, Attribute, expected_type>
Chris@16 158 generate;
Chris@16 159
Chris@16 160 // wrap the given output iterator avoid output as long as one
Chris@16 161 // component fails
Chris@16 162 detail::enable_buffering<OutputIterator> buffering(sink);
Chris@16 163 bool r = false;
Chris@16 164 bool failed = false; // will be ignored
Chris@16 165 {
Chris@16 166 detail::disable_counting<OutputIterator> nocounting(sink);
Chris@16 167 r = generate::call(component, sink, ctx, delim, attr, failed);
Chris@16 168 }
Chris@16 169 if (r)
Chris@16 170 buffering.buffer_copy();
Chris@16 171 return r;
Chris@16 172 }
Chris@16 173
Chris@16 174 // avoid double buffering
Chris@16 175 template <typename Component>
Chris@16 176 bool operator()(buffer_directive<Component> const& component)
Chris@16 177 {
Chris@16 178 typedef typename
Chris@16 179 traits::attribute_of<Component, Context>::type
Chris@16 180 expected_type;
Chris@16 181 typedef alternative_generate<
Chris@16 182 buffer_directive<Component>, Attribute, expected_type>
Chris@16 183 generate;
Chris@16 184
Chris@16 185 bool failed = false; // will be ignored
Chris@16 186 return generate::call(component, sink, ctx, delim, attr, failed);
Chris@16 187 }
Chris@16 188
Chris@16 189 OutputIterator& sink;
Chris@16 190 Context& ctx;
Chris@16 191 Delimiter const& delim;
Chris@16 192 Attribute const& attr;
Chris@16 193
Chris@16 194 private:
Chris@16 195 // silence MSVC warning C4512: assignment operator could not be generated
Chris@16 196 alternative_generate_function& operator= (alternative_generate_function const&);
Chris@16 197 };
Chris@16 198
Chris@16 199 // specialization for strict alternatives
Chris@16 200 template <typename OutputIterator, typename Context, typename Delimiter,
Chris@16 201 typename Attribute>
Chris@16 202 struct alternative_generate_function<
Chris@16 203 OutputIterator, Context, Delimiter, Attribute, mpl::true_>
Chris@16 204 {
Chris@16 205 alternative_generate_function(OutputIterator& sink_, Context& ctx_
Chris@16 206 , Delimiter const& d, Attribute const& attr_)
Chris@16 207 : sink(sink_), ctx(ctx_), delim(d), attr(attr_), failed(false) {}
Chris@16 208
Chris@16 209 template <typename Component>
Chris@16 210 bool operator()(Component const& component)
Chris@16 211 {
Chris@16 212 typedef
Chris@16 213 typename traits::attribute_of<Component, Context>::type
Chris@16 214 expected_type;
Chris@16 215 typedef
Chris@16 216 alternative_generate<Component, Attribute, expected_type>
Chris@16 217 generate;
Chris@16 218
Chris@16 219 if (failed)
Chris@16 220 return false; // give up when already failed
Chris@16 221
Chris@16 222 // wrap the given output iterator avoid output as long as one
Chris@16 223 // component fails
Chris@16 224 detail::enable_buffering<OutputIterator> buffering(sink);
Chris@16 225 bool r = false;
Chris@16 226 {
Chris@16 227 detail::disable_counting<OutputIterator> nocounting(sink);
Chris@16 228 r = generate::call(component, sink, ctx, delim, attr, failed);
Chris@16 229 }
Chris@16 230 if (r && !failed)
Chris@16 231 {
Chris@16 232 buffering.buffer_copy();
Chris@16 233 return true;
Chris@16 234 }
Chris@16 235 return false;
Chris@16 236 }
Chris@16 237
Chris@16 238 OutputIterator& sink;
Chris@16 239 Context& ctx;
Chris@16 240 Delimiter const& delim;
Chris@16 241 Attribute const& attr;
Chris@16 242 bool failed;
Chris@16 243
Chris@16 244 private:
Chris@16 245 // silence MSVC warning C4512: assignment operator could not be generated
Chris@16 246 alternative_generate_function& operator= (alternative_generate_function const&);
Chris@16 247 };
Chris@16 248 }}}}
Chris@16 249
Chris@16 250 #endif