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