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