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