1 /*=============================================================================
2     Copyright (c) 2001-2011 Hartmut Kaiser
3     http://spirit.sourceforge.net/
4 
5     Distributed under the Boost Software License, Version 1.0. (See accompanying
6     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 =============================================================================*/
8 #include <boost/config/warning_disable.hpp>
9 
10 //[customize_karma_counter_includes
11 #include <boost/spirit/include/karma.hpp>
12 #include <iostream>
13 #include <vector>
14 //]
15 
16 ///////////////////////////////////////////////////////////////////////////////
17 //[customize_karma_counter_data
18 namespace client
19 {
20     struct counter
21     {
22         // expose the current value of the counter as our iterator
23         typedef int iterator;
24 
25         // expose 'int' as the type of each generated element
26         typedef int type;
27 
counterclient::counter28         counter(int max_count)
29           : counter_(0), max_count_(max_count)
30         {}
31 
32         int counter_;
33         int max_count_;
34     };
35 }
36 //]
37 
38 //[customize_karma_counter_traits
39 // All specializations of attribute customization points have to be placed into
40 // the namespace boost::spirit::traits.
41 //
42 // Note that all templates below are specialized using the 'const' type.
43 // This is necessary as all attributes in Karma are 'const'.
44 namespace boost { namespace spirit { namespace traits
45 {
46     // The specialization of the template 'is_container<>' will tell the
47     // library to treat the type 'client::counter' as a container providing
48     // the items to generate output from.
49     template <>
50     struct is_container<client::counter const>
51       : mpl::true_
52     {};
53 
54     // The specialization of the template 'container_iterator<>' will be
55     // invoked by the library to evaluate the iterator type to be used
56     // for iterating the data elements in the container.
57     template <>
58     struct container_iterator<client::counter const>
59     {
60         typedef client::counter::iterator type;
61     };
62 
63     // The specialization of the templates 'begin_container<>' and
64     // 'end_container<>' below will be used by the library to get the iterators
65     // pointing to the begin and the end of the data to generate output from.
66     // These specializations respectively return the initial and maximum
67     // counter values.
68     //
69     // The passed argument refers to the attribute instance passed to the list
70     // generator.
71     template <>
72     struct begin_container<client::counter const>
73     {
74         static client::counter::iterator
callboost::spirit::traits::begin_container75         call(client::counter const& c)
76         {
77             return c.counter_;
78         }
79     };
80 
81     template <>
82     struct end_container<client::counter const>
83     {
84         static client::counter::iterator
callboost::spirit::traits::end_container85         call(client::counter const& c)
86         {
87             return c.max_count_;
88         }
89     };
90 }}}
91 //]
92 
93 //[customize_karma_counter_iterator_traits
94 // All specializations of attribute customization points have to be placed into
95 // the namespace boost::spirit::traits.
96 namespace boost { namespace spirit { namespace traits
97 {
98     // The specialization of the template 'deref_iterator<>' will be used to
99     // dereference the iterator associated with our counter data structure.
100     // Since we expose the current value as the iterator we just return the
101     // current iterator as the return value.
102     template <>
103     struct deref_iterator<client::counter::iterator>
104     {
105         typedef client::counter::type type;
106 
callboost::spirit::traits::deref_iterator107         static type call(client::counter::iterator const& it)
108         {
109             return it;
110         }
111     };
112 }}}
113 //]
114 
115 ///////////////////////////////////////////////////////////////////////////////
116 namespace karma = boost::spirit::karma;
117 
main()118 int main()
119 {
120     //[customize_karma_counter
121     // use the instance of a 'client::counter' instead of a STL vector
122     client::counter count(4);
123     std::cout << karma::format(karma::int_ % ", ", count) << std::endl;   // prints: '0, 1, 2, 3'
124     //]
125     return 0;
126 }
127 
128