]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | ||
43 | explicit info(utf8_string const& tag_) | |
44 | : tag(tag_), value(nil_()) {} | |
45 | ||
46 | template <typename T> | |
47 | info(utf8_string const& tag_, T const& value_) | |
48 | : tag(tag_), value(value_) {} | |
49 | ||
50 | info(utf8_string const& tag_, char value_) | |
51 | : tag(tag_), value(utf8_string(1, value_)) {} | |
52 | ||
53 | info(utf8_string const& tag_, wchar_t value_) | |
54 | : tag(tag_), value(to_utf8(value_)) {} | |
55 | ||
56 | info(utf8_string const& tag_, ucs4_char value_) | |
57 | : tag(tag_), value(to_utf8(value_)) {} | |
58 | ||
59 | template <typename Char> | |
60 | info(utf8_string const& tag_, Char const* str) | |
61 | : tag(tag_), value(to_utf8(str)) {} | |
62 | ||
63 | template <typename Char, typename Traits, typename Allocator> | |
64 | 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 | ||
78 | basic_info_walker(Callback& callback_, utf8_string const& tag_, int depth_) | |
79 | : callback(callback_), tag(tag_), depth(depth_) {} | |
80 | ||
81 | void operator()(info::nil_) const | |
82 | { | |
83 | callback.element(tag, "", depth); | |
84 | } | |
85 | ||
86 | void operator()(utf8_string const& str) const | |
87 | { | |
88 | callback.element(tag, str, depth); | |
89 | } | |
90 | ||
91 | void operator()(info const& what) const | |
92 | { | |
93 | boost::apply_visitor( | |
94 | this_type(callback, what.tag, depth+1), what.value); | |
95 | } | |
96 | ||
97 | 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 | ||
106 | 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 | private: | |
121 | // silence MSVC warning C4512: assignment operator could not be generated | |
122 | basic_info_walker& operator= (basic_info_walker const&); | |
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 == "") | |
137 | out << '<' << tag << '>'; | |
138 | else | |
139 | out << '"' << value << '"'; | |
140 | } | |
141 | ||
142 | Out& out; | |
143 | ||
144 | private: | |
145 | // silence MSVC warning C4512: assignment operator could not be generated | |
146 | simple_printer& operator= (simple_printer const&); | |
147 | }; | |
148 | ||
149 | template <typename Out> | |
150 | Out& operator<<(Out& out, info const& what) | |
151 | { | |
152 | simple_printer<Out> pr(out); | |
153 | basic_info_walker<simple_printer<Out> > walker(pr, what.tag, 0); | |
154 | boost::apply_visitor(walker, what.value); | |
155 | return out; | |
156 | } | |
157 | }} | |
158 | ||
159 | #endif |