]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/spirit/include/boost/spirit/home/karma/stream/stream.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / spirit / include / boost / spirit / home / karma / stream / stream.hpp
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