]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/spirit/include/boost/spirit/home/karma/operator/list.hpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / spirit / include / boost / spirit / home / karma / operator / list.hpp
1 // Copyright (c) 2001-2011 Hartmut Kaiser
2 // Copyright (c) 2001-2011 Joel de Guzman
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6
7 #if !defined(SPIRIT_KARMA_LIST_MAY_01_2007_0229PM)
8 #define SPIRIT_KARMA_LIST_MAY_01_2007_0229PM
9
10 #if defined(_MSC_VER)
11 #pragma once
12 #endif
13
14 #include <boost/spirit/home/karma/domain.hpp>
15 #include <boost/spirit/home/karma/generator.hpp>
16 #include <boost/spirit/home/karma/meta_compiler.hpp>
17 #include <boost/spirit/home/karma/detail/output_iterator.hpp>
18 #include <boost/spirit/home/karma/detail/indirect_iterator.hpp>
19 #include <boost/spirit/home/karma/detail/get_stricttag.hpp>
20 #include <boost/spirit/home/karma/detail/pass_container.hpp>
21 #include <boost/spirit/home/karma/detail/fail_function.hpp>
22 #include <boost/spirit/home/support/info.hpp>
23 #include <boost/spirit/home/support/unused.hpp>
24 #include <boost/spirit/home/support/container.hpp>
25 #include <boost/spirit/home/support/handles_container.hpp>
26 #include <boost/spirit/home/karma/detail/attributes.hpp>
27
28 namespace boost { namespace spirit
29 {
30 ///////////////////////////////////////////////////////////////////////////
31 // Enablers
32 ///////////////////////////////////////////////////////////////////////////
33 template <>
34 struct use_operator<karma::domain, proto::tag::modulus> // enables g % d
35 : mpl::true_ {};
36 }}
37
38 ///////////////////////////////////////////////////////////////////////////////
39 namespace boost { namespace spirit { namespace karma
40 {
41 template <typename Left, typename Right, typename Strict, typename Derived>
42 struct base_list : binary_generator<Derived>
43 {
44 private:
45 // iterate over the given container until its exhausted or the embedded
46 // (left) generator succeeds
47 template <typename F, typename Attribute>
48 bool generate_left(F f, Attribute const&, mpl::false_) const
49 {
50 // Failing subject generators are just skipped. This allows to
51 // selectively generate items in the provided attribute.
52 while (!f.is_at_end())
53 {
54 bool r = !f(left);
55 if (r)
56 return true;
57 if (!f.is_at_end())
58 f.next();
59 }
60 return false;
61 }
62
63 template <typename F, typename Attribute>
64 bool generate_left(F f, Attribute const&, mpl::true_) const
65 {
66 return !f(left);
67 }
68
69 // There is no way to distinguish a failed generator from a
70 // generator to be skipped. We assume the user takes responsibility
71 // for ending the loop if no attribute is specified.
72 template <typename F>
73 bool generate_left(F f, unused_type, mpl::false_) const
74 {
75 return !f(left);
76 }
77
78 public:
79 typedef Left left_type;
80 typedef Right right_type;
81
82 typedef mpl::int_<
83 left_type::properties::value
84 | right_type::properties::value
85 | generator_properties::buffering
86 | generator_properties::counting
87 > properties;
88
89 // Build a std::vector from the LHS's attribute. Note
90 // that build_std_vector may return unused_type if the
91 // subject's attribute is an unused_type.
92 template <typename Context, typename Iterator>
93 struct attribute
94 : traits::build_std_vector<
95 typename traits::attribute_of<Left, Context, Iterator>::type>
96 {};
97
98 base_list(Left const& left, Right const& right)
99 : left(left), right(right)
100 {}
101
102 template <
103 typename OutputIterator, typename Context, typename Delimiter
104 , typename Attribute>
105 bool generate(OutputIterator& sink, Context& ctx
106 , Delimiter const& d, Attribute const& attr) const
107 {
108 typedef detail::fail_function<
109 OutputIterator, Context, Delimiter
110 > fail_function;
111
112 typedef typename traits::container_iterator<
113 typename add_const<Attribute>::type
114 >::type iterator_type;
115
116 typedef
117 typename traits::make_indirect_iterator<iterator_type>::type
118 indirect_iterator_type;
119 typedef detail::pass_container<
120 fail_function, Attribute, indirect_iterator_type, mpl::false_>
121 pass_container;
122
123 iterator_type it = traits::begin(attr);
124 iterator_type end = traits::end(attr);
125
126 pass_container pass(fail_function(sink, ctx, d),
127 indirect_iterator_type(it), indirect_iterator_type(end));
128
129 if (generate_left(pass, attr, Strict()))
130 {
131 while (!pass.is_at_end())
132 {
133 // wrap the given output iterator as generate_left might fail
134 detail::enable_buffering<OutputIterator> buffering(sink);
135 {
136 detail::disable_counting<OutputIterator> nocounting(sink);
137
138 if (!right.generate(sink, ctx, d, unused))
139 return false; // shouldn't happen
140
141 if (!generate_left(pass, attr, Strict()))
142 break; // return true as one item succeeded
143 }
144 buffering.buffer_copy();
145 }
146 return detail::sink_is_good(sink);
147 }
148 return false;
149 }
150
151 template <typename Context>
152 info what(Context& context) const
153 {
154 return info("list",
155 std::make_pair(left.what(context), right.what(context)));
156 }
157
158 Left left;
159 Right right;
160 };
161
162 template <typename Left, typename Right>
163 struct list
164 : base_list<Left, Right, mpl::false_, list<Left, Right> >
165 {
166 typedef base_list<Left, Right, mpl::false_, list> base_list_;
167
168 list(Left const& left, Right const& right)
169 : base_list_(left, right) {}
170 };
171
172 template <typename Left, typename Right>
173 struct strict_list
174 : base_list<Left, Right, mpl::true_, strict_list<Left, Right> >
175 {
176 typedef base_list<Left, Right, mpl::true_, strict_list> base_list_;
177
178 strict_list (Left const& left, Right const& right)
179 : base_list_(left, right) {}
180 };
181
182 ///////////////////////////////////////////////////////////////////////////
183 // Generator generators: make_xxx function (objects)
184 ///////////////////////////////////////////////////////////////////////////
185 namespace detail
186 {
187 template <typename Subject, bool strict_mode = false>
188 struct make_list
189 : make_binary_composite<Subject, list>
190 {};
191
192 template <typename Subject>
193 struct make_list<Subject, true>
194 : make_binary_composite<Subject, strict_list>
195 {};
196 }
197
198 template <typename Subject, typename Modifiers>
199 struct make_composite<proto::tag::modulus, Subject, Modifiers>
200 : detail::make_list<Subject, detail::get_stricttag<Modifiers>::value>
201 {};
202 }}}
203
204 namespace boost { namespace spirit { namespace traits
205 {
206 ///////////////////////////////////////////////////////////////////////////
207 template <typename Left, typename Right>
208 struct has_semantic_action<karma::list<Left, Right> >
209 : binary_has_semantic_action<Left, Right> {};
210
211 template <typename Left, typename Right>
212 struct has_semantic_action<karma::strict_list<Left, Right> >
213 : binary_has_semantic_action<Left, Right> {};
214
215 ///////////////////////////////////////////////////////////////////////////
216 template <typename Left, typename Right, typename Attribute
217 , typename Context, typename Iterator>
218 struct handles_container<karma::list<Left, Right>, Attribute
219 , Context, Iterator>
220 : mpl::true_ {};
221
222 template <typename Left, typename Right, typename Attribute
223 , typename Context, typename Iterator>
224 struct handles_container<karma::strict_list<Left, Right>, Attribute
225 , Context, Iterator>
226 : mpl::true_ {};
227 }}}
228
229 #endif