// Copyright (c) 2001-2011 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(SPIRIT_KARMA_DUPLICATE_JUL_11_2010_0954AM) #define SPIRIT_KARMA_DUPLICATE_JUL_11_2010_0954AM #if defined(_MSC_VER) #pragma once #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace boost { namespace spirit { /////////////////////////////////////////////////////////////////////////// // Enablers /////////////////////////////////////////////////////////////////////////// template <> struct use_directive // enables duplicate : mpl::true_ {}; }} namespace boost { namespace spirit { namespace karma { #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS using spirit::duplicate; #endif using spirit::duplicate_type; /////////////////////////////////////////////////////////////////////////// namespace detail { /////////////////////////////////////////////////////////////////////// template ::value> struct attribute_count : fusion::result_of::size {}; template <> struct attribute_count : mpl::int_<0> {}; template struct attribute_count : mpl::int_<1> {}; /////////////////////////////////////////////////////////////////////// template ::value> struct first_attribute_of_subject : remove_reference::type> {}; template struct first_attribute_of_subject : mpl::identity {}; template struct first_attribute_of : first_attribute_of_subject< typename traits::attribute_of::type> {}; /////////////////////////////////////////////////////////////////////// template struct duplicate_sequence_attribute { typedef typename fusion::result_of::make_cons< reference_wrapper , typename duplicate_sequence_attribute::type >::type type; static type call(T const& t) { return fusion::make_cons(boost::cref(t) , duplicate_sequence_attribute::call(t)); } }; template struct duplicate_sequence_attribute { typedef typename fusion::result_of::make_cons< reference_wrapper >::type type; static type call(T const& t) { return fusion::make_cons(boost::cref(t)); } }; /////////////////////////////////////////////////////////////////////// template ::value , bool IsSequence = fusion::traits::is_sequence::value> struct duplicate_attribute { BOOST_SPIRIT_ASSERT_MSG(N > 0, invalid_duplication_count, (Attribute)); typedef typename duplicate_sequence_attribute::type cons_type; typedef typename fusion::result_of::as_vector::type type; static type call(T const& t) { return fusion::as_vector( duplicate_sequence_attribute::call(t)); } }; template struct duplicate_attribute { typedef unused_type type; static type call(T const&) { return unused; } }; template struct duplicate_attribute { typedef Attribute const& type; static type call(T const& t) { return t; } }; } template inline typename detail::duplicate_attribute::type duplicate_attribute(T const& t) { return detail::duplicate_attribute::call(t); } /////////////////////////////////////////////////////////////////////////// // duplicate_directive duplicate its attribute for all elements of the // subject generator without generating anything itself /////////////////////////////////////////////////////////////////////////// template struct duplicate_directive : unary_generator > { typedef Subject subject_type; typedef typename subject_type::properties properties; duplicate_directive(Subject const& subject) : subject(subject) {} template struct attribute : detail::first_attribute_of {}; template bool generate(OutputIterator& sink, Context& ctx, Delimiter const& d , Attribute const& attr) const { typedef typename traits::attribute_of::type subject_attr_type; return subject.generate(sink, ctx, d , duplicate_attribute(attr)); } template info what(Context& context) const { return info("duplicate", subject.what(context)); } Subject subject; }; /////////////////////////////////////////////////////////////////////////// // Generator generators: make_xxx function (objects) /////////////////////////////////////////////////////////////////////////// template struct make_directive { typedef duplicate_directive result_type; result_type operator()(unused_type, Subject const& subject , unused_type) const { return result_type(subject); } }; }}} namespace boost { namespace spirit { namespace traits { /////////////////////////////////////////////////////////////////////////// template struct has_semantic_action > : unary_has_semantic_action {}; /////////////////////////////////////////////////////////////////////////// template struct handles_container, Attribute , Context, Iterator> : unary_handles_container {}; }}} #endif