| // Copyright (c) 2001-2007 Joel de Guzman |
| // Copyright (c) 2001-2009 Hartmut Kaiser |
| // |
| // 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(BOOST_SPIRIT_KARMA_RULE_MAR_05_2007_0519PM) |
| #define BOOST_SPIRIT_KARMA_RULE_MAR_05_2007_0519PM |
| |
| #if defined(_MSC_VER) && (_MSC_VER >= 1020) |
| #pragma once // MS compatible compilers support #pragma once |
| #endif |
| |
| #include <boost/spirit/home/support/unused.hpp> |
| #include <boost/spirit/home/support/attribute_of.hpp> |
| #include <boost/spirit/home/karma/domain.hpp> |
| #include <boost/intrusive_ptr.hpp> |
| #include <boost/detail/atomic_count.hpp> |
| #include <boost/mpl/eval_if.hpp> |
| #include <boost/mpl/identity.hpp> |
| #include <boost/mpl/size.hpp> |
| #include <boost/mpl/bool.hpp> |
| #include <boost/mpl/not.hpp> |
| #include <boost/mpl/and.hpp> |
| #include <boost/mpl/equal_to.hpp> |
| #include <boost/type_traits/is_same.hpp> |
| #include <boost/type_traits/add_const.hpp> |
| #include <boost/type_traits/remove_reference.hpp> |
| #include <boost/function_types/is_function.hpp> |
| #include <boost/assert.hpp> |
| #include <boost/fusion/include/pop_front.hpp> |
| #include <boost/fusion/include/is_sequence.hpp> |
| |
| namespace boost { namespace spirit { namespace karma { namespace detail |
| { |
| struct no_delimiter |
| { |
| // this struct accepts only unused types and |
| // nothing else. This is used by the second |
| // pure virtual parse member function of |
| // virtual_component_base below. |
| |
| no_delimiter(unused_type) {} |
| }; |
| |
| template <typename OutputIterator, typename Context, typename Delimiter> |
| struct virtual_component_base |
| { |
| struct take_no_delimiter {}; |
| |
| typedef typename |
| mpl::eval_if< |
| is_same<Delimiter, unused_type>, |
| mpl::identity<take_no_delimiter>, |
| result_of::as_component<karma::domain, Delimiter> |
| >::type |
| delimiter_type; |
| |
| virtual_component_base() |
| : use_count(0) |
| { |
| } |
| |
| virtual ~virtual_component_base() |
| { |
| } |
| |
| virtual bool |
| generate(OutputIterator& sink, Context& context, |
| delimiter_type const& delim) = 0; |
| |
| virtual bool |
| generate(OutputIterator& sink, Context& context, no_delimiter) = 0; |
| |
| boost::detail::atomic_count use_count; |
| }; |
| |
| template <typename OutputIterator, typename Context, typename Delimiter> |
| inline void |
| intrusive_ptr_add_ref( |
| virtual_component_base<OutputIterator, Context, Delimiter>* p) |
| { |
| ++p->use_count; |
| } |
| |
| template <typename OutputIterator, typename Context, typename Delimiter> |
| inline void |
| intrusive_ptr_release( |
| virtual_component_base<OutputIterator, Context, Delimiter>* p) |
| { |
| if (--p->use_count == 0) |
| delete p; |
| } |
| |
| /////////////////////////////////////////////////////////////////////////// |
| template <typename OutputIterator, typename Component, typename Context, |
| typename Delimiter, typename Auto> |
| struct virtual_component |
| : virtual_component_base<OutputIterator, Context, Delimiter> |
| { |
| typedef |
| virtual_component_base<OutputIterator, Context, Delimiter> |
| base_type; |
| typedef typename base_type::delimiter_type delimiter_type; |
| typedef typename base_type::take_no_delimiter take_no_delimiter; |
| |
| virtual_component(Component const& component) |
| : component(component) |
| { |
| } |
| |
| virtual ~virtual_component() |
| { |
| } |
| |
| template <typename Delimiter_> |
| bool generate_main(OutputIterator& sink, Context& context, |
| Delimiter_ const& delim, mpl::false_) |
| { |
| // If Auto is false, we synthesize a new (default constructed) |
| // attribute instance based on the attributes of the embedded |
| // generator. |
| typename traits::attribute_of< |
| karma::domain, Component, Context |
| >::type param; |
| |
| typedef typename Component::director director; |
| return director::generate(component, sink, context, delim, param); |
| } |
| |
| template <typename Delimiter_> |
| bool generate_main(OutputIterator& sink, Context& context, |
| Delimiter_ const& delim, mpl::true_) |
| { |
| // If Auto is true, we pass the rule's attribute on to the |
| // component. |
| typedef typename Component::director director; |
| return director::generate(component, sink, context, delim, |
| fusion::at_c<0>(fusion::at_c<0>(context))); |
| } |
| |
| bool |
| generate_main(OutputIterator&, Context&, take_no_delimiter, mpl::false_) |
| { |
| BOOST_ASSERT(false); // this should never be called |
| return false; |
| } |
| |
| bool |
| generate_main(OutputIterator&, Context&, take_no_delimiter, mpl::true_) |
| { |
| BOOST_ASSERT(false); // this should never be called |
| return false; |
| } |
| |
| virtual bool |
| generate(OutputIterator& sink, Context& context, |
| delimiter_type const& delim) |
| { |
| return generate_main(sink, context, delim, Auto()); |
| } |
| |
| virtual bool |
| generate(OutputIterator& sink, Context& context, no_delimiter) |
| { |
| return generate_main(sink, context, unused, Auto()); |
| } |
| |
| Component component; |
| }; |
| |
| }}}} |
| |
| #endif |