1 // Copyright (c) 2001-2011 Hartmut Kaiser 2 // 3 // Distributed under the Boost Software License, Version 1.0. (See accompanying 4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 6 #ifndef BOOST_SPIRIT_KARMA_DIRECTIVE_BUFFER_HPP 7 #define BOOST_SPIRIT_KARMA_DIRECTIVE_BUFFER_HPP 8 9 #if defined(_MSC_VER) 10 #pragma once 11 #endif 12 13 #include <boost/spirit/home/karma/meta_compiler.hpp> 14 #include <boost/spirit/home/karma/generator.hpp> 15 #include <boost/spirit/home/karma/domain.hpp> 16 #include <boost/spirit/home/karma/detail/output_iterator.hpp> 17 #include <boost/spirit/home/support/unused.hpp> 18 #include <boost/spirit/home/support/info.hpp> 19 #include <boost/spirit/home/support/common_terminals.hpp> 20 #include <boost/spirit/home/support/has_semantic_action.hpp> 21 #include <boost/spirit/home/support/handles_container.hpp> 22 #include <boost/spirit/home/karma/detail/attributes.hpp> 23 24 namespace boost { namespace spirit 25 { 26 /////////////////////////////////////////////////////////////////////////// 27 // Enablers 28 /////////////////////////////////////////////////////////////////////////// 29 template <> 30 struct use_directive<karma::domain, tag::buffer> // enables buffer 31 : mpl::true_ {}; 32 33 }} 34 35 namespace boost { namespace spirit { namespace karma 36 { 37 #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS 38 using spirit::buffer; 39 #endif 40 using spirit::buffer_type; 41 42 /////////////////////////////////////////////////////////////////////////// 43 // buffer_directive buffers all generated output of the embedded generator 44 // and flushes it only if the whole embedded generator succeeds 45 /////////////////////////////////////////////////////////////////////////// 46 template <typename Subject> 47 struct buffer_directive : unary_generator<buffer_directive<Subject> > 48 { 49 typedef Subject subject_type; 50 typedef mpl::int_< 51 subject_type::properties::value | 52 generator_properties::countingbuffer 53 > properties; 54 buffer_directiveboost::spirit::karma::buffer_directive55 buffer_directive(Subject const& subject) 56 : subject(subject) {} 57 58 template <typename Context, typename Iterator> 59 struct attribute 60 : traits::attribute_of<subject_type, Context, Iterator> 61 {}; 62 63 template <typename OutputIterator, typename Context, typename Delimiter 64 , typename Attribute> generateboost::spirit::karma::buffer_directive65 bool generate(OutputIterator& sink, Context& ctx, Delimiter const& d 66 , Attribute const& attr) const 67 { 68 // wrap the given output iterator to avoid output as long as the 69 // embedded generator (subject) fails 70 detail::enable_buffering<OutputIterator> buffering(sink); 71 bool r = false; 72 { 73 detail::disable_counting<OutputIterator> nocounting(sink); 74 r = subject.generate(sink, ctx, d, attr); 75 } 76 if (r) 77 buffering.buffer_copy(); 78 return r; 79 } 80 81 template <typename Context> whatboost::spirit::karma::buffer_directive82 info what(Context& context) const 83 { 84 return info("buffer", subject.what(context)); 85 } 86 87 Subject subject; 88 }; 89 90 /////////////////////////////////////////////////////////////////////////// 91 // Generator generators: make_xxx function (objects) 92 /////////////////////////////////////////////////////////////////////////// 93 template <typename Subject, typename Modifiers> 94 struct make_directive<tag::buffer, Subject, Modifiers> 95 { 96 typedef buffer_directive<Subject> result_type; operator ()boost::spirit::karma::make_directive97 result_type operator()(unused_type, Subject const& subject 98 , unused_type) const 99 { 100 return result_type(subject); 101 } 102 }; 103 104 // make sure buffer[buffer[...]] does not result in double buffering 105 template <typename Subject, typename Modifiers> 106 struct make_directive<tag::buffer, buffer_directive<Subject>, Modifiers> 107 { 108 typedef buffer_directive<Subject> result_type; operator ()boost::spirit::karma::make_directive109 result_type operator()(unused_type 110 , buffer_directive<Subject> const& subject, unused_type) const 111 { 112 return subject; 113 } 114 }; 115 }}} 116 117 namespace boost { namespace spirit { namespace traits 118 { 119 /////////////////////////////////////////////////////////////////////////// 120 template <typename Subject> 121 struct has_semantic_action<karma::buffer_directive<Subject> > 122 : unary_has_semantic_action<Subject> {}; 123 124 /////////////////////////////////////////////////////////////////////////// 125 template <typename Subject, typename Attribute, typename Context 126 , typename Iterator> 127 struct handles_container<karma::buffer_directive<Subject>, Attribute 128 , Context, Iterator> 129 : unary_handles_container<Subject, Attribute, Context, Iterator> {}; 130 }}} 131 132 #endif 133