PageRenderTime 32ms CodeModel.GetById 11ms app.highlight 18ms RepoModel.GetById 1ms app.codeStats 0ms

/Src/Dependencies/Boost/boost/spirit/home/karma/detail/alternative_function.hpp

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