]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // Copyright (c) 2001-2010 Hartmut Kaiser |
2 | // | |
3 | // Distributed under the Boost Software License, Version 1.0. (See accompanying | |
4 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
5 | ||
6 | // The main purpose of this example is to show the uniform and easy way of | |
7 | // output formatting for different container types. | |
8 | // | |
9 | // The 'auto_' primitive used below is very similar to the 'stream' primitive | |
10 | // demonstrated in the example 'basic_facilities.cpp' as it allows to generate | |
11 | // output from a multitude of data types. The main difference is that it is | |
12 | // mapped to the correct Karma generator instead of using any available | |
13 | // operator<<() for the contained data type. Additionally this means, that | |
14 | // the format descriptions used below will be usable for any contained type as | |
15 | // long as this type has a defined mapping to a Karma generator. | |
16 | ||
17 | // use a larger value for the alignment field width (default is 10) | |
18 | #define BOOST_KARMA_DEFAULT_FIELD_LENGTH 25 | |
19 | ||
20 | #include <boost/config/warning_disable.hpp> | |
21 | ||
22 | #include <iostream> | |
23 | #include <string> | |
24 | #include <vector> | |
25 | #include <list> | |
26 | #include <map> | |
27 | #include <algorithm> | |
28 | #include <cstdlib> | |
29 | ||
7c673cae FG |
30 | #include <boost/array.hpp> |
31 | #include <boost/fusion/include/std_pair.hpp> | |
32 | #include <boost/fusion/include/array.hpp> | |
20effc67 | 33 | #include <boost/range/iterator_range.hpp> |
7c673cae FG |
34 | |
35 | #include <boost/spirit/include/karma.hpp> | |
36 | ||
37 | using namespace boost::spirit; | |
38 | using namespace boost::spirit::ascii; | |
39 | ||
40 | /////////////////////////////////////////////////////////////////////////////// | |
41 | namespace boost { namespace spirit { namespace traits | |
42 | { | |
43 | // We add a specialization for the create_generator customization point | |
44 | // defining a custom output format for the value type of the std::map used | |
45 | // below (std::pair<int const, std::string>). Generally, any specialization | |
46 | // for create_generator is expected to return the proto expression to be | |
47 | // used to generate output for the type the customization point has been | |
48 | // specialized for. | |
49 | // | |
50 | // We need to utilize proto::deep_copy as the expression contains a literal | |
51 | // (the ':') which normally gets embedded in the proto expression by | |
52 | // reference only. The deep copy converts the proto tree to hold this by | |
53 | // value. The deep copy operation can be left out for simpler proto | |
54 | // expressions (not containing references to temporaries). Alternatively | |
55 | // you could use the proto::make_expr() facility to build the required | |
56 | // proto expression. | |
57 | template <> | |
58 | struct create_generator<std::pair<int const, std::string> > | |
59 | { | |
60 | typedef proto::result_of::deep_copy< | |
61 | BOOST_TYPEOF(int_ << ':' << string) | |
62 | >::type type; | |
63 | ||
64 | static type call() | |
65 | { | |
66 | return proto::deep_copy(int_ << ':' << string); | |
67 | } | |
68 | }; | |
69 | }}} | |
70 | ||
71 | /////////////////////////////////////////////////////////////////////////////// | |
72 | // Output the given containers in list format | |
73 | // Note: the format description does not depend on the type of the sequence | |
74 | // nor does it depend on the type of the elements contained in the | |
75 | // sequence | |
76 | /////////////////////////////////////////////////////////////////////////////// | |
77 | template <typename Container> | |
78 | void output_container(std::ostream& os, Container const& c) | |
79 | { | |
80 | // output the container as a sequence without separators | |
81 | os << | |
82 | karma::format( | |
83 | auto_, // format description | |
84 | c // data | |
85 | ) << std::endl << std::endl; | |
86 | ||
87 | os << | |
88 | karma::format( | |
89 | *auto_, // format description | |
90 | c // data | |
91 | ) << std::endl << std::endl; | |
92 | ||
93 | // output the container as a space separated sequence | |
94 | os << | |
95 | karma::format_delimited( | |
96 | auto_, // format description | |
97 | space, // delimiter | |
98 | c // data | |
99 | ) << std::endl << std::endl; | |
100 | ||
101 | os << | |
102 | karma::format_delimited( | |
103 | *auto_, // format description | |
104 | space, // delimiter | |
105 | c // data | |
106 | ) << std::endl << std::endl; | |
107 | ||
108 | os << | |
109 | karma::format_delimited( | |
110 | '[' << *auto_ << ']', // format description | |
111 | space, // delimiter | |
112 | c // data | |
113 | ) << std::endl << std::endl; | |
114 | ||
115 | // output the container as a comma separated list | |
116 | os << | |
117 | karma::format( | |
118 | auto_ % ", ", // format description | |
119 | c // data | |
120 | ) << std::endl << std::endl; | |
121 | ||
122 | os << | |
123 | karma::format( | |
124 | '[' << (auto_ % ", ") << ']', // format description | |
125 | c // data | |
126 | ) << std::endl << std::endl; | |
127 | ||
128 | os << | |
129 | karma::format( | |
130 | '[' << -(auto_ % ", ") << ']', // format description | |
131 | c // data | |
132 | ) << std::endl << std::endl; | |
133 | ||
134 | os << | |
135 | karma::format( | |
136 | '[' << (+auto_ | "empty") << ']', // format description | |
137 | c // data | |
138 | ) << std::endl << std::endl; | |
139 | ||
140 | // output the container as a comma separated list of items enclosed in '()' | |
141 | os << | |
142 | karma::format( | |
143 | ('(' << auto_ << ')') % ", ", // format description | |
144 | c // data | |
145 | ) << std::endl << std::endl; | |
146 | ||
147 | os << | |
148 | karma::format( | |
149 | '[' << ( | |
150 | ('(' << auto_ << ')') % ", " | |
151 | ) << ']', // format description | |
152 | c // data | |
153 | ) << std::endl << std::endl; | |
154 | ||
155 | // output the container as a HTML list | |
156 | os << | |
157 | karma::format_delimited( | |
158 | "<ol>" << | |
159 | *verbatim["<li>" << auto_ << "</li>"] | |
160 | << "</ol>", // format description | |
161 | '\n', // delimiter | |
162 | c // data | |
163 | ) << std::endl; | |
164 | ||
165 | // output the container as right aligned column | |
166 | os << | |
167 | karma::format_delimited( | |
168 | *verbatim[ | |
169 | "|" << right_align[auto_] << "|" | |
170 | ], // format description | |
171 | '\n', // delimiter | |
172 | c // data | |
173 | ) << std::endl; | |
174 | ||
175 | os << std::endl; | |
176 | } | |
177 | ||
178 | int main() | |
179 | { | |
180 | /////////////////////////////////////////////////////////////////////////// | |
181 | // C-style array | |
182 | int i[4] = { 3, 6, 9, 12 }; | |
183 | ||
184 | std::cout << "-------------------------------------------------------------" | |
185 | << std::endl; | |
186 | std::cout << "int i[]" << std::endl; | |
187 | output_container(std::cout, boost::make_iterator_range(i, i+4)); | |
188 | ||
189 | /////////////////////////////////////////////////////////////////////////// | |
190 | // vector | |
191 | std::vector<int> v (5); | |
192 | std::generate(v.begin(), v.end(), std::rand); // randomly fill the vector | |
193 | ||
194 | std::cout << "-------------------------------------------------------------" | |
195 | << std::endl; | |
196 | std::cout << "std::vector<int>" << std::endl; | |
197 | output_container(std::cout, v); | |
198 | ||
199 | /////////////////////////////////////////////////////////////////////////// | |
200 | // list | |
201 | std::list<char> l; | |
202 | l.push_back('A'); | |
203 | l.push_back('B'); | |
204 | l.push_back('C'); | |
205 | ||
206 | std::cout << "-------------------------------------------------------------" | |
207 | << std::endl; | |
208 | std::cout << "std::list<char>" << std::endl; | |
209 | output_container(std::cout, l); | |
210 | ||
211 | /////////////////////////////////////////////////////////////////////////// | |
212 | // strings | |
213 | std::string str("Hello world!"); | |
214 | ||
215 | std::cout << "-------------------------------------------------------------" | |
216 | << std::endl; | |
217 | std::cout << "std::string" << std::endl; | |
218 | output_container(std::cout, str); | |
219 | ||
220 | /////////////////////////////////////////////////////////////////////////// | |
221 | // boost::array | |
222 | boost::array<long, 5> arr; | |
223 | std::generate(arr.begin(), arr.end(), std::rand); // randomly fill the array | |
224 | ||
225 | std::cout << "-------------------------------------------------------------" | |
226 | << std::endl; | |
227 | std::cout << "boost::array<long, 5>" << std::endl; | |
228 | output_container(std::cout, arr); | |
229 | ||
230 | /////////////////////////////////////////////////////////////////////////// | |
231 | // map of int --> string mappings | |
232 | std::map<int, std::string> mappings; | |
233 | mappings.insert(std::make_pair(0, "zero")); | |
234 | mappings.insert(std::make_pair(1, "one")); | |
235 | mappings.insert(std::make_pair(2, "two")); | |
236 | ||
237 | std::cout << "-------------------------------------------------------------" | |
238 | << std::endl; | |
239 | std::cout << "std::map<int, std::string>" << std::endl; | |
240 | output_container(std::cout, mappings); | |
241 | ||
242 | return 0; | |
243 | } | |
244 |