• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
30 #include <boost/array.hpp>
31 #include <boost/fusion/include/std_pair.hpp>
32 #include <boost/fusion/include/array.hpp>
33 #include <boost/range/iterator_range.hpp>
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 
callboost::spirit::traits::create_generator64         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>
output_container(std::ostream & os,Container const & c)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 
main()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 
245