• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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