]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/spirit/example/karma/customize_use_as_container.cpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / spirit / example / karma / customize_use_as_container.cpp
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_use_as_container_includes
11 #include <boost/spirit/include/karma.hpp>
12 #include <iostream>
13 #include <string>
14 #include <vector>
15 //]
16
17 ///////////////////////////////////////////////////////////////////////////////
18 //[customize_karma_use_as_container_data
19 namespace client
20 {
21 struct use_as_container
22 {
23 // Expose a pair holding a pointer to the use_as_container and to the
24 // current element as our iterator.
25 // We intentionally leave out having it a 'operator==()' to demonstrate
26 // the use of the 'compare_iterators' customization point.
27 struct iterator
28 {
29 iterator(use_as_container const* container, int const* current)
30 : container_(container), current_(current)
31 {}
32
33 use_as_container const* container_;
34 int const* current_;
35 };
36
37 // expose 'int' as the type of each generated element
38 typedef int type;
39
40 use_as_container(int value1, int value2, int value3)
41 : value1_(value1), value2_(value2), value3_(value3)
42 {}
43
44 int value1_;
45 std::string dummy1_; // insert some unrelated data
46 int value2_;
47 std::string dummy2_; // insert some more unrelated data
48 int value3_;
49 };
50 }
51 //]
52
53 //[customize_karma_use_as_container_traits
54 // All specializations of attribute customization points have to be placed into
55 // the namespace boost::spirit::traits.
56 //
57 // Note that all templates below are specialized using the 'const' type.
58 // This is necessary as all attributes in Karma are 'const'.
59 namespace boost { namespace spirit { namespace traits
60 {
61 // The specialization of the template 'is_container<>' will tell the
62 // library to treat the type 'client::use_as_container' as a
63 // container holding the items to generate output from.
64 template <>
65 struct is_container<client::use_as_container const>
66 : mpl::true_
67 {};
68
69 // The specialization of the template 'container_iterator<>' will be
70 // invoked by the library to evaluate the iterator type to be used
71 // for iterating the data elements in the container. We simply return
72 // the type of the iterator exposed by the embedded 'std::vector<int>'.
73 template <>
74 struct container_iterator<client::use_as_container const>
75 {
76 typedef client::use_as_container::iterator type;
77 };
78
79 // The specialization of the templates 'begin_container<>' and
80 // 'end_container<>' below will be used by the library to get the iterators
81 // pointing to the begin and the end of the data to generate output from.
82 //
83 // The passed argument refers to the attribute instance passed to the list
84 // generator.
85 template <>
86 struct begin_container<client::use_as_container const>
87 {
88 static client::use_as_container::iterator
89 call(client::use_as_container const& c)
90 {
91 return client::use_as_container::iterator(&c, &c.value1_);
92 }
93 };
94
95 template <>
96 struct end_container<client::use_as_container const>
97 {
98 static client::use_as_container::iterator
99 call(client::use_as_container const& c)
100 {
101 return client::use_as_container::iterator(&c, (int const*)0);
102 }
103 };
104 }}}
105 //]
106
107 //[customize_karma_use_as_container_iterator_traits
108 // All specializations of attribute customization points have to be placed into
109 // the namespace boost::spirit::traits.
110 namespace boost { namespace spirit { namespace traits
111 {
112 // The specialization of the template 'deref_iterator<>' will be used to
113 // dereference the iterator associated with our counter data structure.
114 template <>
115 struct deref_iterator<client::use_as_container::iterator>
116 {
117 typedef client::use_as_container::type type;
118
119 static type call(client::use_as_container::iterator const& it)
120 {
121 return *it.current_;
122 }
123 };
124
125 template <>
126 struct next_iterator<client::use_as_container::iterator>
127 {
128 static void call(client::use_as_container::iterator& it)
129 {
130 if (it.current_ == &it.container_->value1_)
131 it.current_ = &it.container_->value2_;
132 else if (it.current_ == &it.container_->value2_)
133 it.current_ = &it.container_->value3_;
134 else
135 it.current_ = 0;
136 }
137 };
138
139 template <>
140 struct compare_iterators<client::use_as_container::iterator>
141 {
142 static bool call(client::use_as_container::iterator const& it1
143 , client::use_as_container::iterator const& it2)
144 {
145 return it1.current_ == it2.current_ &&
146 it1.container_ == it2.container_;
147 }
148 };
149 }}}
150 //]
151
152 ///////////////////////////////////////////////////////////////////////////////
153 namespace karma = boost::spirit::karma;
154
155 int main()
156 {
157 //[customize_karma_use_as_container
158 client::use_as_container d2 (1, 2, 3);
159 // use the instance of a 'client::use_as_container' instead of a STL vector
160 std::cout << karma::format(karma::int_ % ", ", d2) << std::endl; // prints: '1, 2, 3'
161 //]
162 return 0;
163 }
164