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 #if !defined(BOOST_SPIRIT_KARMA_MAXWIDTH_MAR_18_2009_0827AM) 7 #define BOOST_SPIRIT_KARMA_MAXWIDTH_MAR_18_2009_0827AM 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/karma/detail/default_width.hpp> 18 #include <boost/spirit/home/karma/delimit_out.hpp> 19 #include <boost/spirit/home/karma/auxiliary/lazy.hpp> 20 #include <boost/spirit/home/support/unused.hpp> 21 #include <boost/spirit/home/support/common_terminals.hpp> 22 #include <boost/spirit/home/support/has_semantic_action.hpp> 23 #include <boost/spirit/home/support/handles_container.hpp> 24 #include <boost/spirit/home/karma/detail/attributes.hpp> 25 #include <boost/spirit/home/support/info.hpp> 26 #include <boost/spirit/home/support/unused.hpp> 27 #include <boost/fusion/include/at.hpp> 28 #include <boost/fusion/include/vector.hpp> 29 #include <boost/detail/workaround.hpp> 30 31 /////////////////////////////////////////////////////////////////////////////// 32 namespace boost { namespace spirit 33 { 34 /////////////////////////////////////////////////////////////////////////// 35 // Enablers 36 /////////////////////////////////////////////////////////////////////////// 37 38 // enables maxwidth[] 39 template <> 40 struct use_directive<karma::domain, tag::maxwidth> 41 : mpl::true_ {}; 42 43 // enables maxwidth(w)[g], where w provides a maxwidth 44 template <typename T> 45 struct use_directive<karma::domain 46 , terminal_ex<tag::maxwidth, fusion::vector1<T> > > 47 : mpl::true_ {}; 48 49 // enables *lazy* maxwidth(w)[g], where w provides a maxwidth 50 template <> 51 struct use_lazy_directive<karma::domain, tag::maxwidth, 1> 52 : mpl::true_ {}; 53 54 // enables maxwidth(w, r)[g], where w provides a maxwidth and r is an output 55 // iterator used to receive the rest of the output not fitting into the 56 // maxwidth limit 57 template <typename T, typename RestIter> 58 struct use_directive<karma::domain 59 , terminal_ex<tag::maxwidth, fusion::vector2<T, RestIter> > > 60 : mpl::true_ {}; 61 62 // enables *lazy* maxwidth(w, r)[g], where w provides a maxwidth and r is 63 // an output iterator used to receive the rest of the output not fitting 64 // into the maxwidth limit 65 template <> 66 struct use_lazy_directive<karma::domain, tag::maxwidth, 2> 67 : mpl::true_ {}; 68 69 }} 70 71 /////////////////////////////////////////////////////////////////////////////// 72 namespace boost { namespace spirit { namespace karma 73 { 74 #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS 75 using spirit::maxwidth; 76 #endif 77 using spirit::maxwidth_type; 78 79 namespace detail 80 { 81 /////////////////////////////////////////////////////////////////////// 82 template <typename OutputIterator, typename RestIterator> buffer_copy_rest(detail::enable_buffering<OutputIterator> & buff,std::size_t start_at,RestIterator & dest)83 bool buffer_copy_rest(detail::enable_buffering<OutputIterator>& buff 84 , std::size_t start_at, RestIterator& dest) 85 { 86 return buff.buffer_copy_rest(dest, start_at); 87 } 88 89 template <typename OutputIterator> buffer_copy_rest(detail::enable_buffering<OutputIterator> &,std::size_t,unused_type)90 bool buffer_copy_rest(detail::enable_buffering<OutputIterator>& 91 , std::size_t, unused_type) 92 { 93 return true; 94 } 95 96 /////////////////////////////////////////////////////////////////////// 97 // The maxwidth_generate template function is used for all the 98 // different flavors of the maxwidth[] directive. 99 /////////////////////////////////////////////////////////////////////// 100 template <typename OutputIterator, typename Context, typename Delimiter, 101 typename Attribute, typename Embedded, typename Rest> 102 inline static bool maxwidth_generate(OutputIterator & sink,Context & ctx,Delimiter const & d,Attribute const & attr,Embedded const & e,unsigned int const maxwidth,Rest & restdest)103 maxwidth_generate(OutputIterator& sink, Context& ctx, 104 Delimiter const& d, Attribute const& attr, Embedded const& e, 105 unsigned int const maxwidth, Rest& restdest) 106 { 107 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600)) 108 e; // suppresses warning: C4100: 'e' : unreferenced formal parameter 109 #endif 110 // wrap the given output iterator to allow buffering, but disable 111 // counting 112 detail::enable_buffering<OutputIterator> buffering(sink); 113 114 // generate the underlying output and copy the embedded 115 // output to the target output iterator applying the given 116 // maxwidth 117 bool r = false; 118 { 119 detail::disable_counting<OutputIterator> nocounting(sink); 120 r = e.generate(sink, ctx, d, attr); 121 } // re-enable counting 122 123 return r && buffering.buffer_copy(maxwidth) && 124 buffer_copy_rest(buffering, maxwidth, restdest); 125 } 126 } 127 128 /////////////////////////////////////////////////////////////////////////// 129 // The maxwidth directive is used for maxwidth[...] 130 // generators. It uses default values for the generated width (defined via 131 // the BOOST_KARMA_DEFAULT_FIELD_MAXWIDTH constant). 132 // 133 // The maxwidth with width directive, is used for generators 134 // like maxwidth(width)[...]. 135 /////////////////////////////////////////////////////////////////////////// 136 template <typename Subject, typename Width = detail::default_max_width 137 , typename Rest = unused_type> 138 struct maxwidth_width 139 : unary_generator<maxwidth_width<Subject, Width, Rest> > 140 { 141 typedef Subject subject_type; 142 143 typedef mpl::int_< 144 generator_properties::countingbuffer | subject_type::properties::value 145 > properties; 146 147 template <typename Context, typename Iterator> 148 struct attribute 149 : traits::attribute_of<subject_type, Context, Iterator> 150 {}; 151 maxwidth_widthboost::spirit::karma::maxwidth_width152 maxwidth_width(Subject const& subject, Width const& w = Width() 153 , Rest const& r = Rest()) 154 : subject(subject), width(w), rest(r) {} 155 156 template <typename OutputIterator, typename Context, typename Delimiter 157 , typename Attribute> generateboost::spirit::karma::maxwidth_width158 bool generate(OutputIterator& sink, Context& ctx, Delimiter const& d 159 , Attribute const& attr) const 160 { 161 return detail::maxwidth_generate(sink, ctx, d, attr, subject 162 , width, rest); 163 } 164 165 template <typename Context> whatboost::spirit::karma::maxwidth_width166 info what(Context& context) const 167 { 168 return info("maxwidth", subject.what(context)); 169 } 170 171 Subject subject; 172 Width width; 173 Rest rest; 174 }; 175 176 /////////////////////////////////////////////////////////////////////////// 177 // Generator generators: make_xxx function (objects) 178 /////////////////////////////////////////////////////////////////////////// 179 180 // creates maxwidth[] directive generator 181 template <typename Subject, typename Modifiers> 182 struct make_directive<tag::maxwidth, Subject, Modifiers> 183 { 184 typedef maxwidth_width<Subject> result_type; operator ()boost::spirit::karma::make_directive185 result_type operator()(unused_type, Subject const& subject 186 , unused_type) const 187 { 188 return result_type(subject); 189 } 190 }; 191 192 // creates maxwidth(width)[] directive generator 193 template <typename T, typename Subject, typename Modifiers> 194 struct make_directive< 195 terminal_ex<tag::maxwidth, fusion::vector1<T> > 196 , Subject, Modifiers> 197 { 198 typedef maxwidth_width<Subject, T> result_type; 199 200 template <typename Terminal> operator ()boost::spirit::karma::make_directive201 result_type operator()(Terminal const& term, Subject const& subject 202 , unused_type) const 203 { 204 return result_type(subject, fusion::at_c<0>(term.args), unused); 205 } 206 }; 207 208 // creates maxwidth(width, restiter)[] directive generator 209 template < 210 typename T, typename RestIter, typename Subject, typename Modifiers> 211 struct make_directive< 212 terminal_ex<tag::maxwidth, fusion::vector2<T, RestIter> > 213 , Subject, Modifiers> 214 { 215 typedef maxwidth_width<Subject, T, RestIter> result_type; 216 217 template <typename Terminal> operator ()boost::spirit::karma::make_directive218 result_type operator()(Terminal const& term, Subject const& subject 219 , unused_type) const 220 { 221 return result_type(subject, fusion::at_c<0>(term.args) 222 , fusion::at_c<1>(term.args)); 223 } 224 }; 225 226 }}} // namespace boost::spirit::karma 227 228 namespace boost { namespace spirit { namespace traits 229 { 230 /////////////////////////////////////////////////////////////////////////// 231 template <typename Subject, typename Width, typename Rest> 232 struct has_semantic_action<karma::maxwidth_width<Subject, Width, Rest> > 233 : unary_has_semantic_action<Subject> {}; 234 235 /////////////////////////////////////////////////////////////////////////// 236 template <typename Subject, typename Attribute, typename Context 237 , typename Iterator> 238 struct handles_container<karma::maxwidth_width<Subject>, Attribute 239 , Context, Iterator> 240 : unary_handles_container<Subject, Attribute, Context, Iterator> {}; 241 }}} 242 243 #endif 244 245 246