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 plain data types 71 template <typename T_> callboost::spirit::x3::traits::print_attribute_debug72 static void call(Out& out, T_ const& val, unused_attribute) 73 { 74 out << "unused"; 75 } 76 77 // for plain data types 78 template <typename T_> callboost::spirit::x3::traits::print_attribute_debug79 static void call(Out& out, T_ const& val, plain_attribute) 80 { 81 out << val; 82 } 83 84 // for fusion data types 85 template <typename T_> callboost::spirit::x3::traits::print_attribute_debug86 static void call(Out& out, T_ const& val, tuple_attribute) 87 { 88 out << '['; 89 fusion::for_each(val, detail::print_fusion_sequence<Out>(out)); 90 out << ']'; 91 } 92 93 // stl container 94 template <typename T_> callboost::spirit::x3::traits::print_attribute_debug95 static void call(Out& out, T_ const& val, container_attribute) 96 { 97 out << '['; 98 if (!traits::is_empty(val)) 99 { 100 bool first = true; 101 typename container_iterator<T_ const>::type iend = traits::end(val); 102 for (typename container_iterator<T_ const>::type i = traits::begin(val); 103 !traits::compare(i, iend); traits::next(i)) 104 { 105 if (!first) 106 out << ", "; 107 first = false; 108 x3::traits::print_attribute(out, traits::deref(i)); 109 } 110 } 111 out << ']'; 112 } 113 114 // for variant types 115 template <typename T_> callboost::spirit::x3::traits::print_attribute_debug116 static void call(Out& out, T_ const& val, variant_attribute) 117 { 118 apply_visitor(detail::print_visitor<Out>(out), val); 119 } 120 121 // for optional types 122 template <typename T_> callboost::spirit::x3::traits::print_attribute_debug123 static void call(Out& out, T_ const& val, optional_attribute) 124 { 125 if (val) 126 x3::traits::print_attribute(out, *val); 127 else 128 out << "[empty]"; 129 } 130 131 // main entry point callboost::spirit::x3::traits::print_attribute_debug132 static void call(Out& out, T const& val) 133 { 134 call(out, val, typename attribute_category<T>::type()); 135 } 136 }; 137 138 /////////////////////////////////////////////////////////////////////////// 139 template <typename Out, typename T> print_attribute(Out & out,T const & val)140 inline void print_attribute(Out& out, T const& val) 141 { 142 print_attribute_debug<Out, T>::call(out, val); 143 } 144 }}}} 145 146 #endif 147