]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/spirit/include/boost/spirit/home/karma/operator/kleene.hpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / spirit / include / boost / spirit / home / karma / operator / kleene.hpp
1 // Copyright (c) 2001-2011 Joel de Guzman
2 // Copyright (c) 2001-2011 Hartmut Kaiser
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(BOOST_SPIRIT_KARMA_KLEENE_MAR_03_2007_0337AM)
8 #define BOOST_SPIRIT_KARMA_KLEENE_MAR_03_2007_0337AM
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 #include <boost/type_traits/add_const.hpp>
29
30 namespace boost { namespace spirit
31 {
32 ///////////////////////////////////////////////////////////////////////////
33 // Enablers
34 ///////////////////////////////////////////////////////////////////////////
35 template <>
36 struct use_operator<karma::domain, proto::tag::dereference> // enables *g
37 : mpl::true_ {};
38 }}
39
40 ///////////////////////////////////////////////////////////////////////////////
41 namespace boost { namespace spirit { namespace karma
42 {
43 template <typename Subject, typename Strict, typename Derived>
44 struct base_kleene : unary_generator<Derived>
45 {
46 private:
47 // Ignore return value in relaxed mode (failing subject generators
48 // are just skipped). This allows to selectively generate items in
49 // the provided attribute.
50 template <typename F, typename Attribute>
51 bool generate_subject(F f, Attribute const&, mpl::false_) const
52 {
53 bool r = !f(subject);
54 if (!r && !f.is_at_end())
55 f.next();
56 return true;
57 }
58
59 template <typename F, typename Attribute>
60 bool generate_subject(F f, Attribute const&, mpl::true_) const
61 {
62 return !f(subject);
63 }
64
65 // There is no way to distinguish a failed generator from a
66 // generator to be skipped. We assume the user takes responsibility
67 // for ending the loop if no attribute is specified.
68 template <typename F>
69 bool generate_subject(F f, unused_type, mpl::false_) const
70 {
71 return !f(subject);
72 }
73
74 // template <typename F>
75 // bool generate_subject(F f, unused_type, mpl::true_) const
76 // {
77 // return !f(subject);
78 // }
79
80 public:
81 typedef Subject subject_type;
82 typedef typename subject_type::properties properties;
83
84 // Build a std::vector from the subject's attribute. Note
85 // that build_std_vector may return unused_type if the
86 // subject's attribute is an unused_type.
87 template <typename Context, typename Iterator>
88 struct attribute
89 : traits::build_std_vector<
90 typename traits::attribute_of<Subject, Context, Iterator>::type
91 >
92 {};
93
94 base_kleene(Subject const& subject)
95 : subject(subject) {}
96
97 template <
98 typename OutputIterator, typename Context, typename Delimiter
99 , typename Attribute>
100 bool generate(OutputIterator& sink, Context& ctx
101 , Delimiter const& d, Attribute const& attr) const
102 {
103 typedef detail::fail_function<
104 OutputIterator, Context, Delimiter> fail_function;
105
106 typedef typename traits::container_iterator<
107 typename add_const<Attribute>::type
108 >::type iterator_type;
109
110 typedef
111 typename traits::make_indirect_iterator<iterator_type>::type
112 indirect_iterator_type;
113 typedef detail::pass_container<
114 fail_function, Attribute, indirect_iterator_type, mpl::false_>
115 pass_container;
116
117 iterator_type it = traits::begin(attr);
118 iterator_type end = traits::end(attr);
119
120 pass_container pass(fail_function(sink, ctx, d),
121 indirect_iterator_type(it), indirect_iterator_type(end));
122
123 // kleene fails only if the underlying output fails
124 while (!pass.is_at_end())
125 {
126 if (!generate_subject(pass, attr, Strict()))
127 break;
128 }
129 return detail::sink_is_good(sink);
130 }
131
132 template <typename Context>
133 info what(Context& context) const
134 {
135 return info("kleene", subject.what(context));
136 }
137
138 Subject subject;
139 };
140
141 template <typename Subject>
142 struct kleene
143 : base_kleene<Subject, mpl::false_, kleene<Subject> >
144 {
145 typedef base_kleene<Subject, mpl::false_, kleene> base_kleene_;
146
147 kleene(Subject const& subject)
148 : base_kleene_(subject) {}
149 };
150
151 template <typename Subject>
152 struct strict_kleene
153 : base_kleene<Subject, mpl::true_, strict_kleene<Subject> >
154 {
155 typedef base_kleene<Subject, mpl::true_, strict_kleene> base_kleene_;
156
157 strict_kleene(Subject const& subject)
158 : base_kleene_(subject) {}
159 };
160
161 ///////////////////////////////////////////////////////////////////////////
162 // Generator generators: make_xxx function (objects)
163 ///////////////////////////////////////////////////////////////////////////
164 namespace detail
165 {
166 template <typename Subject, bool strict_mode = false>
167 struct make_kleene
168 : make_unary_composite<Subject, kleene>
169 {};
170
171 template <typename Subject>
172 struct make_kleene<Subject, true>
173 : make_unary_composite<Subject, strict_kleene>
174 {};
175 }
176
177 template <typename Subject, typename Modifiers>
178 struct make_composite<proto::tag::dereference, Subject, Modifiers>
179 : detail::make_kleene<Subject, detail::get_stricttag<Modifiers>::value>
180 {};
181 }}}
182
183 namespace boost { namespace spirit { namespace traits
184 {
185 ///////////////////////////////////////////////////////////////////////////
186 template <typename Subject>
187 struct has_semantic_action<karma::kleene<Subject> >
188 : unary_has_semantic_action<Subject> {};
189
190 template <typename Subject>
191 struct has_semantic_action<karma::strict_kleene<Subject> >
192 : unary_has_semantic_action<Subject> {};
193
194 ///////////////////////////////////////////////////////////////////////////
195 template <typename Subject, typename Attribute, typename Context
196 , typename Iterator>
197 struct handles_container<karma::kleene<Subject>, Attribute
198 , Context, Iterator>
199 : mpl::true_ {};
200
201 template <typename Subject, typename Attribute, typename Context
202 , typename Iterator>
203 struct handles_container<karma::strict_kleene<Subject>, Attribute
204 , Context, Iterator>
205 : mpl::true_ {};
206 }}}
207
208 #endif