// Copyright (c) 2001-2011 Hartmut Kaiser // Copyright (c) 2001-2011 Joel de Guzman // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #if !defined(SPIRIT_KARMA_ALTERNATIVE_MAR_01_2007_1124AM) #define SPIRIT_KARMA_ALTERNATIVE_MAR_01_2007_1124AM #if defined(_MSC_VER) #pragma once #endif #include #include #include #include #include #include #include #include #include #include #include /////////////////////////////////////////////////////////////////////////////// namespace boost { namespace spirit { namespace karma { namespace detail { /////////////////////////////////////////////////////////////////////////// // execute a generator if the given Attribute type is compatible /////////////////////////////////////////////////////////////////////////// // this gets instantiated if the Attribute type is _not_ compatible with // the generator template struct alternative_generate { template static bool call(Component const&, OutputIterator&, Context&, Delimiter const& , Attribute const&, bool& failed) { failed = true; return false; } }; template struct alternative_generate { template static bool call(Component const& component, OutputIterator& sink, Context& ctx , Delimiter const& d, unused_type, bool&) { #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600)) component; // suppresses warning: C4100: 'component' : unreferenced formal parameter #endif // return true if any of the generators succeed return component.generate(sink, ctx, d, unused); } }; // this gets instantiated if there is no Attribute given for the // alternative generator template struct alternative_generate : alternative_generate {}; // this gets instantiated if the generator does not expect to receive an // Attribute (the generator is self contained). template struct alternative_generate : alternative_generate {}; // this gets instantiated if the Attribute type is compatible to the // generator template struct alternative_generate >::type> { template static bool call(Component const& component, OutputIterator& sink , Context& ctx, Delimiter const& d, Attribute const& attr, bool&) { #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600)) component; // suppresses warning: C4100: 'component' : unreferenced formal parameter #endif return call(component, sink, ctx, d, attr , spirit::traits::not_is_variant()); } template static bool call(Component const& component, OutputIterator& sink , Context& ctx, Delimiter const& d, Attribute const& attr, mpl::true_) { #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600)) component; // suppresses warning: C4100: 'component' : unreferenced formal parameter #endif return component.generate(sink, ctx, d, attr); } template static bool call(Component const& component, OutputIterator& sink , Context& ctx, Delimiter const& d, Attribute const& attr, mpl::false_) { #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600)) component; // suppresses warning: C4100: 'component' : unreferenced formal parameter #endif typedef traits::compute_compatible_component component_type; // if we got passed an empty optional, just fail generation if (!traits::has_optional_value(attr)) return false; // make sure, the content of the passed variant matches our // expectations typename traits::optional_attribute::type attr_ = traits::optional_value(attr); if (!component_type::is_compatible(spirit::traits::which(attr_))) return false; // returns true if any of the generators succeed typedef typename component_type::compatible_type compatible_type; return component.generate(sink, ctx, d , boost::get(attr_)); } }; /////////////////////////////////////////////////////////////////////////// // alternative_generate_function: a functor supplied to fusion::any which // will be executed for every generator in a given alternative generator // expression /////////////////////////////////////////////////////////////////////////// template struct alternative_generate_function { alternative_generate_function(OutputIterator& sink_, Context& ctx_ , Delimiter const& d, Attribute const& attr_) : sink(sink_), ctx(ctx_), delim(d), attr(attr_) {} template bool operator()(Component const& component) { typedef typename traits::attribute_of::type expected_type; typedef alternative_generate generate; // wrap the given output iterator avoid output as long as one // component fails detail::enable_buffering buffering(sink); bool r = false; bool failed = false; // will be ignored { detail::disable_counting nocounting(sink); r = generate::call(component, sink, ctx, delim, attr, failed); } if (r) buffering.buffer_copy(); return r; } // avoid double buffering template bool operator()(buffer_directive const& component) { typedef typename traits::attribute_of::type expected_type; typedef alternative_generate< buffer_directive, Attribute, expected_type> generate; bool failed = false; // will be ignored return generate::call(component, sink, ctx, delim, attr, failed); } OutputIterator& sink; Context& ctx; Delimiter const& delim; Attribute const& attr; private: // silence MSVC warning C4512: assignment operator could not be generated alternative_generate_function& operator= (alternative_generate_function const&); }; // specialization for strict alternatives template struct alternative_generate_function< OutputIterator, Context, Delimiter, Attribute, mpl::true_> { alternative_generate_function(OutputIterator& sink_, Context& ctx_ , Delimiter const& d, Attribute const& attr_) : sink(sink_), ctx(ctx_), delim(d), attr(attr_), failed(false) {} template bool operator()(Component const& component) { typedef typename traits::attribute_of::type expected_type; typedef alternative_generate generate; if (failed) return false; // give up when already failed // wrap the given output iterator avoid output as long as one // component fails detail::enable_buffering buffering(sink); bool r = false; { detail::disable_counting nocounting(sink); r = generate::call(component, sink, ctx, delim, attr, failed); } if (r && !failed) { buffering.buffer_copy(); return true; } return false; } OutputIterator& sink; Context& ctx; Delimiter const& delim; Attribute const& attr; bool failed; private: // silence MSVC warning C4512: assignment operator could not be generated alternative_generate_function& operator= (alternative_generate_function const&); }; }}}} #endif