]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/spirit/home/karma/directive/repeat.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / boost / spirit / home / karma / directive / repeat.hpp
CommitLineData
7c673cae
FG
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_REPEAT_MAY_18_2009_0926AM)
8#define SPIRIT_KARMA_REPEAT_MAY_18_2009_0926AM
9
10#if defined(_MSC_VER)
11#pragma once
12#endif
13
14#include <boost/spirit/home/karma/meta_compiler.hpp>
15#include <boost/spirit/home/karma/detail/output_iterator.hpp>
16#include <boost/spirit/home/karma/detail/get_stricttag.hpp>
17#include <boost/spirit/home/karma/generator.hpp>
18#include <boost/spirit/home/karma/auxiliary/lazy.hpp>
19#include <boost/spirit/home/karma/operator/kleene.hpp>
20#include <boost/spirit/home/support/container.hpp>
21#include <boost/spirit/home/support/common_terminals.hpp>
22#include <boost/spirit/home/support/has_semantic_action.hpp>
23#include <boost/spirit/home/support/handles_container.hpp>
24#include <boost/spirit/home/karma/detail/attributes.hpp>
25#include <boost/spirit/home/support/info.hpp>
26#include <boost/fusion/include/at.hpp>
27
28namespace boost { namespace spirit
29{
30 ///////////////////////////////////////////////////////////////////////////
31 // Enablers
32 ///////////////////////////////////////////////////////////////////////////
33 template <>
34 struct use_directive<karma::domain, tag::repeat> // enables repeat[p]
35 : mpl::true_ {};
36
37 template <typename T>
38 struct use_directive<karma::domain
39 , terminal_ex<tag::repeat // enables repeat(exact)[p]
40 , fusion::vector1<T> >
41 > : mpl::true_ {};
42
43 template <typename T>
44 struct use_directive<karma::domain
45 , terminal_ex<tag::repeat // enables repeat(min, max)[p]
46 , fusion::vector2<T, T> >
47 > : mpl::true_ {};
48
49 template <typename T>
50 struct use_directive<karma::domain
51 , terminal_ex<tag::repeat // enables repeat(min, inf)[p]
52 , fusion::vector2<T, inf_type> >
53 > : mpl::true_ {};
54
55 template <> // enables *lazy* repeat(exact)[p]
56 struct use_lazy_directive<
57 karma::domain
58 , tag::repeat
59 , 1 // arity
60 > : mpl::true_ {};
61
62 template <> // enables *lazy* repeat(min, max)[p]
63 struct use_lazy_directive< // and repeat(min, inf)[p]
64 karma::domain
65 , tag::repeat
66 , 2 // arity
67 > : mpl::true_ {};
68}}
69
70namespace boost { namespace spirit { namespace karma
71{
72#ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
73 using spirit::repeat;
74 using spirit::inf;
75#endif
76 using spirit::repeat_type;
77 using spirit::inf_type;
78
79 ///////////////////////////////////////////////////////////////////////////
80 // handles repeat(exact)[p]
81 template <typename T>
82 struct exact_iterator
83 {
84 exact_iterator(T const exact)
85 : exact(exact) {}
86
87 typedef T type;
88 T start() const { return 0; }
89 bool got_max(T i) const { return i >= exact; }
90 bool got_min(T i) const { return i >= exact; }
91
92 T const exact;
93
7c673cae 94 // silence MSVC warning C4512: assignment operator could not be generated
92f5a8d4 95 BOOST_DELETED_FUNCTION(exact_iterator& operator= (exact_iterator const&))
7c673cae
FG
96 };
97
98 // handles repeat(min, max)[p]
99 template <typename T>
100 struct finite_iterator
101 {
102 finite_iterator(T const min, T const max)
103 : min BOOST_PREVENT_MACRO_SUBSTITUTION (min)
104 , max BOOST_PREVENT_MACRO_SUBSTITUTION (max) {}
105
106 typedef T type;
107 T start() const { return 0; }
108 bool got_max(T i) const { return i >= max; }
109 bool got_min(T i) const { return i >= min; }
110
111 T const min;
112 T const max;
113
7c673cae 114 // silence MSVC warning C4512: assignment operator could not be generated
92f5a8d4 115 BOOST_DELETED_FUNCTION(finite_iterator& operator= (finite_iterator const&))
7c673cae
FG
116 };
117
118 // handles repeat(min, inf)[p]
119 template <typename T>
120 struct infinite_iterator
121 {
122 infinite_iterator(T const min)
123 : min BOOST_PREVENT_MACRO_SUBSTITUTION (min) {}
124
125 typedef T type;
126 T start() const { return 0; }
127 bool got_max(T /*i*/) const { return false; }
128 bool got_min(T i) const { return i >= min; }
129
130 T const min;
131
7c673cae 132 // silence MSVC warning C4512: assignment operator could not be generated
92f5a8d4 133 BOOST_DELETED_FUNCTION(infinite_iterator& operator= (infinite_iterator const&))
7c673cae
FG
134 };
135
136 ///////////////////////////////////////////////////////////////////////////
137 template <typename Subject, typename LoopIter, typename Strict
138 , typename Derived>
139 struct base_repeat_generator : unary_generator<Derived>
140 {
141 private:
142 // iterate over the given container until its exhausted or the embedded
143 // generator succeeds
144 template <typename F, typename Attribute>
145 bool generate_subject(F f, Attribute const&, mpl::false_) const
146 {
147 // Failing subject generators are just skipped. This allows to
148 // selectively generate items in the provided attribute.
149 while (!f.is_at_end())
150 {
151 bool r = !f(subject);
152 if (r)
153 return true;
154 if (!f.is_at_end())
155 f.next();
156 }
157 return false;
158 }
159
160 template <typename F, typename Attribute>
161 bool generate_subject(F f, Attribute const&, mpl::true_) const
162 {
163 return !f(subject);
164 }
165
166 // There is no way to distinguish a failed generator from a
167 // generator to be skipped. We assume the user takes responsibility
168 // for ending the loop if no attribute is specified.
169 template <typename F>
170 bool generate_subject(F f, unused_type, mpl::false_) const
171 {
172 return !f(subject);
173 }
174
175 public:
176 typedef Subject subject_type;
177
178 typedef mpl::int_<subject_type::properties::value> properties;
179
180 // Build a std::vector from the subject's attribute. Note
181 // that build_std_vector may return unused_type if the
182 // subject's attribute is an unused_type.
183 template <typename Context, typename Iterator>
184 struct attribute
185 : traits::build_std_vector<
186 typename traits::attribute_of<Subject, Context, Iterator>::type
187 >
188 {};
189
190 base_repeat_generator(Subject const& subject, LoopIter const& iter)
191 : subject(subject), iter(iter) {}
192
193 template <typename OutputIterator, typename Context, typename Delimiter
194 , typename Attribute>
195 bool generate(OutputIterator& sink, Context& ctx, Delimiter const& d
196 , Attribute const& attr) const
197 {
198 typedef detail::fail_function<
199 OutputIterator, Context, Delimiter
200 > fail_function;
201
202 typedef typename traits::container_iterator<
203 typename add_const<Attribute>::type
204 >::type iterator_type;
205
206 typedef
207 typename traits::make_indirect_iterator<iterator_type>::type
208 indirect_iterator_type;
209
210 typedef detail::pass_container<
211 fail_function, Attribute, indirect_iterator_type, mpl::false_>
212 pass_container;
213
214 iterator_type it = traits::begin(attr);
215 iterator_type end = traits::end(attr);
216
217 pass_container pass(fail_function(sink, ctx, d),
218 indirect_iterator_type(it), indirect_iterator_type(end));
219
220 // generate the minimal required amount of output
221 typename LoopIter::type i = iter.start();
222 for (/**/; !pass.is_at_end() && !iter.got_min(i); ++i)
223 {
224 if (!generate_subject(pass, attr, Strict()))
225 {
226 // if we fail before reaching the minimum iteration
227 // required, do not output anything and return false
228 return false;
229 }
230 }
231
232 if (pass.is_at_end() && !iter.got_min(i))
233 return false; // insufficient attribute elements
234
235 // generate some more up to the maximum specified
236 for (/**/; !pass.is_at_end() && !iter.got_max(i); ++i)
237 {
238 if (!generate_subject(pass, attr, Strict()))
239 break;
240 }
241 return detail::sink_is_good(sink);
242 }
243
244 template <typename Context>
245 info what(Context& context) const
246 {
247 return info("repeat", subject.what(context));
248 }
249
250 Subject subject;
251 LoopIter iter;
252 };
253
254 template <typename Subject, typename LoopIter>
255 struct repeat_generator
256 : base_repeat_generator<
257 Subject, LoopIter, mpl::false_
258 , repeat_generator<Subject, LoopIter> >
259 {
260 typedef base_repeat_generator<
261 Subject, LoopIter, mpl::false_, repeat_generator
262 > base_repeat_generator_;
263
264 repeat_generator(Subject const& subject, LoopIter const& iter)
265 : base_repeat_generator_(subject, iter) {}
266 };
267
268 template <typename Subject, typename LoopIter>
269 struct strict_repeat_generator
270 : base_repeat_generator<
271 Subject, LoopIter, mpl::true_
272 , strict_repeat_generator<Subject, LoopIter> >
273 {
274 typedef base_repeat_generator<
275 Subject, LoopIter, mpl::true_, strict_repeat_generator
276 > base_repeat_generator_;
277
278 strict_repeat_generator(Subject const& subject, LoopIter const& iter)
279 : base_repeat_generator_(subject, iter) {}
280 };
281
282 ///////////////////////////////////////////////////////////////////////////
283 // Generator generators: make_xxx function (objects)
284 ///////////////////////////////////////////////////////////////////////////
285 template <typename Subject, typename Modifiers>
286 struct make_directive<tag::repeat, Subject, Modifiers>
287 {
288 typedef typename mpl::if_<
289 detail::get_stricttag<Modifiers>
290 , strict_kleene<Subject>, kleene<Subject>
291 >::type result_type;
292
293 result_type operator()(unused_type, Subject const& subject
294 , unused_type) const
295 {
296 return result_type(subject);
297 }
298 };
299
300 template <typename T, typename Subject, typename Modifiers>
301 struct make_directive<
302 terminal_ex<tag::repeat, fusion::vector1<T> >, Subject, Modifiers>
303 {
304 typedef exact_iterator<T> iterator_type;
305
306 typedef typename mpl::if_<
307 detail::get_stricttag<Modifiers>
308 , strict_repeat_generator<Subject, iterator_type>
309 , repeat_generator<Subject, iterator_type>
310 >::type result_type;
311
312 template <typename Terminal>
313 result_type operator()(
314 Terminal const& term, Subject const& subject, unused_type) const
315 {
316 return result_type(subject, fusion::at_c<0>(term.args));
317 }
318 };
319
320 template <typename T, typename Subject, typename Modifiers>
321 struct make_directive<
322 terminal_ex<tag::repeat, fusion::vector2<T, T> >, Subject, Modifiers>
323 {
324 typedef finite_iterator<T> iterator_type;
325
326 typedef typename mpl::if_<
327 detail::get_stricttag<Modifiers>
328 , strict_repeat_generator<Subject, iterator_type>
329 , repeat_generator<Subject, iterator_type>
330 >::type result_type;
331
332 template <typename Terminal>
333 result_type operator()(
334 Terminal const& term, Subject const& subject, unused_type) const
335 {
336 return result_type(subject,
337 iterator_type(
338 fusion::at_c<0>(term.args)
339 , fusion::at_c<1>(term.args)
340 )
341 );
342 }
343 };
344
345 template <typename T, typename Subject, typename Modifiers>
346 struct make_directive<
347 terminal_ex<tag::repeat
348 , fusion::vector2<T, inf_type> >, Subject, Modifiers>
349 {
350 typedef infinite_iterator<T> iterator_type;
351
352 typedef typename mpl::if_<
353 detail::get_stricttag<Modifiers>
354 , strict_repeat_generator<Subject, iterator_type>
355 , repeat_generator<Subject, iterator_type>
356 >::type result_type;
357
358 template <typename Terminal>
359 result_type operator()(
360 Terminal const& term, Subject const& subject, unused_type) const
361 {
362 return result_type(subject, fusion::at_c<0>(term.args));
363 }
364 };
365}}}
366
367namespace boost { namespace spirit { namespace traits
368{
369 ///////////////////////////////////////////////////////////////////////////
370 template <typename Subject, typename LoopIter>
371 struct has_semantic_action<karma::repeat_generator<Subject, LoopIter> >
372 : unary_has_semantic_action<Subject> {};
373
374 template <typename Subject, typename LoopIter>
375 struct has_semantic_action<karma::strict_repeat_generator<Subject, LoopIter> >
376 : unary_has_semantic_action<Subject> {};
377
378 ///////////////////////////////////////////////////////////////////////////
379 template <typename Subject, typename LoopIter, typename Attribute
380 , typename Context, typename Iterator>
381 struct handles_container<
382 karma::repeat_generator<Subject, LoopIter>, Attribute
383 , Context, Iterator>
384 : mpl::true_ {};
385
386 template <typename Subject, typename LoopIter, typename Attribute
387 , typename Context, typename Iterator>
388 struct handles_container<
389 karma::strict_repeat_generator<Subject, LoopIter>, Attribute
390 , Context, Iterator>
391 : mpl::true_ {};
392}}}
393
394#endif