1 /*============================================================================= 2 Copyright (c) 2001-2011 Joel de Guzman 3 4 Distributed under the Boost Software License, Version 1.0. (See accompanying 5 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 ==============================================================================*/ 7 #if !defined(BOOST_SPIRIT_INFO_NOVEMBER_22_2008_1132AM) 8 #define BOOST_SPIRIT_INFO_NOVEMBER_22_2008_1132AM 9 10 #if defined(_MSC_VER) 11 #pragma once 12 #endif 13 14 #include <boost/variant/variant.hpp> 15 #include <boost/variant/recursive_variant.hpp> 16 #include <boost/variant/apply_visitor.hpp> 17 #include <boost/foreach.hpp> 18 #include <boost/spirit/home/support/utf8.hpp> 19 #include <list> 20 #include <iterator> 21 #include <utility> 22 23 namespace boost { namespace spirit 24 { 25 // info provides information about a component. Each component 26 // has a what member function that returns an info object. 27 // strings in the info object are assumed to be encoded as UTF8 28 // for uniformity. 29 struct info 30 { 31 struct nil_ {}; 32 33 typedef 34 boost::variant< 35 nil_ 36 , utf8_string 37 , recursive_wrapper<info> 38 , recursive_wrapper<std::pair<info, info> > 39 , recursive_wrapper<std::list<info> > 40 > 41 value_type; 42 infoboost::spirit::info43 explicit info(utf8_string const& tag_) 44 : tag(tag_), value(nil_()) {} 45 46 template <typename T> infoboost::spirit::info47 info(utf8_string const& tag_, T const& value_) 48 : tag(tag_), value(value_) {} 49 infoboost::spirit::info50 info(utf8_string const& tag_, char value_) 51 : tag(tag_), value(utf8_string(1, value_)) {} 52 infoboost::spirit::info53 info(utf8_string const& tag_, wchar_t value_) 54 : tag(tag_), value(to_utf8(value_)) {} 55 infoboost::spirit::info56 info(utf8_string const& tag_, ucs4_char value_) 57 : tag(tag_), value(to_utf8(value_)) {} 58 59 template <typename Char> infoboost::spirit::info60 info(utf8_string const& tag_, Char const* str) 61 : tag(tag_), value(to_utf8(str)) {} 62 63 template <typename Char, typename Traits, typename Allocator> infoboost::spirit::info64 info(utf8_string const& tag_ 65 , std::basic_string<Char, Traits, Allocator> const& str) 66 : tag(tag_), value(to_utf8(str)) {} 67 68 utf8_string tag; 69 value_type value; 70 }; 71 72 template <typename Callback> 73 struct basic_info_walker 74 { 75 typedef void result_type; 76 typedef basic_info_walker<Callback> this_type; 77 basic_info_walkerboost::spirit::basic_info_walker78 basic_info_walker(Callback& callback_, utf8_string const& tag_, int depth_) 79 : callback(callback_), tag(tag_), depth(depth_) {} 80 operator ()boost::spirit::basic_info_walker81 void operator()(info::nil_) const 82 { 83 callback.element(tag, "", depth); 84 } 85 operator ()boost::spirit::basic_info_walker86 void operator()(utf8_string const& str) const 87 { 88 callback.element(tag, str, depth); 89 } 90 operator ()boost::spirit::basic_info_walker91 void operator()(info const& what) const 92 { 93 boost::apply_visitor( 94 this_type(callback, what.tag, depth+1), what.value); 95 } 96 operator ()boost::spirit::basic_info_walker97 void operator()(std::pair<info, info> const& pair) const 98 { 99 callback.element(tag, "", depth); 100 boost::apply_visitor( 101 this_type(callback, pair.first.tag, depth+1), pair.first.value); 102 boost::apply_visitor( 103 this_type(callback, pair.second.tag, depth+1), pair.second.value); 104 } 105 operator ()boost::spirit::basic_info_walker106 void operator()(std::list<info> const& l) const 107 { 108 callback.element(tag, "", depth); 109 BOOST_FOREACH(info const& what, l) 110 { 111 boost::apply_visitor( 112 this_type(callback, what.tag, depth+1), what.value); 113 } 114 } 115 116 Callback& callback; 117 utf8_string const& tag; 118 int depth; 119 120 // silence MSVC warning C4512: assignment operator could not be generated 121 BOOST_DELETED_FUNCTION(basic_info_walker& operator= (basic_info_walker const&)) 122 }; 123 124 // bare-bones print support 125 template <typename Out> 126 struct simple_printer 127 { 128 typedef utf8_string string; 129 simple_printerboost::spirit::simple_printer130 simple_printer(Out& out_) 131 : out(out_) {} 132 elementboost::spirit::simple_printer133 void element(string const& tag, string const& value, int /*depth*/) const 134 { 135 if (value.empty()) 136 out << '<' << tag << '>'; 137 else 138 out << '"' << value << '"'; 139 } 140 141 Out& out; 142 143 // silence MSVC warning C4512: assignment operator could not be generated 144 BOOST_DELETED_FUNCTION(simple_printer& operator= (simple_printer const&)) 145 }; 146 147 template <typename Out> operator <<(Out & out,info const & what)148 Out& operator<<(Out& out, info const& what) 149 { 150 simple_printer<Out> pr(out); 151 basic_info_walker<simple_printer<Out> > walker(pr, what.tag, 0); 152 boost::apply_visitor(walker, what.value); 153 return out; 154 } 155 }} 156 157 #endif 158