]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/spirit/include/boost/spirit/home/karma/string/symbols.hpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / spirit / include / boost / spirit / home / karma / string / symbols.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_SYMBOLS_NOV_23_2009_1251PM)
7 #define BOOST_SPIRIT_KARMA_SYMBOLS_NOV_23_2009_1251PM
8
9 #include <boost/spirit/home/support/common_terminals.hpp>
10 #include <boost/spirit/home/support/info.hpp>
11 #include <boost/spirit/home/support/unused.hpp>
12 #include <boost/spirit/home/support/attributes_fwd.hpp>
13 #include <boost/spirit/home/support/detail/get_encoding.hpp>
14 #include <boost/spirit/home/karma/detail/attributes.hpp>
15 #include <boost/spirit/home/karma/detail/extract_from.hpp>
16 #include <boost/spirit/home/karma/domain.hpp>
17 #include <boost/spirit/home/karma/meta_compiler.hpp>
18 #include <boost/spirit/home/karma/reference.hpp>
19 #include <boost/spirit/home/karma/generate.hpp>
20 #include <boost/spirit/home/karma/delimit_out.hpp>
21 #include <boost/spirit/home/karma/detail/get_casetag.hpp>
22 #include <boost/spirit/home/karma/detail/string_generate.hpp>
23 #include <boost/config.hpp>
24 #include <boost/shared_ptr.hpp>
25 #include <boost/mpl/if.hpp>
26 #include <map>
27 #include <set>
28
29 #if defined(BOOST_MSVC)
30 # pragma warning(push)
31 # pragma warning(disable: 4355) // 'this' : used in base member initializer list warning
32 #endif
33
34 ///////////////////////////////////////////////////////////////////////////////
35 namespace boost { namespace spirit { namespace traits
36 {
37 template <typename T, typename Attribute, typename Enable>
38 struct symbols_lookup
39 {
40 typedef
41 mpl::eval_if<fusion::traits::is_sequence<T>
42 , traits::detail::value_at_c<T, 0>
43 , detail::add_const_ref<T> > sequence_type;
44 typedef typename
45 mpl::eval_if<traits::is_container<T>
46 , traits::container_value<T>
47 , sequence_type>::type type;
48
49 // fusion sequence
50 template <typename T_>
51 static type call(T_ const& t, mpl::false_, mpl::true_)
52 {
53 return fusion::at_c<0>(t);
54 }
55
56 // container
57 template <typename T_, typename IsSequence>
58 static type call(T_ const& t, mpl::true_, IsSequence)
59 {
60 return t[0];
61 }
62
63 // not a container and not a fusion sequence
64 template <typename T_>
65 static type call(T_ const& t, mpl::false_, mpl::false_)
66 {
67 return t;
68 }
69
70 static type call(T const& t)
71 {
72 typedef typename traits::is_container<T>::type is_container;
73 typedef typename fusion::traits::is_sequence<T>::type is_sequence;
74
75 return call(t, is_container(), is_sequence());
76 }
77 };
78
79 template <typename Attribute>
80 struct symbols_lookup<Attribute, Attribute>
81 {
82 typedef Attribute const& type;
83
84 static type call(Attribute const& t)
85 {
86 return t;
87 }
88 };
89
90 template <typename Attribute, typename T, typename Enable>
91 struct symbols_value
92 {
93 typedef
94 mpl::eval_if<fusion::traits::is_sequence<T>
95 , traits::detail::value_at_c<T, 1>
96 , mpl::identity<unused_type> > sequence_type;
97 typedef typename
98 mpl::eval_if<traits::is_container<T>
99 , traits::container_value<T>
100 , sequence_type>::type type;
101
102 // fusion sequence
103 template <typename T_>
104 static type call(T_ const& t, mpl::false_, mpl::true_)
105 {
106 return fusion::at_c<1>(t);
107 }
108
109 // container
110 template <typename T_, typename IsSequence>
111 static type call(T_ const& t, mpl::true_, IsSequence)
112 {
113 return t[1];
114 }
115
116 // not a container nor a fusion sequence
117 template <typename T_>
118 static type call(T_ const&, mpl::false_, mpl::false_)
119 {
120 return unused;
121 }
122
123 static type call(T const& t)
124 {
125 typedef typename traits::is_container<T>::type is_container;
126 typedef typename fusion::traits::is_sequence<T>::type is_sequence;
127
128 return call(t, is_container(), is_sequence());
129 }
130 };
131
132 template <typename Attribute>
133 struct symbols_value<Attribute, Attribute>
134 {
135 typedef unused_type type;
136
137 static type call(Attribute const&)
138 {
139 return unused;
140 }
141 };
142 }}}
143
144 ///////////////////////////////////////////////////////////////////////////////
145 namespace boost { namespace spirit { namespace karma
146 {
147 ///////////////////////////////////////////////////////////////////////////
148 template <typename T, typename Attribute>
149 struct symbols_lookup
150 : mpl::if_<
151 traits::not_is_unused<T>
152 , std::map<Attribute, T>
153 , std::set<Attribute>
154 >
155 {};
156
157 ///////////////////////////////////////////////////////////////////////////
158 namespace detail
159 {
160 ///////////////////////////////////////////////////////////////////////
161 template <typename CharEncoding, typename Tag>
162 struct generate_encoded
163 {
164 typedef typename
165 proto::terminal<tag::char_code<Tag, CharEncoding> >::type
166 encoding_type;
167
168 template <typename OutputIterator, typename Expr, typename Attribute>
169 static bool call(OutputIterator& sink, Expr const& expr
170 , Attribute const& attr)
171 {
172 encoding_type const encoding = encoding_type();
173 return karma::generate(sink, encoding[expr], attr);
174 }
175 };
176
177 template <>
178 struct generate_encoded<unused_type, unused_type>
179 {
180 template <typename OutputIterator, typename Expr, typename Attribute>
181 static bool call(OutputIterator& sink, Expr const& expr
182 , Attribute const& attr)
183 {
184 return karma::generate(sink, expr, attr);
185 }
186 };
187 }
188
189 template <
190 typename Attribute = char, typename T = unused_type
191 , typename Lookup = typename symbols_lookup<T, Attribute>::type
192 , typename CharEncoding = unused_type, typename Tag = unused_type>
193 struct symbols
194 : proto::extends<
195 typename proto::terminal<
196 reference<symbols<Attribute, T, Lookup, CharEncoding, Tag> >
197 >::type
198 , symbols<Attribute, T, Lookup, CharEncoding, Tag> >
199 , primitive_generator<
200 symbols<Attribute, T, Lookup, CharEncoding, Tag> >
201 {
202 typedef T value_type; // the value associated with each entry
203
204 typedef reference<symbols> reference_;
205 typedef typename proto::terminal<reference_>::type terminal;
206 typedef proto::extends<terminal, symbols> base_type;
207
208 template <typename Context, typename Unused>
209 struct attribute
210 {
211 typedef Attribute type;
212 };
213
214 symbols(std::string const& name = "symbols")
215 : base_type(terminal::make(reference_(*this)))
216 , add(*this)
217 , remove(*this)
218 , lookup(new Lookup())
219 , name_(name)
220 {}
221
222 symbols(symbols const& syms)
223 : base_type(terminal::make(reference_(*this)))
224 , add(*this)
225 , remove(*this)
226 , lookup(syms.lookup)
227 , name_(syms.name_)
228 {}
229
230 template <typename CharEncoding_, typename Tag_>
231 symbols(symbols<Attribute, T, Lookup, CharEncoding_, Tag_> const& syms)
232 : base_type(terminal::make(reference_(*this)))
233 , add(*this)
234 , remove(*this)
235 , lookup(syms.lookup)
236 , name_(syms.name_)
237 {}
238
239 template <typename Symbols, typename Data>
240 symbols(Symbols const& syms, Data const& data
241 , std::string const& name = "symbols")
242 : base_type(terminal::make(reference_(*this)))
243 , add(*this)
244 , remove(*this)
245 , lookup(new Lookup())
246 , name_(name)
247 {
248 typename range_const_iterator<Symbols>::type si = boost::begin(syms);
249 typename range_const_iterator<Data>::type di = boost::begin(data);
250 while (si != boost::end(syms))
251 add(*si++, *di++);
252 }
253
254 symbols&
255 operator=(symbols const& rhs)
256 {
257 *lookup = *rhs.lookup;
258 name_ = rhs.name_;
259 return *this;
260 }
261
262 template <typename CharEncoding_, typename Tag_>
263 symbols&
264 operator=(symbols<Attribute, T, Lookup, CharEncoding_, Tag_> const& rhs)
265 {
266 *lookup = *rhs.lookup;
267 name_ = rhs.name_;
268 return *this;
269 }
270
271 void clear()
272 {
273 lookup->clear();
274 }
275
276 struct adder;
277 struct remover;
278
279 template <typename Attr, typename T_>
280 adder const&
281 operator=(std::pair<Attr, T_> const& p)
282 {
283 lookup->clear();
284 return add(p.first, p.second);
285 }
286
287 template <typename Attr, typename T_>
288 friend adder const&
289 operator+= (symbols& sym, std::pair<Attr, T_> const& p)
290 {
291 return sym.add(p.first, p.second);
292 }
293
294 template <typename Attr>
295 friend remover const&
296 operator-= (symbols& sym, Attr const& attr)
297 {
298 return sym.remove(attr);
299 }
300
301 #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
302 // non-const version needed to suppress proto's += kicking in
303 template <typename Attr, typename T_>
304 friend adder const&
305 operator+= (symbols& sym, std::pair<Attr, T_>& p)
306 {
307 return sym.add(p.first, p.second);
308 }
309
310 // non-const version needed to suppress proto's -= kicking in
311 template <typename Attr>
312 friend remover const&
313 operator-= (symbols& sym, Attr& attr)
314 {
315 return sym.remove(attr);
316 }
317 #else
318 // for rvalue references
319 template <typename Attr, typename T_>
320 friend adder const&
321 operator+= (symbols& sym, std::pair<Attr, T_>&& p)
322 {
323 return sym.add(p.first, p.second);
324 }
325
326 // for rvalue references
327 template <typename Attr>
328 friend remover const&
329 operator-= (symbols& sym, Attr&& attr)
330 {
331 return sym.remove(attr);
332 }
333 #endif
334 template <typename F>
335 void for_each(F f) const
336 {
337 std::for_each(lookup->begin(), lookup->end(), f);
338 }
339
340 template <typename Attr>
341 value_type* find(Attr const& attr)
342 {
343 typename Lookup::iterator it = lookup->find(attr);
344 return (it != lookup->end()) ? &(*it).second : 0;
345 }
346
347 template <typename Attr>
348 value_type& at(Attr const& attr)
349 {
350 return (*lookup)[attr];
351 }
352
353 ///////////////////////////////////////////////////////////////////////
354 template <typename OutputIterator, typename Context, typename Delimiter
355 , typename Attr>
356 bool generate(OutputIterator& sink, Context&, Delimiter const& d
357 , Attr const& attr) const
358 {
359 typename Lookup::iterator it = lookup->find(
360 traits::symbols_lookup<Attr, Attribute>::call(attr));
361 if (it == lookup->end())
362 return false;
363
364 return karma::detail::generate_encoded<CharEncoding, Tag>::call(
365 sink, (*it).second
366 , traits::symbols_value<Attribute, Attr>::call(attr)) &&
367 karma::delimit_out(sink, d);
368 }
369
370 template <typename Context>
371 info what(Context&) const
372 {
373 return info(name_);
374 }
375
376 void name(std::string const &str)
377 {
378 name_ = str;
379 }
380 std::string const &name() const
381 {
382 return name_;
383 }
384
385 ///////////////////////////////////////////////////////////////////////
386 struct adder
387 {
388 template <typename, typename = unused_type>
389 struct result { typedef adder const& type; };
390
391 adder(symbols& sym)
392 : sym(sym)
393 {
394 }
395
396 template <typename Attr>
397 adder const&
398 operator()(Attr const& attr, T const& val = T()) const
399 {
400 sym.lookup->insert(typename Lookup::value_type(attr, val));
401 return *this;
402 }
403
404 template <typename Attr>
405 adder const&
406 operator, (Attr const& attr) const
407 {
408 sym.lookup->insert(typename Lookup::value_type(attr, T()));
409 return *this;
410 }
411
412 symbols& sym;
413
414 private:
415 // silence MSVC warning C4512: assignment operator could not be generated
416 adder& operator= (adder const&);
417 };
418
419 struct remover
420 {
421 template <typename>
422 struct result { typedef remover const& type; };
423
424 remover(symbols& sym)
425 : sym(sym)
426 {
427 }
428
429 template <typename Attr>
430 remover const&
431 operator()(Attr const& attr) const
432 {
433 sym.lookup->erase(attr);
434 return *this;
435 }
436
437 template <typename Attr>
438 remover const&
439 operator, (Attr const& attr) const
440 {
441 sym.lookup->erase(attr);
442 return *this;
443 }
444
445 symbols& sym;
446
447 private:
448 // silence MSVC warning C4512: assignment operator could not be generated
449 remover& operator= (remover const&);
450 };
451
452 adder add;
453 remover remove;
454 shared_ptr<Lookup> lookup;
455 std::string name_;
456 };
457
458 ///////////////////////////////////////////////////////////////////////////
459 // specialization for unused stored type
460 template <
461 typename Attribute, typename Lookup
462 , typename CharEncoding, typename Tag>
463 struct symbols<Attribute, unused_type, Lookup, CharEncoding, Tag>
464 : proto::extends<
465 typename proto::terminal<
466 spirit::karma::reference<
467 symbols<Attribute, unused_type, Lookup, CharEncoding, Tag> >
468 >::type
469 , symbols<Attribute, unused_type, Lookup, CharEncoding, Tag>
470 >
471 , spirit::karma::generator<
472 symbols<Attribute, unused_type, Lookup, CharEncoding, Tag> >
473 {
474 typedef unused_type value_type; // the value associated with each entry
475
476 typedef spirit::karma::reference<symbols> reference_;
477 typedef typename proto::terminal<reference_>::type terminal;
478 typedef proto::extends<terminal, symbols> base_type;
479
480 template <typename Context, typename Unused>
481 struct attribute
482 {
483 typedef Attribute type;
484 };
485
486 symbols(std::string const& name = "symbols")
487 : base_type(terminal::make(reference_(*this)))
488 , add(*this)
489 , remove(*this)
490 , lookup(new Lookup())
491 , name_(name)
492 {}
493
494 symbols(symbols const& syms)
495 : base_type(terminal::make(reference_(*this)))
496 , add(*this)
497 , remove(*this)
498 , lookup(syms.lookup)
499 , name_(syms.name_)
500 {}
501
502 template <typename CharEncoding_, typename Tag_>
503 symbols(symbols<Attribute, unused_type, Lookup, CharEncoding_, Tag_> const& syms)
504 : base_type(terminal::make(reference_(*this)))
505 , add(*this)
506 , remove(*this)
507 , lookup(syms.lookup)
508 , name_(syms.name_)
509 {}
510
511 template <typename Symbols, typename Data>
512 symbols(Symbols const& syms, Data const& data
513 , std::string const& name = "symbols")
514 : base_type(terminal::make(reference_(*this)))
515 , add(*this)
516 , remove(*this)
517 , lookup(new Lookup())
518 , name_(name)
519 {
520 typename range_const_iterator<Symbols>::type si = boost::begin(syms);
521 typename range_const_iterator<Data>::type di = boost::begin(data);
522 while (si != boost::end(syms))
523 add(*si++, *di++);
524 }
525
526 symbols&
527 operator=(symbols const& rhs)
528 {
529 *lookup = *rhs.lookup;
530 name_ = rhs.name_;
531 return *this;
532 }
533
534 template <typename CharEncoding_, typename Tag_>
535 symbols&
536 operator=(symbols<Attribute, unused_type, Lookup, CharEncoding_, Tag_> const& rhs)
537 {
538 *lookup = *rhs.lookup;
539 name_ = rhs.name_;
540 return *this;
541 }
542
543 void clear()
544 {
545 lookup->clear();
546 }
547
548 struct adder;
549 struct remover;
550
551 template <typename Attr>
552 adder const&
553 operator=(Attr const& attr)
554 {
555 lookup->clear();
556 return add(attr);
557 }
558
559 template <typename Attr>
560 friend adder const&
561 operator+= (symbols& sym, Attr const& attr)
562 {
563 return sym.add(attr);
564 }
565
566 template <typename Attr>
567 friend remover const&
568 operator-= (symbols& sym, Attr const& attr)
569 {
570 return sym.remove(attr);
571 }
572
573 // non-const version needed to suppress proto's += kicking in
574 template <typename Attr>
575 friend adder const&
576 operator+= (symbols& sym, Attr& attr)
577 {
578 return sym.add(attr);
579 }
580
581 // non-const version needed to suppress proto's -= kicking in
582 template <typename Attr>
583 friend remover const&
584 operator-= (symbols& sym, Attr& attr)
585 {
586 return sym.remove(attr);
587 }
588
589 template <typename F>
590 void for_each(F f) const
591 {
592 std::for_each(lookup->begin(), lookup->end(), f);
593 }
594
595 template <typename Attr>
596 value_type const* find(Attr const& attr)
597 {
598 typename Lookup::iterator it = lookup->find(attr);
599 return (it != lookup->end()) ? &unused : 0;
600 }
601
602 template <typename Attr>
603 value_type at(Attr const& attr)
604 {
605 typename Lookup::iterator it = lookup->find(attr);
606 if (it == lookup->end())
607 add(attr);
608 return unused;
609 }
610
611 ///////////////////////////////////////////////////////////////////////
612 template <typename OutputIterator, typename Context, typename Delimiter
613 , typename Attr>
614 bool generate(OutputIterator& sink, Context&, Delimiter const& d
615 , Attr const& attr) const
616 {
617 typename Lookup::iterator it = lookup->find(
618 traits::symbols_lookup<Attr, Attribute>::call(attr));
619 if (it == lookup->end())
620 return false;
621
622 return karma::detail::generate_encoded<CharEncoding, Tag>::
623 call(sink
624 , traits::symbols_lookup<Attr, Attribute>::call(attr)
625 , unused) &&
626 karma::delimit_out(sink, d);
627 }
628
629 template <typename Context>
630 info what(Context&) const
631 {
632 return info(name_);
633 }
634
635 void name(std::string const &str)
636 {
637 name_ = str;
638 }
639 std::string const &name() const
640 {
641 return name_;
642 }
643
644 ///////////////////////////////////////////////////////////////////////
645 struct adder
646 {
647 template <typename, typename = unused_type>
648 struct result { typedef adder const& type; };
649
650 adder(symbols& sym)
651 : sym(sym)
652 {
653 }
654
655 template <typename Attr>
656 adder const&
657 operator()(Attr const& attr) const
658 {
659 sym.lookup->insert(attr);
660 return *this;
661 }
662
663 template <typename Attr>
664 adder const&
665 operator, (Attr const& attr) const
666 {
667 sym.lookup->insert(attr);
668 return *this;
669 }
670
671 symbols& sym;
672
673 private:
674 // silence MSVC warning C4512: assignment operator could not be generated
675 adder& operator= (adder const&);
676 };
677
678 struct remover
679 {
680 template <typename>
681 struct result { typedef remover const& type; };
682
683 remover(symbols& sym)
684 : sym(sym)
685 {
686 }
687
688 template <typename Attr>
689 remover const&
690 operator()(Attr const& attr) const
691 {
692 sym.lookup->erase(attr);
693 return *this;
694 }
695
696 template <typename Attr>
697 remover const&
698 operator, (Attr const& attr) const
699 {
700 sym.lookup->erase(attr);
701 return *this;
702 }
703
704 symbols& sym;
705
706 private:
707 // silence MSVC warning C4512: assignment operator could not be generated
708 remover& operator= (remover const&);
709 };
710
711 adder add;
712 remover remove;
713 shared_ptr<Lookup> lookup;
714 std::string name_;
715 };
716
717 ///////////////////////////////////////////////////////////////////////////
718 // Generator generators: make_xxx function (objects)
719 ///////////////////////////////////////////////////////////////////////////
720 template <typename Attribute, typename T, typename Lookup
721 , typename CharEnconding, typename Tag, typename Modifiers>
722 struct make_primitive<
723 reference<symbols<Attribute, T, Lookup, CharEnconding, Tag> >
724 , Modifiers>
725 {
726 static bool const lower =
727 has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
728 static bool const upper =
729 has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
730
731 typedef reference<
732 symbols<Attribute, T, Lookup, CharEnconding, Tag>
733 > reference_;
734
735 typedef typename mpl::if_c<
736 lower || upper
737 , symbols<
738 Attribute, T, Lookup
739 , typename spirit::detail::get_encoding_with_case<
740 Modifiers, unused_type, lower || upper>::type
741 , typename detail::get_casetag<Modifiers, lower || upper>::type>
742 , reference_>::type
743 result_type;
744
745 result_type operator()(reference_ ref, unused_type) const
746 {
747 return result_type(ref.ref.get());
748 }
749 };
750 }}}
751
752 namespace boost { namespace spirit { namespace traits
753 {
754 ///////////////////////////////////////////////////////////////////////////
755 template <typename Attribute, typename T, typename Lookup
756 , typename CharEncoding, typename Tag
757 , typename Attr, typename Context, typename Iterator>
758 struct handles_container<karma::symbols<Attribute, T, Lookup, CharEncoding, Tag>
759 , Attr, Context, Iterator>
760 : traits::is_container<Attr> {};
761 }}}
762
763 #if defined(BOOST_MSVC)
764 # pragma warning(pop)
765 #endif
766
767 #endif
768