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