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/spirit/home/support/utf8.hpp> |
18 | #include <list> |
19 | #include <iterator> |
20 | #include <utility> |
21 | |
22 | namespace boost { namespace spirit |
23 | { |
24 | // info provides information about a component. Each component |
25 | // has a what member function that returns an info object. |
26 | // strings in the info object are assumed to be encoded as UTF8 |
27 | // for uniformity. |
28 | struct info |
29 | { |
30 | struct nil_ {}; |
31 | |
32 | typedef |
33 | boost::variant< |
34 | nil_ |
35 | , utf8_string |
36 | , recursive_wrapper<info> |
37 | , recursive_wrapper<std::pair<info, info> > |
38 | , recursive_wrapper<std::list<info> > |
39 | > |
40 | value_type; |
41 | |
42 | explicit info(utf8_string const& tag_) |
43 | : tag(tag_), value(nil_()) {} |
44 | |
45 | template <typename T> |
46 | info(utf8_string const& tag_, T const& value_) |
47 | : tag(tag_), value(value_) {} |
48 | |
49 | info(utf8_string const& tag_, char value_) |
50 | : tag(tag_), value(utf8_string(1, value_)) {} |
51 | |
52 | info(utf8_string const& tag_, wchar_t value_) |
53 | : tag(tag_), value(to_utf8(value: value_)) {} |
54 | |
55 | info(utf8_string const& tag_, ucs4_char value_) |
56 | : tag(tag_), value(to_utf8(value: value_)) {} |
57 | |
58 | template <typename Char> |
59 | info(utf8_string const& tag_, Char const* str) |
60 | : tag(tag_), value(to_utf8(str)) {} |
61 | |
62 | template <typename Char, typename Traits, typename Allocator> |
63 | info(utf8_string const& tag_ |
64 | , std::basic_string<Char, Traits, Allocator> const& str) |
65 | : tag(tag_), value(to_utf8(str)) {} |
66 | |
67 | utf8_string tag; |
68 | value_type value; |
69 | }; |
70 | |
71 | #ifdef _MSC_VER |
72 | # pragma warning(push) |
73 | # pragma warning(disable: 4512) // assignment operator could not be generated. |
74 | #endif |
75 | template <typename Callback> |
76 | struct basic_info_walker |
77 | { |
78 | typedef void result_type; |
79 | typedef basic_info_walker<Callback> this_type; |
80 | |
81 | basic_info_walker(Callback& callback_, utf8_string const& tag_, int depth_) |
82 | : callback(callback_), tag(tag_), depth(depth_) {} |
83 | |
84 | void operator()(info::nil_) const |
85 | { |
86 | callback.element(tag, "" , depth); |
87 | } |
88 | |
89 | void operator()(utf8_string const& str) const |
90 | { |
91 | callback.element(tag, str, depth); |
92 | } |
93 | |
94 | void operator()(info const& what) const |
95 | { |
96 | boost::apply_visitor( |
97 | this_type(callback, what.tag, depth+1), what.value); |
98 | } |
99 | |
100 | void operator()(std::pair<info, info> const& pair) const |
101 | { |
102 | callback.element(tag, "" , depth); |
103 | boost::apply_visitor( |
104 | this_type(callback, pair.first.tag, depth+1), pair.first.value); |
105 | boost::apply_visitor( |
106 | this_type(callback, pair.second.tag, depth+1), pair.second.value); |
107 | } |
108 | |
109 | void operator()(std::list<info> const& l) const |
110 | { |
111 | callback.element(tag, "" , depth); |
112 | for (std::list<info>::const_iterator it = l.begin(), |
113 | end = l.end(); it != end; ++it) |
114 | { |
115 | boost::apply_visitor( |
116 | this_type(callback, it->tag, depth+1), it->value); |
117 | } |
118 | } |
119 | |
120 | Callback& callback; |
121 | utf8_string const& tag; |
122 | int depth; |
123 | }; |
124 | |
125 | // bare-bones print support |
126 | template <typename Out> |
127 | struct simple_printer |
128 | { |
129 | typedef utf8_string string; |
130 | |
131 | simple_printer(Out& out_) |
132 | : out(out_) {} |
133 | |
134 | void element(string const& tag, string const& value, int /*depth*/) const |
135 | { |
136 | if (value.empty()) |
137 | out << '<' << tag << '>'; |
138 | else |
139 | out << '"' << value << '"'; |
140 | } |
141 | |
142 | Out& out; |
143 | }; |
144 | #ifdef _MSC_VER |
145 | # pragma warning(pop) |
146 | #endif |
147 | |
148 | template <typename Out> |
149 | Out& operator<<(Out& out, info const& what) |
150 | { |
151 | simple_printer<Out> pr(out); |
152 | basic_info_walker<simple_printer<Out> > walker(pr, what.tag, 0); |
153 | boost::apply_visitor(walker, what.value); |
154 | return out; |
155 | } |
156 | }} |
157 | |
158 | #endif |
159 | |