]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/spirit/home/support/utree/utree_traits.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / boost / spirit / home / support / utree / utree_traits.hpp
1 /*=============================================================================
2 Copyright (c) 2001-2011 Joel de Guzman
3 Copyright (c) 2001-2011 Hartmut Kaiser
4 Copyright (c) 2010-2011 Bryce Lelbach
5
6 Distributed under the Boost Software License, Version 1.0. (See accompanying
7 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8 =============================================================================*/
9 #if !defined(BOOST_SPIRIT_OUTPUT_UTREE_TRAITS_APR_16_2010_0655AM)
10 #define BOOST_SPIRIT_OUTPUT_UTREE_TRAITS_APR_16_2010_0655AM
11
12 #include <boost/spirit/home/support/attributes.hpp>
13 #include <boost/spirit/home/support/container.hpp>
14 #include <boost/spirit/home/support/utree.hpp>
15 #include <boost/spirit/home/qi/domain.hpp>
16 #include <boost/spirit/home/karma/domain.hpp>
17 #include <boost/spirit/home/qi/nonterminal/nonterminal_fwd.hpp>
18 #include <boost/spirit/home/karma/nonterminal/nonterminal_fwd.hpp>
19
20 #include <string>
21
22 #include <boost/cstdint.hpp>
23 #include <boost/variant.hpp>
24 #include <boost/range/iterator_range.hpp>
25 #include <boost/mpl/bool.hpp>
26 #include <boost/mpl/identity.hpp>
27 #include <boost/mpl/or.hpp>
28 #include <boost/type_traits/is_same.hpp>
29 #include <boost/utility/enable_if.hpp>
30
31 ///////////////////////////////////////////////////////////////////////////////
32 namespace boost
33 {
34 template <typename T>
35 inline T get(boost::spirit::utree const& x)
36 {
37 return x.get<T>();
38 }
39 }
40
41 ///////////////////////////////////////////////////////////////////////////////
42 namespace boost { namespace spirit { namespace traits
43 {
44 namespace detail
45 {
46 inline bool is_list(utree const& ut)
47 {
48 switch (traits::which(ut))
49 {
50 case utree_type::reference_type:
51 return is_list(ut.deref());
52
53 case utree_type::list_type:
54 case utree_type::range_type:
55 return true;
56
57 default:
58 break;
59 }
60 return false;
61 }
62
63 inline bool is_uninitialized(utree const& ut)
64 {
65 return traits::which(ut) == utree_type::invalid_type;
66 }
67 }
68
69 // this specialization tells Spirit how to extract the type of the value
70 // stored in the given utree node
71 template <>
72 struct variant_which<utree>
73 {
74 static int call(utree const& u) { return u.which(); }
75 };
76
77 template <>
78 struct variant_which<utree::list_type>
79 {
80 static int call(utree::list_type const& u) { return u.which(); }
81 };
82
83 ///////////////////////////////////////////////////////////////////////////
84 // Make sure all components of an alternative expose utree, even if they
85 // actually expose a utree::list_type
86 template <typename Domain>
87 struct alternative_attribute_transform<utree::list_type, Domain>
88 : mpl::identity<utree>
89 {};
90
91 ///////////////////////////////////////////////////////////////////////////
92 // Make sure all components of a sequence expose utree, even if they
93 // actually expose a utree::list_type
94 template <typename Domain>
95 struct sequence_attribute_transform<utree::list_type, Domain>
96 : mpl::identity<utree>
97 {};
98
99 ///////////////////////////////////////////////////////////////////////////
100 // this specialization lets Spirit know that typed basic_strings
101 // are strings
102 template <typename Base, utree_type::info I>
103 struct is_string<spirit::basic_string<Base, I> >
104 : mpl::true_
105 {};
106
107 ///////////////////////////////////////////////////////////////////////////
108 // these specializations extract the character type of a utree typed string
109 template <typename T, utree_type::info I>
110 struct char_type_of<spirit::basic_string<iterator_range<T>, I> >
111 : char_type_of<T>
112 {};
113
114 template <utree_type::info I>
115 struct char_type_of<spirit::basic_string<std::string, I> >
116 : mpl::identity<char>
117 {};
118
119 ///////////////////////////////////////////////////////////////////////////
120 // these specializations extract a c string from a utree typed string
121 template <typename String>
122 struct extract_c_string;
123
124 template <typename T, utree_type::info I>
125 struct extract_c_string<
126 spirit::basic_string<iterator_range<T const*>, I>
127 > {
128 typedef T char_type;
129
130 typedef spirit::basic_string<iterator_range<T const*>, I> string;
131
132 static T const* call (string& s)
133 {
134 return s.begin();
135 }
136
137 static T const* call (string const& s)
138 {
139 return s.begin();
140 }
141 };
142
143 template <utree_type::info I>
144 struct extract_c_string<spirit::basic_string<std::string, I> >
145 {
146 typedef char char_type;
147
148 typedef spirit::basic_string<std::string, I> string;
149
150 static char const* call (string& s)
151 {
152 return s.c_str();
153 }
154
155 static char const* call (string const& s)
156 {
157 return s.c_str();
158 }
159 };
160
161 ///////////////////////////////////////////////////////////////////////////
162 // these specializations are needed because utree::value_type == utree
163 template <>
164 struct is_substitute<utree, utree>
165 : mpl::true_
166 {};
167
168 template <>
169 struct is_weak_substitute<utree, utree>
170 : mpl::true_
171 {};
172
173 template <>
174 struct is_substitute<utree::list_type, utree::list_type>
175 : mpl::true_
176 {};
177
178 template <>
179 struct is_weak_substitute<utree::list_type, utree::list_type>
180 : mpl::true_
181 {};
182
183 ///////////////////////////////////////////////////////////////////////////
184 // this specialization tells Spirit.Qi to allow assignment to an utree from
185 // a variant
186 namespace detail
187 {
188 struct assign_to_utree_visitor : static_visitor<>
189 {
190 assign_to_utree_visitor(utree& ut) : ut_(ut) {}
191
192 template <typename T>
193 void operator()(T& val) const
194 {
195 ut_ = val;
196 }
197
198 utree& ut_;
199 };
200 }
201
202 template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
203 struct assign_to_container_from_value<
204 utree, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
205 {
206 static void
207 call(variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& val, utree& attr)
208 {
209 apply_visitor(detail::assign_to_utree_visitor(attr), val);
210 }
211 };
212
213 ///////////////////////////////////////////////////////////////////////////
214 // this specialization tells Spirit.Qi to allow assignment to an utree from
215 // a STL container
216 template <typename Attribute>
217 struct assign_to_container_from_value<utree, Attribute>
218 {
219 // any non-container type will be either directly assigned or appended
220 static void call(Attribute const& val, utree& attr, mpl::false_)
221 {
222 if (attr.empty())
223 attr = val;
224 else
225 push_back(attr, val);
226 }
227
228 // any container type will be converted into a list_type utree
229 static void call(Attribute const& val, utree& attr, mpl::true_)
230 {
231 typedef typename traits::container_iterator<Attribute const>::type
232 iterator_type;
233
234 // make sure the attribute is a list, at least an empty one
235 if (attr.empty())
236 attr = empty_list;
237
238 iterator_type end = traits::end(val);
239 for (iterator_type i = traits::begin(val); i != end; traits::next(i))
240 push_back(attr, traits::deref(i));
241 }
242
243 static void call(Attribute const& val, utree& attr)
244 {
245 call(val, attr, is_container<Attribute>());
246 }
247 };
248
249 ///////////////////////////////////////////////////////////////////////////
250 // this specialization is required to disambiguate the specializations
251 // related to utree
252 template <>
253 struct assign_to_container_from_value<utree, utree>
254 {
255 static void call(utree const& val, utree& attr)
256 {
257 if (attr.empty()) {
258 attr = val;
259 }
260 else if (detail::is_list(val)) {
261 typedef utree::const_iterator iterator_type;
262
263 iterator_type end = traits::end(val);
264 for (iterator_type i = traits::begin(val); i != end; traits::next(i))
265 push_back(attr, traits::deref(i));
266 }
267 else {
268 push_back(attr, val);
269 }
270 }
271 };
272
273 template <>
274 struct assign_to_container_from_value<utree, utree::list_type>
275 : assign_to_container_from_value<utree, utree>
276 {};
277
278 // If the destination is a utree_list, we need to force the right hand side
279 // value into a new sub-node, always, no questions asked.
280 template <>
281 struct assign_to_container_from_value<utree::list_type, utree>
282 {
283 static void call(utree const& val, utree& attr)
284 {
285 push_back(attr, val);
286 }
287 };
288
289 // If both, the right hand side and the left hand side are utree_lists
290 // we have a lhs rule which has a single rule exposing a utree_list as its
291 // rhs (optionally wrapped into a directive or other unary parser). In this
292 // case we do not create a new sub-node.
293 template <>
294 struct assign_to_container_from_value<utree::list_type, utree::list_type>
295 : assign_to_container_from_value<utree, utree>
296 {};
297
298 ///////////////////////////////////////////////////////////////////////////
299 // this specialization makes sure strings get assigned as a whole and are
300 // not converted into a utree list
301 template <>
302 struct assign_to_container_from_value<utree, utf8_string_type>
303 {
304 static void call(utf8_string_type const& val, utree& attr)
305 {
306 if (attr.empty())
307 attr = val;
308 else
309 push_back(attr, val);
310 }
311 };
312
313 // this specialization keeps symbols from being transformed into strings
314 template<>
315 struct assign_to_container_from_value<utree, utf8_symbol_type>
316 {
317 static void call (utf8_symbol_type const& val, utree& attr)
318 {
319 if (attr.empty())
320 attr = val;
321 else
322 push_back(attr, val);
323 }
324 };
325
326 template <>
327 struct assign_to_container_from_value<utree, binary_string_type>
328 {
329 static void call(binary_string_type const& val, utree& attr)
330 {
331 if (attr.empty())
332 attr = val;
333 else
334 push_back(attr, val);
335 }
336 };
337
338 template<>
339 struct assign_to_container_from_value<utree, utf8_symbol_range_type>
340 {
341 static void call (utf8_symbol_range_type const& val, utree& attr)
342 {
343 if (attr.empty())
344 attr = val;
345 else
346 push_back(attr, val);
347 }
348 };
349
350 template <>
351 struct assign_to_container_from_value<utree, binary_range_type>
352 {
353 static void call(binary_range_type const& val, utree& attr)
354 {
355 if (attr.empty())
356 attr = val;
357 else
358 push_back(attr, val);
359 }
360 };
361
362 template <>
363 struct assign_to_container_from_value<utree, std::string>
364 {
365 static void call(std::string const& val, utree& attr)
366 {
367 if (attr.empty())
368 attr = val;
369 else
370 push_back(attr, val);
371 }
372 };
373
374 ///////////////////////////////////////////////////////////////////////////
375 // this specialization tells Spirit.Qi to allow assignment to an utree from
376 // generic iterators
377 template <typename Iterator>
378 struct assign_to_attribute_from_iterators<utree, Iterator>
379 {
380 static void
381 call(Iterator const& first, Iterator const& last, utree& attr)
382 {
383 if (attr.empty())
384 attr.assign(first, last);
385 else {
386 for (Iterator i = first; i != last; ++i)
387 push_back(attr, traits::deref(i));
388 }
389 }
390 };
391
392 ///////////////////////////////////////////////////////////////////////////
393 // Karma only: convert utree node to string
394 namespace detail
395 {
396 struct attribute_as_string_type
397 {
398 typedef utf8_string_range_type type;
399
400 static type call(utree const& attr)
401 {
402 return boost::get<utf8_string_range_type>(attr);
403 }
404
405 static bool is_valid(utree const& attr)
406 {
407 switch (traits::which(attr))
408 {
409 case utree_type::reference_type:
410 return is_valid(attr.deref());
411
412 case utree_type::string_range_type:
413 case utree_type::string_type:
414 return true;
415
416 default:
417 return false;
418 }
419 }
420 };
421 }
422
423 template <>
424 struct attribute_as<std::string, utree>
425 : detail::attribute_as_string_type
426 {};
427
428 template <>
429 struct attribute_as<utf8_string_type, utree>
430 : detail::attribute_as_string_type
431 {};
432
433 template <>
434 struct attribute_as<utf8_string_range_type, utree>
435 : detail::attribute_as_string_type
436 {};
437
438 ///////////////////////////////////////////////////////////////////////////
439 namespace detail
440 {
441 struct attribute_as_symbol_type
442 {
443 typedef utf8_symbol_range_type type;
444
445 static type call(utree const& attr)
446 {
447 return boost::get<utf8_symbol_range_type>(attr);
448 }
449
450 static bool is_valid(utree const& attr)
451 {
452 switch (traits::which(attr))
453 {
454 case utree_type::reference_type:
455 return is_valid(attr.deref());
456
457 case utree_type::symbol_type:
458 return true;
459
460 default:
461 return false;
462 }
463 }
464 };
465 }
466
467 template <>
468 struct attribute_as<utf8_symbol_type, utree>
469 : detail::attribute_as_symbol_type
470 {};
471
472 template <>
473 struct attribute_as<utf8_symbol_range_type, utree>
474 : detail::attribute_as_symbol_type
475 {};
476
477 template <typename Attribute>
478 struct attribute_as<Attribute, utree::list_type>
479 : attribute_as<Attribute, utree>
480 {};
481
482 ///////////////////////////////////////////////////////////////////////////
483 namespace detail
484 {
485 struct attribute_as_binary_string_type
486 {
487 typedef binary_range_type type;
488
489 static type call(utree const& attr)
490 {
491 return boost::get<binary_range_type>(attr);
492 }
493
494 static bool is_valid(utree const& attr)
495 {
496 switch (traits::which(attr))
497 {
498 case utree_type::reference_type:
499 return is_valid(attr.deref());
500
501 case utree_type::binary_type:
502 return true;
503
504 default:
505 return false;
506 }
507 }
508 };
509 }
510
511 template <>
512 struct attribute_as<binary_string_type, utree>
513 : detail::attribute_as_binary_string_type
514 {};
515
516 template <>
517 struct attribute_as<binary_range_type, utree>
518 : detail::attribute_as_binary_string_type
519 {};
520
521 ///////////////////////////////////////////////////////////////////////////
522 // push_back support for utree
523 template <typename T>
524 struct push_back_container<utree, T>
525 {
526 static bool call(utree& c, T const& val)
527 {
528 switch (traits::which(c))
529 {
530 case utree_type::invalid_type:
531 case utree_type::nil_type:
532 case utree_type::list_type:
533 c.push_back(val);
534 break;
535
536 default:
537 {
538 utree ut;
539 ut.push_back(c);
540 ut.push_back(val);
541 c.swap(ut);
542 }
543 break;
544 }
545 return true;
546 }
547 };
548
549 template <typename T>
550 struct push_back_container<utree::list_type, T>
551 : push_back_container<utree, T>
552 {};
553
554 ///////////////////////////////////////////////////////////////////////////
555 // ensure the utree attribute is an empty list
556 template <>
557 struct make_container_attribute<utree>
558 {
559 static void call(utree& ut)
560 {
561 if (!detail::is_list(ut)) {
562 if (detail::is_uninitialized(ut))
563 ut = empty_list;
564 else {
565 utree retval (empty_list);
566 retval.push_back(ut);
567 ut.swap(retval);
568 }
569 }
570 }
571 };
572
573 template <>
574 struct make_container_attribute<utree::list_type>
575 : make_container_attribute<utree>
576 {};
577
578 ///////////////////////////////////////////////////////////////////////////
579 // an utree is a container on its own
580 template <>
581 struct build_std_vector<utree>
582 {
583 typedef utree type;
584 };
585
586 template <>
587 struct build_std_vector<utree::list_type>
588 {
589 typedef utree::list_type type;
590 };
591
592 ///////////////////////////////////////////////////////////////////////////
593 // debug support for utree
594 template <typename Out>
595 struct print_attribute_debug<Out, utree>
596 {
597 static void call(Out& out, utree const& val)
598 {
599 out << val;
600 }
601 };
602
603 ///////////////////////////////////////////////////////////////////////////
604 // force utree list attribute in a sequence to be dereferenced if a rule
605 // or a grammar exposes an utree as it's attribute
606 namespace detail
607 {
608 // Checks whether the exposed Attribute allows to handle utree or
609 // utree::list_type directly. Returning mpl::false_ from this meta
610 // function will force a new utree instance to be created for each
611 // invocation of the embedded parser.
612
613 // The purpose of using utree::list_type as an attribute is to force a
614 // new sub-node in the result.
615 template <typename Attribute, typename Enable = void>
616 struct handles_utree_list_container
617 : mpl::and_<
618 mpl::not_<is_same<utree::list_type, Attribute> >,
619 traits::is_container<Attribute> >
620 {};
621
622 // The following specializations make sure that the actual handling of
623 // an utree (or utree::list_type) attribute is deferred to the embedded
624 // parsers of a sequence, alternative or optional component.
625 template <typename Attribute>
626 struct handles_utree_list_container<Attribute
627 , typename enable_if<fusion::traits::is_sequence<Attribute> >::type>
628 : mpl::true_
629 {};
630
631 template <typename Attribute>
632 struct handles_utree_list_container<boost::optional<Attribute> >
633 : mpl::true_
634 {};
635
636 template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
637 struct handles_utree_list_container<
638 boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
639 : mpl::true_
640 {};
641 }
642
643 template <
644 typename IteratorA, typename IteratorB, typename Context
645 , typename T1, typename T2, typename T3, typename T4>
646 struct handles_container<qi::rule<IteratorA, T1, T2, T3, T4>
647 , utree, Context, IteratorB>
648 : detail::handles_utree_list_container<typename attribute_of<
649 qi::rule<IteratorA, T1, T2, T3, T4>, Context, IteratorB
650 >::type>
651 {};
652
653 template <
654 typename IteratorA, typename IteratorB, typename Context
655 , typename T1, typename T2, typename T3, typename T4>
656 struct handles_container<qi::grammar<IteratorA, T1, T2, T3, T4>
657 , utree, Context, IteratorB>
658 : detail::handles_utree_list_container<typename attribute_of<
659 qi::grammar<IteratorA, T1, T2, T3, T4>, Context, IteratorB
660 >::type>
661 {};
662
663 template <
664 typename IteratorA, typename IteratorB, typename Context
665 , typename T1, typename T2, typename T3, typename T4>
666 struct handles_container<qi::rule<IteratorA, T1, T2, T3, T4>
667 , utree::list_type, Context, IteratorB>
668 : detail::handles_utree_list_container<typename attribute_of<
669 qi::rule<IteratorA, T1, T2, T3, T4>, Context, IteratorB
670 >::type>
671 {};
672
673 template <
674 typename IteratorA, typename IteratorB, typename Context
675 , typename T1, typename T2, typename T3, typename T4>
676 struct handles_container<qi::grammar<IteratorA, T1, T2, T3, T4>
677 , utree::list_type, Context, IteratorB>
678 : detail::handles_utree_list_container<typename attribute_of<
679 qi::grammar<IteratorA, T1, T2, T3, T4>, Context, IteratorB
680 >::type>
681 {};
682
683 ///////////////////////////////////////////////////////////////////////////
684 template <typename Attribute, typename Sequence>
685 struct pass_through_container<
686 utree, utree, Attribute, Sequence, qi::domain>
687 : detail::handles_utree_list_container<Attribute>
688 {};
689
690 template <typename Attribute, typename Sequence>
691 struct pass_through_container<
692 utree::list_type, utree, Attribute, Sequence, qi::domain>
693 : detail::handles_utree_list_container<Attribute>
694 {};
695
696 ///////////////////////////////////////////////////////////////////////////
697 namespace detail
698 {
699 // Checks whether the exposed Attribute allows to handle utree or
700 // utree::list_type directly. Returning mpl::false_ from this meta
701 // function will force a new utree instance to be created for each
702 // invocation of the embedded parser.
703
704 // The purpose of using utree::list_type as an attribute is to force a
705 // new sub-node in the result.
706 template <typename Attribute, typename Enable = void>
707 struct handles_utree_container
708 : mpl::and_<
709 mpl::not_<is_same<utree, Attribute> >,
710 traits::is_container<Attribute> >
711 {};
712
713 // The following specializations make sure that the actual handling of
714 // an utree (or utree::list_type) attribute is deferred to the embedded
715 // parsers of a sequence, alternative or optional component.
716 template <typename Attribute>
717 struct handles_utree_container<Attribute
718 , typename enable_if<fusion::traits::is_sequence<Attribute> >::type>
719 : mpl::true_
720 {};
721
722 template <typename Attribute>
723 struct handles_utree_container<boost::optional<Attribute> >
724 : mpl::true_
725 {};
726
727 template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
728 struct handles_utree_container<
729 boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
730 : mpl::true_
731 {};
732 }
733
734 template <
735 typename IteratorA, typename IteratorB, typename Context
736 , typename T1, typename T2, typename T3, typename T4>
737 struct handles_container<karma::rule<IteratorA, T1, T2, T3, T4>
738 , utree, Context, IteratorB>
739 : detail::handles_utree_container<typename attribute_of<
740 karma::rule<IteratorA, T1, T2, T3, T4>, Context, IteratorB
741 >::type>
742 {};
743
744 template <
745 typename IteratorA, typename IteratorB, typename Context
746 , typename T1, typename T2, typename T3, typename T4>
747 struct handles_container<karma::grammar<IteratorA, T1, T2, T3, T4>
748 , utree, Context, IteratorB>
749 : detail::handles_utree_container<typename attribute_of<
750 karma::grammar<IteratorA, T1, T2, T3, T4>, Context, IteratorB
751 >::type>
752 {};
753
754 ///////////////////////////////////////////////////////////////////////////
755 template <typename Attribute, typename Sequence>
756 struct pass_through_container<
757 utree, utree, Attribute, Sequence, karma::domain>
758 : detail::handles_utree_container<Attribute>
759 {};
760
761 ///////////////////////////////////////////////////////////////////////////
762 // the specialization below tells Spirit how to handle utree if it is used
763 // with an optional component
764 template <>
765 struct optional_attribute<utree>
766 {
767 typedef utree const& type;
768
769 static type call(utree const& val)
770 {
771 return val;
772 }
773
774 // only 'invalid_type' utree nodes are not valid
775 static bool is_valid(utree const& val)
776 {
777 return !detail::is_uninitialized(val);
778 }
779 };
780
781 template <>
782 struct build_optional<utree>
783 {
784 typedef utree type;
785 };
786
787 template <>
788 struct build_optional<utree::list_type>
789 {
790 typedef utree::list_type type;
791 };
792
793 // an utree is an optional (in any domain)
794 template <>
795 struct not_is_optional<utree, qi::domain>
796 : mpl::false_
797 {};
798
799 template <>
800 struct not_is_optional<utree::list_type, qi::domain>
801 : mpl::false_
802 {};
803
804 template <>
805 struct not_is_optional<utree, karma::domain>
806 : mpl::false_
807 {};
808
809 template <>
810 struct not_is_optional<utree::list_type, karma::domain>
811 : mpl::false_
812 {};
813
814 ///////////////////////////////////////////////////////////////////////////
815 // the specialization below tells Spirit to handle utree as if it
816 // where a 'real' variant (in the context of karma)
817 template <>
818 struct not_is_variant<utree, karma::domain>
819 : mpl::false_
820 {};
821
822 template <>
823 struct not_is_variant<utree::list_type, karma::domain>
824 : mpl::false_
825 {};
826
827 // The specializations below tell Spirit to verify whether an attribute
828 // type is compatible with a given variant type
829 template <>
830 struct compute_compatible_component_variant<
831 utree, iterator_range<utree::iterator> >
832 : mpl::true_
833 {
834 typedef iterator_range<utree::iterator> compatible_type;
835
836 static bool is_compatible(int d)
837 {
838 return d == utree_type::list_type;
839 }
840 };
841
842 template <>
843 struct compute_compatible_component_variant<
844 utree, iterator_range<utree::const_iterator> >
845 : mpl::true_
846 {
847 typedef iterator_range<utree::const_iterator> compatible_type;
848
849 static bool is_compatible(int d)
850 {
851 return d == utree_type::list_type;
852 }
853 };
854
855 template <>
856 struct compute_compatible_component_variant<utree, utree::invalid_type>
857 : mpl::true_
858 {
859 typedef utree::invalid_type compatible_type;
860
861 static bool is_compatible(int d)
862 {
863 return d == utree_type::invalid_type;
864 }
865 };
866
867 template <>
868 struct compute_compatible_component_variant<utree, utree::nil_type>
869 : mpl::true_
870 {
871 typedef utree::nil_type compatible_type;
872
873 static bool is_compatible(int d)
874 {
875 return d == utree_type::nil_type;
876 }
877 };
878
879 template <>
880 struct compute_compatible_component_variant<utree, bool>
881 : mpl::true_
882 {
883 typedef bool compatible_type;
884
885 static bool is_compatible(int d)
886 {
887 return d == utree_type::bool_type;
888 }
889 };
890
891 template <>
892 struct compute_compatible_component_variant<utree, int>
893 : mpl::true_
894 {
895 typedef int compatible_type;
896
897 static bool is_compatible(int d)
898 {
899 return d == utree_type::int_type;
900 }
901 };
902
903 template <>
904 struct compute_compatible_component_variant<utree, double>
905 : mpl::true_
906 {
907 typedef double compatible_type;
908
909 static bool is_compatible(int d)
910 {
911 return d == utree_type::double_type;
912 }
913 };
914
915 template <>
916 struct compute_compatible_component_variant<
917 utree, utf8_string_range_type>
918 : mpl::true_
919 {
920 typedef utf8_string_range_type compatible_type;
921
922 static bool is_compatible(int d)
923 {
924 return d == utree_type::string_type;
925 }
926 };
927
928 template <>
929 struct compute_compatible_component_variant<
930 utree, utf8_string_type>
931 : mpl::true_
932 {
933 typedef utf8_string_type compatible_type;
934
935 static bool is_compatible(int d)
936 {
937 return d == utree_type::string_type;
938 }
939 };
940
941 template <>
942 struct compute_compatible_component_variant<
943 utree, utf8_symbol_range_type>
944 : mpl::true_
945 {
946 typedef utf8_symbol_range_type compatible_type;
947
948 static bool is_compatible(int d)
949 {
950 return d == utree_type::symbol_type;
951 }
952 };
953
954 template <>
955 struct compute_compatible_component_variant<
956 utree, utf8_symbol_type>
957 : mpl::true_
958 {
959 typedef utf8_symbol_type compatible_type;
960
961 static bool is_compatible(int d)
962 {
963 return d == utree_type::symbol_type;
964 }
965 };
966
967 template <>
968 struct compute_compatible_component_variant<
969 utree, binary_range_type>
970 : mpl::true_
971 {
972 typedef binary_range_type compatible_type;
973
974 static bool is_compatible(int d)
975 {
976 return d == utree_type::binary_type;
977 }
978 };
979
980 template <>
981 struct compute_compatible_component_variant<
982 utree, binary_string_type>
983 : mpl::true_
984 {
985 typedef binary_string_type compatible_type;
986
987 static bool is_compatible(int d)
988 {
989 return d == utree_type::binary_type;
990 }
991 };
992
993 template <>
994 struct compute_compatible_component_variant<utree, utree>
995 : mpl::true_
996 {
997 typedef utree compatible_type;
998
999 static bool is_compatible(int d)
1000 {
1001 return d >= utree_type::invalid_type &&
1002 d <= utree_type::reference_type;
1003 }
1004 };
1005
1006 template <>
1007 struct compute_compatible_component_variant<
1008 utree, std::vector<utree> >
1009 : mpl::true_
1010 {
1011 typedef utree compatible_type;
1012
1013 static bool is_compatible(int d)
1014 {
1015 return d >= utree_type::invalid_type &&
1016 d <= utree_type::reference_type;
1017 }
1018 };
1019
1020 template <typename Sequence>
1021 struct compute_compatible_component_variant<utree, Sequence
1022 , mpl::false_
1023 , typename enable_if<fusion::traits::is_sequence<Sequence> >::type>
1024 : mpl::true_
1025 {
1026 typedef iterator_range<utree::const_iterator> compatible_type;
1027
1028 static bool is_compatible(int d)
1029 {
1030 return d == utree_type::list_type;
1031 }
1032 };
1033
1034 template <typename Attribute>
1035 struct compute_compatible_component_variant<utree::list_type, Attribute>
1036 : compute_compatible_component_variant<utree, Attribute>
1037 {};
1038
1039 ///////////////////////////////////////////////////////////////////////////
1040 template <>
1041 struct symbols_lookup<utree, utf8_symbol_type>
1042 {
1043 typedef std::string type;
1044
1045 static type call(utree const& t)
1046 {
1047 utf8_symbol_range_type r = boost::get<utf8_symbol_range_type>(t);
1048 return std::string(traits::begin(r), traits::end(r));
1049 }
1050 };
1051
1052 template <>
1053 struct symbols_lookup<utf8_symbol_type, utf8_symbol_type>
1054 {
1055 typedef std::string type;
1056
1057 static type call(utf8_symbol_type const& t)
1058 {
1059 return t;
1060 }
1061 };
1062
1063 ///////////////////////////////////////////////////////////////////////////
1064 namespace detail
1065 {
1066 template <typename T>
1067 inline T get_or_deref(utree const& t)
1068 {
1069 if (detail::is_list(t))
1070 return boost::get<T>(t.front());
1071 return boost::get<T>(t);
1072 }
1073 }
1074
1075 template <>
1076 struct extract_from_container<utree, utree::nil_type>
1077 {
1078 typedef utree::nil_type type;
1079
1080 template <typename Context>
1081 static type call(utree const&, Context&)
1082 {
1083 return nil;
1084 }
1085 };
1086
1087 template <>
1088 struct extract_from_container<utree, char>
1089 {
1090 typedef char type;
1091
1092 template <typename Context>
1093 static type call(utree const& t, Context&)
1094 {
1095 utf8_symbol_range_type r = detail::get_or_deref<utf8_symbol_range_type>(t);
1096 return r.front();
1097 }
1098 };
1099
1100 template <>
1101 struct extract_from_container<utree, bool>
1102 {
1103 typedef bool type;
1104
1105 template <typename Context>
1106 static type call(utree const& t, Context&)
1107 {
1108 return detail::get_or_deref<bool>(t);
1109 }
1110 };
1111
1112 template <>
1113 struct extract_from_container<utree, int>
1114 {
1115 typedef int type;
1116
1117 template <typename Context>
1118 static type call(utree const& t, Context&)
1119 {
1120 return detail::get_or_deref<int>(t);
1121 }
1122 };
1123
1124 template <>
1125 struct extract_from_container<utree, double>
1126 {
1127 typedef double type;
1128
1129 template <typename Context>
1130 static type call(utree const& t, Context&)
1131 {
1132 return detail::get_or_deref<double>(t);
1133 }
1134 };
1135
1136 template <typename Traits, typename Alloc>
1137 struct extract_from_container<utree, std::basic_string<char, Traits, Alloc> >
1138 {
1139 typedef std::basic_string<char, Traits, Alloc> type;
1140
1141 template <typename Context>
1142 static type call(utree const& t, Context&)
1143 {
1144 utf8_string_range_type r = detail::get_or_deref<utf8_string_range_type>(t);
1145 return type(traits::begin(r), traits::end(r));
1146 }
1147 };
1148
1149 template <>
1150 struct extract_from_container<utree, utf8_symbol_type>
1151 {
1152 typedef utf8_symbol_type type;
1153
1154 template <typename Context>
1155 static type call(utree const& t, Context&)
1156 {
1157 utf8_symbol_range_type r = detail::get_or_deref<utf8_symbol_range_type>(t);
1158 return type(traits::begin(r), traits::end(r));
1159 }
1160 };
1161
1162 template <>
1163 struct extract_from_container<utree, utf8_string_type>
1164 {
1165 typedef utf8_string_type type;
1166
1167 template <typename Context>
1168 static type call(utree const& t, Context&)
1169 {
1170 utf8_string_range_type r = detail::get_or_deref<utf8_string_range_type>(t);
1171 return type(traits::begin(r), traits::end(r));
1172 }
1173 };
1174
1175 ///////////////////////////////////////////////////////////////////////////
1176 template <>
1177 struct transform_attribute<utree const, utree::nil_type, karma::domain>
1178 {
1179 typedef utree::nil_type type;
1180
1181 static type pre(utree const&)
1182 {
1183 return nil;
1184 }
1185 };
1186
1187 template <>
1188 struct transform_attribute<utree const, char, karma::domain>
1189 {
1190 typedef char type;
1191
1192 static type pre(utree const& t)
1193 {
1194 utf8_string_range_type r = detail::get_or_deref<utf8_string_range_type>(t);
1195 return r.front();
1196 }
1197 };
1198
1199 template <>
1200 struct transform_attribute<utree const, bool, karma::domain>
1201 {
1202 typedef bool type;
1203
1204 static type pre(utree const& t)
1205 {
1206 return detail::get_or_deref<bool>(t);
1207 }
1208 };
1209
1210 template <>
1211 struct transform_attribute<utree const, int, karma::domain>
1212 {
1213 typedef int type;
1214
1215 static type pre(utree const& t)
1216 {
1217 return detail::get_or_deref<int>(t);
1218 }
1219 };
1220
1221 template <>
1222 struct transform_attribute<utree const, double, karma::domain>
1223 {
1224 typedef double type;
1225
1226 static type pre(utree const& t)
1227 {
1228 return detail::get_or_deref<double>(t);
1229 }
1230 };
1231
1232 template <typename Traits, typename Alloc>
1233 struct transform_attribute<
1234 utree const, std::basic_string<char, Traits, Alloc>, karma::domain>
1235 {
1236 typedef std::basic_string<char, Traits, Alloc> type;
1237
1238 static type pre(utree const& t)
1239 {
1240 utf8_string_range_type r = detail::get_or_deref<utf8_string_range_type>(t);
1241 return type(traits::begin(r), traits::end(r));
1242 }
1243 };
1244
1245 // this specialization is used whenever a utree is passed to a rule as part
1246 // of a sequence
1247 template <typename Iterator>
1248 struct transform_attribute<
1249 iterator_range<Iterator> const, utree, karma::domain>
1250 {
1251 typedef utree type;
1252
1253 static type pre(iterator_range<Iterator> const& t)
1254 {
1255 // return utree the begin iterator points to
1256 Iterator it = boost::begin(t);
1257 utree result(boost::ref(*it));
1258 ++it;
1259 return result;
1260 }
1261 };
1262
1263 ///////////////////////////////////////////////////////////////////////////
1264 template <>
1265 struct transform_attribute<utree const, utf8_string_type, karma::domain>
1266 {
1267 typedef utf8_string_type type;
1268
1269 static type pre(utree const& t)
1270 {
1271 utf8_string_range_type r = detail::get_or_deref<utf8_string_range_type>(t);
1272 return type(traits::begin(r), traits::end(r));
1273 }
1274 };
1275
1276 template <>
1277 struct transform_attribute<utree const, utf8_symbol_type, karma::domain>
1278 {
1279 typedef utf8_symbol_type type;
1280
1281 static type pre(utree const& t)
1282 {
1283 utf8_symbol_range_type r = detail::get_or_deref<utf8_symbol_range_type>(t);
1284 return type(traits::begin(r), traits::end(r));
1285 }
1286 };
1287
1288 template <typename Attribute>
1289 struct transform_attribute<utree::list_type const, Attribute, karma::domain>
1290 : transform_attribute<utree const, Attribute, karma::domain>
1291 {};
1292 }}}
1293
1294 #endif