Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-19 09:47:35

0001 //  Copyright (c) 2001-2011 Hartmut Kaiser
0002 //  Copyright (c) 2001-2011 Joel de Guzman
0003 //
0004 //  Distributed under the Boost Software License, Version 1.0. (See accompanying
0005 //  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
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     //  execute a generator if the given Attribute type is compatible
0031     ///////////////////////////////////////////////////////////////////////////
0032 
0033     //  this gets instantiated if the Attribute type is _not_ compatible with
0034     //  the generator
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; // suppresses warning: C4100: 'component' : unreferenced formal parameter
0059 #endif
0060             // return true if any of the generators succeed
0061             return component.generate(sink, ctx, d, unused);
0062         }
0063     };
0064 
0065     //  this gets instantiated if there is no Attribute given for the
0066     //  alternative generator
0067     template <typename Component, typename Expected>
0068     struct alternative_generate<Component, unused_type, Expected>
0069       : alternative_generate<Component, unused_type, unused_type> {};
0070 
0071     //  this gets instantiated if the generator does not expect to receive an
0072     //  Attribute (the generator is self contained).
0073     template <typename Component, typename Attribute>
0074     struct alternative_generate<Component, Attribute, unused_type>
0075       : alternative_generate<Component, unused_type, unused_type> {};
0076 
0077     //  this gets instantiated if the Attribute type is compatible to the
0078     //  generator
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; // suppresses warning: C4100: 'component' : unreferenced formal parameter
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; // suppresses warning: C4100: 'component' : unreferenced formal parameter
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; // suppresses warning: C4100: 'component' : unreferenced formal parameter
0114 #endif
0115             typedef
0116                 traits::compute_compatible_component<Expected, Attribute, domain>
0117             component_type;
0118 
0119             // if we got passed an empty optional, just fail generation
0120             if (!traits::has_optional_value(attr))
0121                 return false;
0122 
0123             // make sure, the content of the passed variant matches our
0124             // expectations
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             // returns true if any of the generators succeed
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     //  alternative_generate_function: a functor supplied to fusion::any which
0139     //  will be executed for every generator in a given alternative generator
0140     //  expression
0141     ///////////////////////////////////////////////////////////////////////////
0142 #ifdef _MSC_VER
0143 #  pragma warning(push)
0144 #  pragma warning(disable: 4512) // assignment operator could not be generated.
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             // wrap the given output iterator avoid output as long as one
0165             // component fails
0166             detail::enable_buffering<OutputIterator> buffering(sink);
0167             bool r = false;
0168             bool failed = false;    // will be ignored
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         // avoid double buffering
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;    // will be ignored
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     // specialization for strict alternatives
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;     // give up when already failed
0221 
0222             // wrap the given output iterator avoid output as long as one
0223             // component fails
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