• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*=============================================================================
2     Copyright (c) 2001-2014 Joel de Guzman
3     Copyright (c) 2001-2011 Hartmut Kaiser
4 
5     Distributed under the Boost Software License, Version 1.0. (See accompanying
6     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 ================================================_==============================*/
8 #if !defined(BOOST_SPIRIT_X3_PRINT_ATTRIBUTE_JANUARY_20_2013_0814AM)
9 #define BOOST_SPIRIT_X3_PRINT_ATTRIBUTE_JANUARY_20_2013_0814AM
10 
11 #include <boost/variant.hpp>
12 #include <boost/optional/optional.hpp>
13 #include <boost/fusion/include/is_sequence.hpp>
14 #include <boost/fusion/include/for_each.hpp>
15 #include <boost/spirit/home/x3/support/traits/attribute_category.hpp>
16 #include <boost/spirit/home/x3/support/traits/is_variant.hpp>
17 
18 namespace boost { namespace spirit { namespace x3 { namespace traits
19 {
20     template <typename Out, typename T>
21     void print_attribute(Out& out, T const& val);
22 
23     template <typename Out>
print_attribute(Out &,unused_type)24     inline void print_attribute(Out&, unused_type) {}
25 
26     ///////////////////////////////////////////////////////////////////////////
27     namespace detail
28     {
29         template <typename Out>
30         struct print_fusion_sequence
31         {
print_fusion_sequenceboost::spirit::x3::traits::detail::print_fusion_sequence32             print_fusion_sequence(Out& out)
33               : out(out), is_first(true) {}
34 
35             typedef void result_type;
36 
37             template <typename T>
operator ()boost::spirit::x3::traits::detail::print_fusion_sequence38             void operator()(T const& val) const
39             {
40                 if (is_first)
41                     is_first = false;
42                 else
43                     out << ", ";
44                 x3::traits::print_attribute(out, val);
45             }
46 
47             Out& out;
48             mutable bool is_first;
49         };
50 
51         // print elements in a variant
52         template <typename Out>
53         struct print_visitor : static_visitor<>
54         {
print_visitorboost::spirit::x3::traits::detail::print_visitor55             print_visitor(Out& out) : out(out) {}
56 
57             template <typename T>
operator ()boost::spirit::x3::traits::detail::print_visitor58             void operator()(T const& val) const
59             {
60                 x3::traits::print_attribute(out, val);
61             }
62 
63             Out& out;
64         };
65     }
66 
67     template <typename Out, typename T, typename Enable = void>
68     struct print_attribute_debug
69     {
70         // for unused_type
callboost::spirit::x3::traits::print_attribute_debug71         static void call(Out& out, unused_type, unused_attribute)
72         {
73             out << "unused";
74         }
75 
76         // for plain data types
77         template <typename T_>
callboost::spirit::x3::traits::print_attribute_debug78         static void call(Out& out, T_ const& val, plain_attribute)
79         {
80             out << val;
81         }
82 
83         // for fusion data types
84         template <typename T_>
callboost::spirit::x3::traits::print_attribute_debug85         static void call(Out& out, T_ const& val, tuple_attribute)
86         {
87             out << '[';
88             fusion::for_each(val, detail::print_fusion_sequence<Out>(out));
89             out << ']';
90         }
91 
92         // stl container
93         template <typename T_>
callboost::spirit::x3::traits::print_attribute_debug94         static void call(Out& out, T_ const& val, container_attribute)
95         {
96             out << '[';
97             if (!traits::is_empty(val))
98             {
99                 bool first = true;
100                 typename container_iterator<T_ const>::type iend = traits::end(val);
101                 for (typename container_iterator<T_ const>::type i = traits::begin(val);
102                      !traits::compare(i, iend); traits::next(i))
103                 {
104                     if (!first)
105                         out << ", ";
106                     first = false;
107                     x3::traits::print_attribute(out, traits::deref(i));
108                 }
109             }
110             out << ']';
111         }
112 
113         // for variant types
114         template <typename T_>
callboost::spirit::x3::traits::print_attribute_debug115         static void call(Out& out, T_ const& val, variant_attribute)
116         {
117             apply_visitor(detail::print_visitor<Out>(out), val);
118         }
119 
120         // for optional types
121         template <typename T_>
callboost::spirit::x3::traits::print_attribute_debug122         static void call(Out& out, T_ const& val, optional_attribute)
123         {
124             if (val)
125                 x3::traits::print_attribute(out, *val);
126             else
127                 out << "[empty]";
128         }
129 
130         // main entry point
callboost::spirit::x3::traits::print_attribute_debug131         static void call(Out& out, T const& val)
132         {
133             call(out, val, typename attribute_category<T>::type());
134         }
135     };
136 
137     ///////////////////////////////////////////////////////////////////////////
138     template <typename Out, typename T>
print_attribute(Out & out,T const & val)139     inline void print_attribute(Out& out, T const& val)
140     {
141         print_attribute_debug<Out, T>::call(out, val);
142     }
143 }}}}
144 
145 #endif
146