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>
get(boost::spirit::utree const & x)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     {
is_list(utree const & ut)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 
is_uninitialized(utree const & ut)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     {
callboost::spirit::traits::variant_which74         static int call(utree const& u) { return u.which(); }
75     };
76 
77     template <>
78     struct variant_which<utree::list_type>
79     {
callboost::spirit::traits::variant_which80         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 
callboost::spirit::traits::extract_c_string132         static T const* call (string& s)
133         {
134             return s.begin();
135         }
136 
callboost::spirit::traits::extract_c_string137         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 
callboost::spirit::traits::extract_c_string150         static char const* call (string& s)
151         {
152             return s.c_str();
153         }
154 
callboost::spirit::traits::extract_c_string155         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         {
assign_to_utree_visitorboost::spirit::traits::detail::assign_to_utree_visitor190             assign_to_utree_visitor(utree& ut) : ut_(ut) {}
191 
192             template <typename T>
operator ()boost::spirit::traits::detail::assign_to_utree_visitor193             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
callboost::spirit::traits::assign_to_container_from_value207         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
callboost::spirit::traits::assign_to_container_from_value220         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
callboost::spirit::traits::assign_to_container_from_value229         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 
callboost::spirit::traits::assign_to_container_from_value243         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     {
callboost::spirit::traits::assign_to_container_from_value255         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     {
callboost::spirit::traits::assign_to_container_from_value283         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     {
callboost::spirit::traits::assign_to_container_from_value304         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     {
callboost::spirit::traits::assign_to_container_from_value317         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     {
callboost::spirit::traits::assign_to_container_from_value329         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     {
callboost::spirit::traits::assign_to_container_from_value341         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     {
callboost::spirit::traits::assign_to_container_from_value353         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     {
callboost::spirit::traits::assign_to_container_from_value365         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
callboost::spirit::traits::assign_to_attribute_from_iterators381         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 
callboost::spirit::traits::detail::attribute_as_string_type400             static type call(utree const& attr)
401             {
402                 return boost::get<utf8_string_range_type>(attr);
403             }
404 
is_validboost::spirit::traits::detail::attribute_as_string_type405             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 
callboost::spirit::traits::detail::attribute_as_symbol_type445             static type call(utree const& attr)
446             {
447                 return boost::get<utf8_symbol_range_type>(attr);
448             }
449 
is_validboost::spirit::traits::detail::attribute_as_symbol_type450             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 
callboost::spirit::traits::detail::attribute_as_binary_string_type489             static type call(utree const& attr)
490             {
491                 return boost::get<binary_range_type>(attr);
492             }
493 
is_validboost::spirit::traits::detail::attribute_as_binary_string_type494             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     {
callboost::spirit::traits::push_back_container526         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     {
callboost::spirit::traits::make_container_attribute559         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     {
callboost::spirit::traits::print_attribute_debug597         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 
callboost::spirit::traits::optional_attribute769         static type call(utree const& val)
770         {
771             return val;
772         }
773 
774         // only 'invalid_type' utree nodes are not valid
is_validboost::spirit::traits::optional_attribute775         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 
is_compatibleboost::spirit::traits::compute_compatible_component_variant836         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 
is_compatibleboost::spirit::traits::compute_compatible_component_variant849         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 
is_compatibleboost::spirit::traits::compute_compatible_component_variant861         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 
is_compatibleboost::spirit::traits::compute_compatible_component_variant873         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 
is_compatibleboost::spirit::traits::compute_compatible_component_variant885         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 
is_compatibleboost::spirit::traits::compute_compatible_component_variant897         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 
is_compatibleboost::spirit::traits::compute_compatible_component_variant909         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 
is_compatibleboost::spirit::traits::compute_compatible_component_variant922         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 
is_compatibleboost::spirit::traits::compute_compatible_component_variant935         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 
is_compatibleboost::spirit::traits::compute_compatible_component_variant948         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 
is_compatibleboost::spirit::traits::compute_compatible_component_variant961         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 
is_compatibleboost::spirit::traits::compute_compatible_component_variant974         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 
is_compatibleboost::spirit::traits::compute_compatible_component_variant987         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 
is_compatibleboost::spirit::traits::compute_compatible_component_variant999         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 
is_compatibleboost::spirit::traits::compute_compatible_component_variant1013         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 
is_compatibleboost::spirit::traits::compute_compatible_component_variant1028         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 
callboost::spirit::traits::symbols_lookup1045         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 
callboost::spirit::traits::symbols_lookup1057         static type call(utf8_symbol_type const& t)
1058         {
1059             return t;
1060         }
1061     };
1062 
1063     ///////////////////////////////////////////////////////////////////////////
1064     namespace detail
1065     {
1066         template <typename T>
get_or_deref(utree const & 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>
callboost::spirit::traits::extract_from_container1081         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>
callboost::spirit::traits::extract_from_container1093         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>
callboost::spirit::traits::extract_from_container1106         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>
callboost::spirit::traits::extract_from_container1118         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>
callboost::spirit::traits::extract_from_container1130         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>
callboost::spirit::traits::extract_from_container1142         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>
callboost::spirit::traits::extract_from_container1155         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>
callboost::spirit::traits::extract_from_container1168         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 
preboost::spirit::traits::transform_attribute1181         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 
preboost::spirit::traits::transform_attribute1192         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 
preboost::spirit::traits::transform_attribute1204         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 
preboost::spirit::traits::transform_attribute1215         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 
preboost::spirit::traits::transform_attribute1226         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 
preboost::spirit::traits::transform_attribute1238         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 
preboost::spirit::traits::karma::domain1253         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 
preboost::spirit::traits::transform_attribute1269         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 
preboost::spirit::traits::transform_attribute1281         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
1295