Mercurial > hg > vamp-build-and-test
comparison DEPENDENCIES/generic/include/boost/spirit/home/karma/stream/stream.hpp @ 16:2665513ce2d3
Add boost headers
author | Chris Cannam |
---|---|
date | Tue, 05 Aug 2014 11:11:38 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
15:663ca0da4350 | 16:2665513ce2d3 |
---|---|
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_STREAM_MAY_01_2007_0310PM) | |
7 #define BOOST_SPIRIT_KARMA_STREAM_MAY_01_2007_0310PM | |
8 | |
9 #if defined(_MSC_VER) | |
10 #pragma once | |
11 #endif | |
12 | |
13 #include <boost/spirit/home/support/common_terminals.hpp> | |
14 #include <boost/spirit/home/support/info.hpp> | |
15 #include <boost/spirit/home/support/container.hpp> | |
16 #include <boost/spirit/home/support/detail/hold_any.hpp> | |
17 #include <boost/spirit/home/support/detail/get_encoding.hpp> | |
18 #include <boost/spirit/home/support/detail/is_spirit_tag.hpp> | |
19 #include <boost/spirit/home/karma/domain.hpp> | |
20 #include <boost/spirit/home/karma/meta_compiler.hpp> | |
21 #include <boost/spirit/home/karma/delimit_out.hpp> | |
22 #include <boost/spirit/home/karma/auxiliary/lazy.hpp> | |
23 #include <boost/spirit/home/karma/stream/detail/format_manip.hpp> | |
24 #include <boost/spirit/home/karma/stream/detail/iterator_sink.hpp> | |
25 #include <boost/spirit/home/karma/detail/get_casetag.hpp> | |
26 #include <boost/spirit/home/karma/detail/extract_from.hpp> | |
27 #include <boost/fusion/include/at.hpp> | |
28 #include <boost/fusion/include/vector.hpp> | |
29 #include <boost/fusion/include/cons.hpp> | |
30 #include <boost/utility/enable_if.hpp> | |
31 #include <boost/type_traits/is_same.hpp> | |
32 | |
33 #include <iosfwd> | |
34 | |
35 /////////////////////////////////////////////////////////////////////////////// | |
36 namespace boost { namespace spirit | |
37 { | |
38 namespace tag | |
39 { | |
40 template <typename Char = char> | |
41 struct stream_tag | |
42 { | |
43 BOOST_SPIRIT_IS_TAG() | |
44 }; | |
45 } | |
46 | |
47 namespace karma | |
48 { | |
49 /////////////////////////////////////////////////////////////////////// | |
50 // This one is the class that the user can instantiate directly in | |
51 // order to create a customized int generator | |
52 template <typename Char = char> | |
53 struct stream_generator | |
54 : spirit::terminal<tag::stream_tag<Char> > | |
55 {}; | |
56 } | |
57 | |
58 /////////////////////////////////////////////////////////////////////////// | |
59 // Enablers | |
60 /////////////////////////////////////////////////////////////////////////// | |
61 template <> | |
62 struct use_terminal<karma::domain, tag::stream> // enables stream | |
63 : mpl::true_ {}; | |
64 | |
65 template <> | |
66 struct use_terminal<karma::domain, tag::wstream> // enables wstream | |
67 : mpl::true_ {}; | |
68 | |
69 template <typename A0> | |
70 struct use_terminal<karma::domain // enables stream(...) | |
71 , terminal_ex<tag::stream, fusion::vector1<A0> > | |
72 > : mpl::true_ {}; | |
73 | |
74 template <typename A0> | |
75 struct use_terminal<karma::domain // enables wstream(...) | |
76 , terminal_ex<tag::wstream, fusion::vector1<A0> > | |
77 > : mpl::true_ {}; | |
78 | |
79 template <> // enables stream(f) | |
80 struct use_lazy_terminal< | |
81 karma::domain, tag::stream, 1 /*arity*/ | |
82 > : mpl::true_ {}; | |
83 | |
84 template <> // enables wstream(f) | |
85 struct use_lazy_terminal< | |
86 karma::domain, tag::wstream, 1 /*arity*/ | |
87 > : mpl::true_ {}; | |
88 | |
89 // enables stream_generator<char_type> | |
90 template <typename Char> | |
91 struct use_terminal<karma::domain, tag::stream_tag<Char> > | |
92 : mpl::true_ {}; | |
93 | |
94 template <typename Char, typename A0> | |
95 struct use_terminal<karma::domain | |
96 , terminal_ex<tag::stream_tag<Char>, fusion::vector1<A0> > | |
97 > : mpl::true_ {}; | |
98 | |
99 template <typename Char> | |
100 struct use_lazy_terminal< | |
101 karma::domain, tag::stream_tag<Char>, 1 /*arity*/ | |
102 > : mpl::true_ {}; | |
103 | |
104 }} | |
105 | |
106 /////////////////////////////////////////////////////////////////////////////// | |
107 namespace boost { namespace spirit { namespace karma | |
108 { | |
109 #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS | |
110 using spirit::stream; | |
111 using spirit::wstream; | |
112 #endif | |
113 using spirit::stream_type; | |
114 using spirit::wstream_type; | |
115 | |
116 /////////////////////////////////////////////////////////////////////////// | |
117 template <typename Char, typename CharEncoding, typename Tag> | |
118 struct any_stream_generator | |
119 : primitive_generator<any_stream_generator<Char, CharEncoding, Tag> > | |
120 { | |
121 template <typename Context, typename Unused = unused_type> | |
122 struct attribute | |
123 { | |
124 typedef spirit::basic_hold_any<Char> type; | |
125 }; | |
126 | |
127 // any_stream_generator has an attached attribute | |
128 template < | |
129 typename OutputIterator, typename Context, typename Delimiter | |
130 , typename Attribute | |
131 > | |
132 static bool generate(OutputIterator& sink, Context& context | |
133 , Delimiter const& d, Attribute const& attr) | |
134 { | |
135 typedef karma::detail::iterator_sink< | |
136 OutputIterator, Char, CharEncoding, Tag | |
137 > sink_device; | |
138 | |
139 if (!traits::has_optional_value(attr)) | |
140 return false; | |
141 | |
142 // use existing operator<<() | |
143 typedef typename attribute<Context>::type attribute_type; | |
144 | |
145 { | |
146 boost::iostreams::stream<sink_device> ostr(sink); | |
147 ostr << traits::extract_from<attribute_type>(attr, context) << std::flush; | |
148 | |
149 if (!ostr.good()) | |
150 return false; | |
151 } | |
152 | |
153 return karma::delimit_out(sink, d); // always do post-delimiting | |
154 } | |
155 | |
156 // this is a special overload to detect if the output iterator has been | |
157 // generated by a format_manip object. | |
158 template < | |
159 typename T, typename Traits, typename Properties, typename Context | |
160 , typename Delimiter, typename Attribute | |
161 > | |
162 static bool generate( | |
163 karma::detail::output_iterator< | |
164 karma::ostream_iterator<T, Char, Traits>, Properties | |
165 >& sink, Context& context, Delimiter const& d | |
166 , Attribute const& attr) | |
167 { | |
168 typedef karma::detail::output_iterator< | |
169 karma::ostream_iterator<T, Char, Traits>, Properties | |
170 > output_iterator; | |
171 typedef karma::detail::iterator_sink< | |
172 output_iterator, Char, CharEncoding, Tag | |
173 > sink_device; | |
174 | |
175 if (!traits::has_optional_value(attr)) | |
176 return false; | |
177 | |
178 // use existing operator<<() | |
179 typedef typename attribute<Context>::type attribute_type; | |
180 | |
181 { | |
182 boost::iostreams::stream<sink_device> ostr(sink); | |
183 ostr.imbue(sink.get_ostream().getloc()); | |
184 ostr << traits::extract_from<attribute_type>(attr, context) | |
185 << std::flush; | |
186 if (!ostr.good()) | |
187 return false; | |
188 } | |
189 | |
190 return karma::delimit_out(sink, d); // always do post-delimiting | |
191 } | |
192 | |
193 // this any_stream has no parameter attached, it needs to have been | |
194 // initialized from a value/variable | |
195 template <typename OutputIterator, typename Context | |
196 , typename Delimiter> | |
197 static bool | |
198 generate(OutputIterator&, Context&, Delimiter const&, unused_type) | |
199 { | |
200 // It is not possible (doesn't make sense) to use stream generators | |
201 // without providing any attribute, as the generator doesn't 'know' | |
202 // what to output. The following assertion fires if this situation | |
203 // is detected in your code. | |
204 BOOST_SPIRIT_ASSERT_FAIL(OutputIterator, stream_not_usable_without_attribute, ()); | |
205 return false; | |
206 } | |
207 | |
208 template <typename Context> | |
209 info what(Context& /*context*/) const | |
210 { | |
211 return info("stream"); | |
212 } | |
213 }; | |
214 | |
215 template <typename T, typename Char, typename CharEncoding, typename Tag> | |
216 struct lit_stream_generator | |
217 : primitive_generator<lit_stream_generator<T, Char, CharEncoding, Tag> > | |
218 { | |
219 template <typename Context, typename Unused> | |
220 struct attribute | |
221 { | |
222 typedef unused_type type; | |
223 }; | |
224 | |
225 lit_stream_generator(typename add_reference<T>::type t) | |
226 : t_(t) | |
227 {} | |
228 | |
229 // lit_stream_generator has an attached parameter | |
230 | |
231 // this overload will be used in the normal case (not called from | |
232 // format_manip). | |
233 template < | |
234 typename OutputIterator, typename Context, typename Delimiter | |
235 , typename Attribute> | |
236 bool generate(OutputIterator& sink, Context&, Delimiter const& d | |
237 , Attribute const&) const | |
238 { | |
239 typedef karma::detail::iterator_sink< | |
240 OutputIterator, Char, CharEncoding, Tag | |
241 > sink_device; | |
242 | |
243 boost::iostreams::stream<sink_device> ostr(sink); | |
244 ostr << t_ << std::flush; // use existing operator<<() | |
245 | |
246 if (ostr.good()) | |
247 return karma::delimit_out(sink, d); // always do post-delimiting | |
248 return false; | |
249 } | |
250 | |
251 // this is a special overload to detect if the output iterator has been | |
252 // generated by a format_manip object. | |
253 template < | |
254 typename T1, typename Traits, typename Properties | |
255 , typename Context, typename Delimiter, typename Attribute> | |
256 bool generate( | |
257 karma::detail::output_iterator< | |
258 karma::ostream_iterator<T1, Char, Traits>, Properties | |
259 >& sink, Context&, Delimiter const& d, Attribute const&) const | |
260 { | |
261 typedef karma::detail::output_iterator< | |
262 karma::ostream_iterator<T1, Char, Traits>, Properties | |
263 > output_iterator; | |
264 typedef karma::detail::iterator_sink< | |
265 output_iterator, Char, CharEncoding, Tag | |
266 > sink_device; | |
267 | |
268 { | |
269 boost::iostreams::stream<sink_device> ostr(sink); | |
270 ostr.imbue(sink.get_ostream().getloc()); | |
271 ostr << t_ << std::flush; // use existing operator<<() | |
272 | |
273 if (!ostr.good()) | |
274 return false; | |
275 } | |
276 | |
277 return karma::delimit_out(sink, d); // always do post-delimiting | |
278 } | |
279 | |
280 template <typename Context> | |
281 info what(Context& /*context*/) const | |
282 { | |
283 return info("any-stream"); | |
284 } | |
285 | |
286 T t_; | |
287 | |
288 private: | |
289 // silence MSVC warning C4512: assignment operator could not be generated | |
290 lit_stream_generator& operator= (lit_stream_generator const&); | |
291 }; | |
292 | |
293 /////////////////////////////////////////////////////////////////////////// | |
294 // Generator generators: make_xxx function (objects) | |
295 /////////////////////////////////////////////////////////////////////////// | |
296 template <typename Char, typename Modifiers> | |
297 struct make_stream | |
298 { | |
299 static bool const lower = | |
300 has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value; | |
301 | |
302 static bool const upper = | |
303 has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value; | |
304 | |
305 typedef any_stream_generator< | |
306 Char | |
307 , typename spirit::detail::get_encoding_with_case< | |
308 Modifiers, unused_type, lower || upper>::type | |
309 , typename detail::get_casetag<Modifiers, lower || upper>::type | |
310 > result_type; | |
311 | |
312 result_type operator()(unused_type, unused_type) const | |
313 { | |
314 return result_type(); | |
315 } | |
316 }; | |
317 | |
318 // stream | |
319 template <typename Modifiers> | |
320 struct make_primitive<tag::stream, Modifiers> | |
321 : make_stream<char, Modifiers> {}; | |
322 | |
323 // wstream | |
324 template <typename Modifiers> | |
325 struct make_primitive<tag::wstream, Modifiers> | |
326 : make_stream<wchar_t, Modifiers> {}; | |
327 | |
328 // any_stream_generator<char_type> | |
329 template <typename Char, typename Modifiers> | |
330 struct make_primitive<tag::stream_tag<Char>, Modifiers> | |
331 : make_stream<Char, Modifiers> {}; | |
332 | |
333 /////////////////////////////////////////////////////////////////////////// | |
334 template <typename Char, typename A0, typename Modifiers> | |
335 struct make_any_stream | |
336 { | |
337 static bool const lower = | |
338 has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value; | |
339 | |
340 static bool const upper = | |
341 has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value; | |
342 | |
343 typedef typename add_const<A0>::type const_attribute; | |
344 typedef lit_stream_generator< | |
345 const_attribute, Char | |
346 , typename spirit::detail::get_encoding_with_case< | |
347 Modifiers, unused_type, lower || upper>::type | |
348 , typename detail::get_casetag<Modifiers, lower || upper>::type | |
349 > result_type; | |
350 | |
351 template <typename Terminal> | |
352 result_type operator()(Terminal const& term, unused_type) const | |
353 { | |
354 return result_type(fusion::at_c<0>(term.args)); | |
355 } | |
356 }; | |
357 | |
358 // stream(...) | |
359 template <typename Modifiers, typename A0> | |
360 struct make_primitive< | |
361 terminal_ex<tag::stream, fusion::vector1<A0> >, Modifiers> | |
362 : make_any_stream<char, A0, Modifiers> {}; | |
363 | |
364 // wstream(...) | |
365 template <typename Modifiers, typename A0> | |
366 struct make_primitive< | |
367 terminal_ex<tag::wstream, fusion::vector1<A0> >, Modifiers> | |
368 : make_any_stream<wchar_t, A0, Modifiers> {}; | |
369 | |
370 // any_stream_generator<char_type>(...) | |
371 template <typename Char, typename Modifiers, typename A0> | |
372 struct make_primitive< | |
373 terminal_ex<tag::stream_tag<Char>, fusion::vector1<A0> > | |
374 , Modifiers> | |
375 : make_any_stream<Char, A0, Modifiers> {}; | |
376 | |
377 }}} | |
378 | |
379 #endif |