]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/spirit/home/karma/char/char.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / spirit / home / karma / char / char.hpp
1 // Copyright (c) 2001-2011 Hartmut Kaiser
2 // Copyright (c) 2010 Bryce Lelbach
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6
7 #if !defined(BOOST_SPIRIT_KARMA_CHAR_FEB_21_2007_0543PM)
8 #define BOOST_SPIRIT_KARMA_CHAR_FEB_21_2007_0543PM
9
10 #if defined(_MSC_VER)
11 #pragma once
12 #endif
13
14 #include <boost/spirit/home/support/common_terminals.hpp>
15 #include <boost/spirit/home/support/string_traits.hpp>
16 #include <boost/spirit/home/support/info.hpp>
17 #include <boost/spirit/home/support/char_class.hpp>
18 #include <boost/spirit/home/support/detail/get_encoding.hpp>
19 #include <boost/spirit/home/support/char_set/basic_chset.hpp>
20 #include <boost/spirit/home/karma/domain.hpp>
21 #include <boost/spirit/home/karma/meta_compiler.hpp>
22 #include <boost/spirit/home/karma/delimit_out.hpp>
23 #include <boost/spirit/home/karma/char/char_generator.hpp>
24 #include <boost/spirit/home/karma/auxiliary/lazy.hpp>
25 #include <boost/spirit/home/karma/detail/get_casetag.hpp>
26 #include <boost/spirit/home/karma/detail/generate_to.hpp>
27 #include <boost/spirit/home/karma/detail/enable_lit.hpp>
28 #include <boost/fusion/include/at.hpp>
29 #include <boost/fusion/include/vector.hpp>
30 #include <boost/fusion/include/cons.hpp>
31 #include <boost/mpl/if.hpp>
32 #include <boost/mpl/assert.hpp>
33 #include <boost/mpl/bool.hpp>
34 #include <boost/utility/enable_if.hpp>
35 #include <string>
36
37 ///////////////////////////////////////////////////////////////////////////////
38 namespace boost { namespace spirit
39 {
40 ///////////////////////////////////////////////////////////////////////////
41 // Enablers
42 ///////////////////////////////////////////////////////////////////////////
43 template <typename CharEncoding>
44 struct use_terminal<karma::domain
45 , tag::char_code<tag::char_, CharEncoding> // enables char_
46 > : mpl::true_ {};
47
48 template <typename CharEncoding, typename A0>
49 struct use_terminal<karma::domain
50 , terminal_ex<
51 tag::char_code<tag::char_, CharEncoding> // enables char_('x'), char_("x")
52 , fusion::vector1<A0>
53 >
54 > : mpl::true_ {};
55
56 template <typename A0>
57 struct use_terminal<karma::domain
58 , terminal_ex<tag::lit, fusion::vector1<A0> > // enables lit('x')
59 , typename enable_if<traits::is_char<A0> >::type>
60 : mpl::true_ {};
61
62 template <typename CharEncoding, typename A0, typename A1>
63 struct use_terminal<karma::domain
64 , terminal_ex<
65 tag::char_code<tag::char_, CharEncoding> // enables char_('a','z')
66 , fusion::vector2<A0, A1>
67 >
68 > : mpl::true_ {};
69
70 template <typename CharEncoding> // enables *lazy* char_('x'), char_("x")
71 struct use_lazy_terminal<
72 karma::domain
73 , tag::char_code<tag::char_, CharEncoding>
74 , 1 // arity
75 > : mpl::true_ {};
76
77 template <>
78 struct use_terminal<karma::domain, char> // enables 'x'
79 : mpl::true_ {};
80
81 template <>
82 struct use_terminal<karma::domain, char[2]> // enables "x"
83 : mpl::true_ {};
84
85 template <>
86 struct use_terminal<karma::domain, wchar_t> // enables L'x'
87 : mpl::true_ {};
88
89 template <>
90 struct use_terminal<karma::domain, wchar_t[2]> // enables L"x"
91 : mpl::true_ {};
92 }}
93
94 ///////////////////////////////////////////////////////////////////////////////
95 namespace boost { namespace spirit { namespace karma
96 {
97 #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
98 using spirit::lit; // lit('x') is equivalent to 'x'
99 #endif
100 using spirit::lit_type;
101
102 ///////////////////////////////////////////////////////////////////////////
103 //
104 // any_char
105 // generates a single character from the associated attribute
106 //
107 // Note: this generator has to have an associated attribute
108 //
109 ///////////////////////////////////////////////////////////////////////////
110 template <typename CharEncoding, typename Tag>
111 struct any_char
112 : char_generator<any_char<CharEncoding, Tag>, CharEncoding, Tag>
113 {
114 typedef typename CharEncoding::char_type char_type;
115 typedef CharEncoding char_encoding;
116
117 template <typename Context, typename Unused>
118 struct attribute
119 {
120 typedef char_type type;
121 };
122
123 // any_char has an attached parameter
124 template <typename Attribute, typename CharParam, typename Context>
125 bool test(Attribute const& attr, CharParam& ch, Context&) const
126 {
127 ch = CharParam(attr);
128 return true;
129 }
130
131 // any_char has no attribute attached, it needs to have been
132 // initialized from a direct literal
133 template <typename CharParam, typename Context>
134 bool test(unused_type, CharParam&, Context&) const
135 {
136 // It is not possible (doesn't make sense) to use char_ without
137 // providing any attribute, as the generator doesn't 'know' what
138 // character to output. The following assertion fires if this
139 // situation is detected in your code.
140 BOOST_SPIRIT_ASSERT_FAIL(CharParam, char_not_usable_without_attribute, ());
141 return false;
142 }
143
144 template <typename Context>
145 static info what(Context const& /*context*/)
146 {
147 return info("any-char");
148 }
149 };
150
151 ///////////////////////////////////////////////////////////////////////////
152 //
153 // literal_char
154 // generates a single character given by a literal it was initialized
155 // from
156 //
157 ///////////////////////////////////////////////////////////////////////////
158 template <typename CharEncoding, typename Tag, bool no_attribute>
159 struct literal_char
160 : char_generator<literal_char<CharEncoding, Tag, no_attribute>
161 , CharEncoding, Tag>
162 {
163 typedef typename CharEncoding::char_type char_type;
164 typedef CharEncoding char_encoding;
165
166 literal_char(char_type ch)
167 : ch (spirit::char_class::convert<char_encoding>::to(Tag(), ch))
168 {}
169
170 template <typename Context, typename Unused>
171 struct attribute
172 : mpl::if_c<no_attribute, unused_type, char_type>
173 {};
174
175 // A char_('x') which additionally has an associated attribute emits
176 // its immediate literal only if it matches the attribute, otherwise
177 // it fails.
178 // any_char has an attached parameter
179 template <typename Attribute, typename CharParam, typename Context>
180 bool test(Attribute const& attr, CharParam& ch_, Context&) const
181 {
182 // fail if attribute isn't matched my immediate literal
183 ch_ = attr;
184 return attr == ch;
185 }
186
187 // A char_('x') without any associated attribute just emits its
188 // immediate literal
189 template <typename CharParam, typename Context>
190 bool test(unused_type, CharParam& ch_, Context&) const
191 {
192 ch_ = ch;
193 return true;
194 }
195
196 template <typename Context>
197 info what(Context const& /*context*/) const
198 {
199 return info("literal-char", char_encoding::toucs4(ch));
200 }
201
202 char_type ch;
203 };
204
205 ///////////////////////////////////////////////////////////////////////////
206 // char range generator
207 template <typename CharEncoding, typename Tag>
208 struct char_range
209 : char_generator<char_range<CharEncoding, Tag>, CharEncoding, Tag>
210 {
211 typedef typename CharEncoding::char_type char_type;
212 typedef CharEncoding char_encoding;
213
214 char_range(char_type from, char_type to)
215 : from(spirit::char_class::convert<char_encoding>::to(Tag(), from))
216 , to(spirit::char_class::convert<char_encoding>::to(Tag(), to))
217 {}
218
219 // A char_('a', 'z') which has an associated attribute emits it only if
220 // it matches the character range, otherwise it fails.
221 template <typename Attribute, typename CharParam, typename Context>
222 bool test(Attribute const& attr, CharParam& ch, Context&) const
223 {
224 // fail if attribute doesn't belong to character range
225 ch = attr;
226 return (from <= char_type(attr)) && (char_type(attr) <= to);
227 }
228
229 // A char_('a', 'z') without any associated attribute fails compiling
230 template <typename CharParam, typename Context>
231 bool test(unused_type, CharParam&, Context&) const
232 {
233 // It is not possible (doesn't make sense) to use char_ generators
234 // without providing any attribute, as the generator doesn't 'know'
235 // what to output. The following assertion fires if this situation
236 // is detected in your code.
237 BOOST_SPIRIT_ASSERT_FAIL(CharParam
238 , char_range_not_usable_without_attribute, ());
239 return false;
240 }
241
242 template <typename Context>
243 info what(Context& /*context*/) const
244 {
245 info result("char-range", char_encoding::toucs4(from));
246 boost::get<std::string>(result.value) += '-';
247 boost::get<std::string>(result.value) += to_utf8(char_encoding::toucs4(to));
248 return result;
249 }
250
251 char_type from, to;
252 };
253
254 ///////////////////////////////////////////////////////////////////////////
255 // character set generator
256 template <typename CharEncoding, typename Tag, bool no_attribute>
257 struct char_set
258 : char_generator<char_set<CharEncoding, Tag, no_attribute>
259 , CharEncoding, Tag>
260 {
261 typedef typename CharEncoding::char_type char_type;
262 typedef CharEncoding char_encoding;
263
264 template <typename Context, typename Unused>
265 struct attribute
266 : mpl::if_c<no_attribute, unused_type, char_type>
267 {};
268
269 template <typename String>
270 char_set(String const& str)
271 {
272 typedef typename traits::char_type_of<String>::type in_type;
273
274 BOOST_SPIRIT_ASSERT_MSG((
275 (sizeof(char_type) == sizeof(in_type))
276 ), cannot_convert_string, (String));
277
278 typedef spirit::char_class::convert<char_encoding> convert_type;
279
280 char_type const* definition =
281 (char_type const*)traits::get_c_string(str);
282 char_type ch = convert_type::to(Tag(), *definition++);
283 while (ch)
284 {
285 char_type next = convert_type::to(Tag(), *definition++);
286 if (next == '-')
287 {
288 next = convert_type::to(Tag(), *definition++);
289 if (next == 0)
290 {
291 chset.set(ch);
292 chset.set('-');
293 break;
294 }
295 chset.set(ch, next);
296 }
297 else
298 {
299 chset.set(ch);
300 }
301 ch = next;
302 }
303 }
304
305 // A char_("a-z") which has an associated attribute emits it only if
306 // it matches the character set, otherwise it fails.
307 template <typename Attribute, typename CharParam, typename Context>
308 bool test(Attribute const& attr, CharParam& ch, Context&) const
309 {
310 // fail if attribute doesn't belong to character set
311 ch = attr;
312 return chset.test(char_type(attr));
313 }
314
315 // A char_("a-z") without any associated attribute fails compiling
316 template <typename CharParam, typename Context>
317 bool test(unused_type, CharParam&, Context&) const
318 {
319 // It is not possible (doesn't make sense) to use char_ generators
320 // without providing any attribute, as the generator doesn't 'know'
321 // what to output. The following assertion fires if this situation
322 // is detected in your code.
323 BOOST_SPIRIT_ASSERT_FAIL(CharParam
324 , char_set_not_usable_without_attribute, ());
325 return false;
326 }
327
328 template <typename Context>
329 info what(Context& /*context*/) const
330 {
331 return info("char-set");
332 }
333
334 support::detail::basic_chset<char_type> chset;
335 };
336
337 ///////////////////////////////////////////////////////////////////////////
338 // Generator generators: make_xxx function (objects)
339 ///////////////////////////////////////////////////////////////////////////
340 namespace detail
341 {
342 template <typename Modifiers, typename Encoding>
343 struct basic_literal
344 {
345 static bool const lower =
346 has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
347 static bool const upper =
348 has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
349
350 typedef literal_char<
351 typename spirit::detail::get_encoding_with_case<
352 Modifiers, Encoding, lower || upper>::type
353 , typename get_casetag<Modifiers, lower || upper>::type
354 , true>
355 result_type;
356
357 template <typename Char>
358 result_type operator()(Char ch, unused_type) const
359 {
360 return result_type(ch);
361 }
362
363 template <typename Char>
364 result_type operator()(Char const* str, unused_type) const
365 {
366 return result_type(str[0]);
367 }
368 };
369 }
370
371 // literals: 'x', "x"
372 template <typename Modifiers>
373 struct make_primitive<char, Modifiers>
374 : detail::basic_literal<Modifiers, char_encoding::standard> {};
375
376 template <typename Modifiers>
377 struct make_primitive<char const(&)[2], Modifiers>
378 : detail::basic_literal<Modifiers, char_encoding::standard> {};
379
380 // literals: L'x', L"x"
381 template <typename Modifiers>
382 struct make_primitive<wchar_t, Modifiers>
383 : detail::basic_literal<Modifiers, char_encoding::standard_wide> {};
384
385 template <typename Modifiers>
386 struct make_primitive<wchar_t const(&)[2], Modifiers>
387 : detail::basic_literal<Modifiers, char_encoding::standard_wide> {};
388
389 // char_
390 template <typename CharEncoding, typename Modifiers>
391 struct make_primitive<tag::char_code<tag::char_, CharEncoding>, Modifiers>
392 {
393 static bool const lower =
394 has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
395 static bool const upper =
396 has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
397
398 typedef any_char<
399 typename spirit::detail::get_encoding_with_case<
400 Modifiers, CharEncoding, lower || upper>::type
401 , typename detail::get_casetag<Modifiers, lower || upper>::type
402 > result_type;
403
404 result_type operator()(unused_type, unused_type) const
405 {
406 return result_type();
407 }
408 };
409
410 ///////////////////////////////////////////////////////////////////////////
411 namespace detail
412 {
413 template <typename CharEncoding, typename Modifiers, typename A0
414 , bool no_attribute>
415 struct make_char_direct
416 {
417 static bool const lower =
418 has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
419 static bool const upper =
420 has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
421
422 typedef typename spirit::detail::get_encoding_with_case<
423 Modifiers, CharEncoding, lower || upper>::type encoding;
424 typedef typename detail::get_casetag<
425 Modifiers, lower || upper>::type tag;
426
427 typedef typename mpl::if_<
428 traits::is_string<A0>
429 , char_set<encoding, tag, no_attribute>
430 , literal_char<encoding, tag, no_attribute>
431 >::type result_type;
432
433 template <typename Terminal>
434 result_type operator()(Terminal const& term, unused_type) const
435 {
436 return result_type(fusion::at_c<0>(term.args));
437 }
438 };
439 }
440
441 // char_(...), lit(...)
442 template <typename CharEncoding, typename Modifiers, typename A0>
443 struct make_primitive<
444 terminal_ex<
445 tag::char_code<tag::char_, CharEncoding>
446 , fusion::vector1<A0> >
447 , Modifiers>
448 : detail::make_char_direct<CharEncoding, Modifiers, A0, false>
449 {};
450
451 template <typename Modifiers, typename A0>
452 struct make_primitive<
453 terminal_ex<tag::lit, fusion::vector1<A0> >
454 , Modifiers
455 , typename enable_if<traits::is_char<A0> >::type>
456 : detail::make_char_direct<
457 typename traits::char_encoding_from_char<
458 typename traits::char_type_of<A0>::type>::type
459 , Modifiers, A0, true>
460 {};
461
462 ///////////////////////////////////////////////////////////////////////////
463 // char_("x")
464 template <typename CharEncoding, typename Modifiers, typename Char>
465 struct make_primitive<
466 terminal_ex<
467 tag::char_code<tag::char_, CharEncoding>
468 , fusion::vector1<Char(&)[2]> > // For single char strings
469 , Modifiers>
470 {
471 static bool const lower =
472 has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
473 static bool const upper =
474 has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
475
476 typedef literal_char<
477 typename spirit::detail::get_encoding_with_case<
478 Modifiers, CharEncoding, lower || upper>::type
479 , typename detail::get_casetag<Modifiers, lower || upper>::type
480 , false
481 > result_type;
482
483 template <typename Terminal>
484 result_type operator()(Terminal const& term, unused_type) const
485 {
486 return result_type(fusion::at_c<0>(term.args)[0]);
487 }
488 };
489
490 ///////////////////////////////////////////////////////////////////////////
491 // char_('a', 'z')
492 template <typename CharEncoding, typename Modifiers, typename A0, typename A1>
493 struct make_primitive<
494 terminal_ex<
495 tag::char_code<tag::char_, CharEncoding>
496 , fusion::vector2<A0, A1>
497 >
498 , Modifiers>
499 {
500 static bool const lower =
501 has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
502 static bool const upper =
503 has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
504
505 typedef char_range<
506 typename spirit::detail::get_encoding_with_case<
507 Modifiers, CharEncoding, lower || upper>::type
508 , typename detail::get_casetag<Modifiers, lower || upper>::type
509 > result_type;
510
511 template <typename Terminal>
512 result_type operator()(Terminal const& term, unused_type) const
513 {
514 return result_type(fusion::at_c<0>(term.args)
515 , fusion::at_c<1>(term.args));
516 }
517 };
518
519 template <typename CharEncoding, typename Modifiers, typename Char>
520 struct make_primitive<
521 terminal_ex<
522 tag::char_code<tag::char_, CharEncoding>
523 , fusion::vector2<Char(&)[2], Char(&)[2]> // For single char strings
524 >
525 , Modifiers>
526 {
527 static bool const lower =
528 has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
529 static bool const upper =
530 has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
531
532 typedef char_range<
533 typename spirit::detail::get_encoding_with_case<
534 Modifiers, CharEncoding, lower || upper>::type
535 , typename detail::get_casetag<Modifiers, lower || upper>::type
536 > result_type;
537
538 template <typename Terminal>
539 result_type operator()(Terminal const& term, unused_type) const
540 {
541 return result_type(fusion::at_c<0>(term.args)[0]
542 , fusion::at_c<1>(term.args)[0]);
543 }
544 };
545 }}} // namespace boost::spirit::karma
546
547 #endif