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